WordPress: how to remove unwanted code from your site’s header

Ross Hall

July 15, 2021
(Updated on July 27, 2021)

Illustration of a laptop placed on an engineering size reduction symbol with lines showing data deflected away from a red circle

When WordPress generates a webpage, it adds a lot of information unseen by the user. Much of this appears between the <head> tags in the code, and asks the browser to interpret information in a certain way, or load additional files and resources. While some of these are useful (such as style.css, which turns raw words into a stylish website), others are not. Some could compromise the security of your site.

Each resource that’s requested slows your website a little. It makes sense to remove anything your theme or site doesn’t use, even if all it does is shave a third of a second off the loading time.

In this guide I’ve outlined the resources I’ve suppressed from this site, and the code I’ve used. You can include the code either in your functions.php file or your own plugin. It’ll get updated from time to time as WordPress develops, which I’ll flag in my periodic email.

Contents

First, some basics

For much of what follows I’m using a function called “remove_action“. If you know how this works, you can skip this section.

When WordPress assembles a page, it triggers various “actions” to bring together its different parts. Developers create functions, then “hook” them to the action so when the action happens, their function runs. The action “wp_head” handles much of what you see in the <head> on your site.

Just as we can add a function to an action, so we can take it away. That’s what remove_action does. It takes three parameters: the name of the action, the function we want to remove and a priority.

To remove something from our header, we need a single line of code:

remove_action('wp_head','something_to_remove',10);

This goes into your site plugin or functions.php file outside of any functions, although you can wrap it in logic. For example, you might only want to load the emoticons when someone has edit rights. The priority is usually set to a high number to ensure you trigger remove_action after add_action. Otherwise it has no effect.

A word of caution

Functions are linked to specific actions. You must have the same combination of action and function as used to connect them together. If you don’t, WordPress ignores your instruction.

How to remove emoticons

The lowest hanging fruit is emoticon support. If you’re not accepting comments or don’t want smiley faces plastered across web pages, you can remove these.

There are two parts to this: an embedded set of styles, and embedded JavaScript. Both have to be removed.

remove_action('wp_head', 'print_emoji_detection_script',10);
remove_action('wp_print_styles', 'print_emoji_styles',10);

Disable the REST API

The REST API lets external apps access the content on your site, either to update show it. An example could be if you have a mobile app that lets people buy from your Woocommerce site.

From a security standpoint, it’s a good idea to switch it off if you’re not using REST. Remember some plugin and theme developers use it, which may stop functionality from working. If this happens, you can either select a different product, or switch it on.

remove_action('wp_head', 'rest_output_link_wp_head',10);

For Gutenberg users

WordPress lets you manage your content using tools other than Gutenberg. These work through two interfaces called RSD and WLW. If you’re only using Gutenberg you can remove both.

remove_action('wp_head', 'rsd_link',10);
remove_action('wp_head', 'wlwmanifest_link',10);

Canonical and short links

These are two pieces of information used by search engines. A “canonical link” tells a search engine which URL is the preferred one when indexing the page. This is useful if the page is a duplicate, or can be accessed through different URLs. SEO plugins will usually override this functionality, so you can leave it in place. If you want to remove it, use the following code:

remove_action('wp_head', 'rel_canonical',10);

Short links are abbreviated URLs which used to be easier to share in emails or on social networks when text length was a constraint. For example, the URL to this page is <URL>, but you can also access it through <URL?id=>. I prefer to remove this.

remove_action('wp_head', 'wp_shortlink_wp_head',10);

Block embedding your content

Oembed is an open standard that embeds your content into another website. If you’ve pasted a link to Twitter in a post and seen the Tweet appear, that’s Oembed at work.

Screenshot of a tweet from rossahall embedded in a post
Example screenshot of a Tweet embedded in a post.

WordPress allows other people to embed your content in their sites using the same method. However, few sites use this feature, and many have restrictions in place that may even block your content from being embedded.

Disable Oembed for your site using this code.

remove_action('wp_head', 'wp_oembed_add_discovery_links',10);
remove_action('wp_head', 'wp_oembed_add_host_js',10);

Note: this doesn’t stop you from embedding Tweets, YouTube videos etc in your content.

Disable RSS feeds

RSS feeds are a simple way of showing users what content is available on your site. Depending on their software, they might also flag when new content is available. However, they lose all the styling and branding you’ve created, may not show images, and it isn’t used widely.

I’ve disabled RSS feeds on my site using this code:

remove_action('wp_head', 'feed_links',10);
remove_action('wp_head', 'feed_links_extra',10);

Remove prefetching

Prefetching is a technique to speed up browsing when the user clicks on a link. When your page loads, the web browser looks at the links and finds the IP address of the domain. It cuts a second or two out of the delay between clicking a link and the page loading. There are some issues with this approach, not least domains inside scripts might be missed.

WordPress explicitly asks the browser to prefetch specific domains in the “dns-prefetch” tag in <HEAD>. Most of the time the only domain declared is s.w.org – the WordPress.org domain.

Remove it with this code:

remove_action('wp_head', 'wp_resource_hints',10);

Hide the WordPress version number

WordPress likes to broadcast which version you’re running. This can be a security issue, and it’s a good idea to suppress this information.

remove_action('wp_head', 'wp_generator',10);

Remove backward capability for JQuery

As JQuery develops, so it leaves a trail of legacy code that may not work correctly. To prevent this from crashing your site, WordPress loads a library called JQuery.migrate. As long as you’re keeping WordPress, and its themes and plugins, up to date you shouldn’t need it.

Disabling it requires more complicated code than seen previously as it has to be cleaned out of WordPress completely. The following code works on my sites, and was contributed by Pascal Birchler.

function dequeue_jquery_migrate( $scripts ) {
    if ( ! is_admin() && ! empty( $scripts->registered['jquery'] ) ) {
        $scripts->registered['jquery']->deps = array_diff(
            $scripts->registered['jquery']->deps,
            [ 'jquery-migrate' ]
        );
    }
}
add_action( 'wp_default_scripts', 'dequeue_jquery_migrate' );

Older WordPress

The following code removes various links to posts in <head>. If your version of WordPress is newer than 4.0 you can ignore these.

remove_action('wp_head', 'start_post_rel_link',10);
remove_action('wp_head', 'index_rel_link',10);

Robots

WordPress defines a default “robots” meta tag which is applied to every page. If you want to be more nuanced and create your own robots tag, use the following to remove the default. You can also use it if you’ve installed an SEO Plugin that’s left duplicate robots tags in your code.

remove_action( 'wp_head', 'wp_robots', 1 );

Adding some logic

Removing functionality from WordPress, particularly in admin, carries the risk you’ll break something. I suggest you wrap these instructions in some logic that disables them on the public facing website. This leaves them active in the administration screens.

To do this, use:

if ( !is_admin() ) :
// All the commands
endif;

Last words

The more plugins and blocks you add to your site, the more resources your web pages will demand. Each new .css or .js file is another file to download and a slight slowing of your site. This will impact both SEO and the usability of your site.

You can limit the damage to some extent by removing anything you don’t need from your headers. What I’ve outlined is the basics that work on my site.

I'm Ross Hall, a writer and researcher based in Kobe, Japan. You can talk to me about B2B, sustainability and strategic management.

Like what you read? Sign up for my weekly(ish) missive, delivered straight to your inbox.