How To Clean Up WordPress Head Code

WordPress does a lot of things for us automatically. However, because it tries to be all things to all people, there are a few bits of code in the header that I always take out.

Reducing the code can speed up the site and make it easier for a developer to see what's actually important on your site, for debugging etc.

There are three groups of things we'll be taking out today:

If you don't care about the explanations and just want the code, here it is:

// Remove Feed Links
remove_action('wp_head', 'feed_links_extra', 3);
remove_action('wp_head', 'feed_links', 2);

// Remove Smilies
add_filter( 'emoji_svg_url', '__return_false');
remove_filter('comment_text', 'convert_smilies', 20);
remove_filter('the_excerpt', 'convert_smilies');
remove_filter('the_content', 'convert_smilies');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('admin_print_styles', 'print_emoji_styles');
remove_action('init', 'smilies_init', 5);

// Remove Unneccessary Header Code
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10);
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wp_shortlink_wp_head', 10);
remove_action('wp_head', 'wp_oembed_add_discovery_links');

Copy that, paste it into the functions.php file of your child theme. If you don't have one yet, go through our tutorial on creating a WordPress child theme here.

That's all you need to do to clean up the header.

None of these changes are permanent, so as soon as you remove the code from functions.php, the lines will return.

We'll end up with a header that looks like this:

Please note I truncated the inline style in this image, for clarity.

Read on for a more detailed explanation on how to clean up the WordPress header.

Different pages will have different feed links on them.

These used to be a lot more useful for blogs, back when people would use feed readers and subscribe to blogs.

Now they're just legacy and don't really belong on your website.

The feed links on a blog page look like this:

There is a general website feed, one for website comments and one for the comments on this page.

In case it's hard to read, the feed code output is:

<link rel="alternate" type="application/rss+xml" title="Intelliwolf Example Site &raquo; Feed" href="http://localhost/demo/feed/" />
<link rel="alternate" type="application/rss+xml" title="Intelliwolf Example Site &raquo; Comments Feed" href="http://localhost/demo/comments/feed/" />
<link rel="alternate" type="application/rss+xml" title="Intelliwolf Example Site &raquo; Next Post Comments Feed" href="http://localhost/demo/2019/12/05/next-post/feed/" />

We can get rid of that in two lines (because the first is a comment):

// Remove Feed Links
remove_action('wp_head', 'feed_links_extra', 3);
remove_action('wp_head', 'feed_links', 2);

Copy those lines into the functions.php file of your Child Theme.

How to remove WordPress Emoji code

The WordPress Emoji code, also known as WordPress Smilies, is one of my bugbears.

For such limited functionality (it literally just recognizes and displays emojis), it brings in a whole lot of JavaScript and CSS.

It looks like this:

If you want to see the code in text, this is everything that's thrown in there, willy-nilly:

<link rel='dns-prefetch' href='//s.w.org' />
<script type="text/javascript">
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/12.0.0-1\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/12.0.0-1\/svg\/","svgExt":".svg","source":{"concatemoji":"http:\/\/localhost\/demo\/wp-includes\/js\/wp-emoji-release.min.js?ver=5.3"}};
!function(e,a,t){var r,n,o,i,p=a.createElement("canvas"),s=p.getContext&&p.getContext("2d");function c(e,t){var a=String.fromCharCode;s.clearRect(0,0,p.width,p.height),s.fillText(a.apply(this,e),0,0);var r=p.toDataURL();return s.clearRect(0,0,p.width,p.height),s.fillText(a.apply(this,t),0,0),r===p.toDataURL()}function l(e){if(!s||!s.fillText)return!1;switch(s.textBaseline="top",s.font="600 32px Arial",e){case"flag":return!c([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])&&(!c([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!c([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]));case"emoji":return!c([55357,56424,55356,57342,8205,55358,56605,8205,55357,56424,55356,57340],[55357,56424,55356,57342,8203,55358,56605,8203,55357,56424,55356,57340])}return!1}function d(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(i=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},o=0;o<i.length;o++)t.supports[i[o]]=l(i[o]),t.supports.everything=t.supports.everything&&t.supports[i[o]],"flag"!==i[o]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[i[o]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(r=t.source||{}).concatemoji?d(r.concatemoji):r.wpemoji&&r.twemoji&&(d(r.twemoji),d(r.wpemoji)))}(window,document,window._wpemojiSettings);
</script>
<style type="text/css">
img.wp-smiley,
img.emoji {
  display: inline !important;
  border: none !important;
  box-shadow: none !important;
  height: 1em !important;
  width: 1em !important;
  margin: 0 .07em !important;
  vertical-align: -0.1em !important;
  background: none !important;
  padding: 0 !important;
}
</style>

Yikes. Let's get rid of that.

Put this code into the functions.php file of your Child Theme.

// Remove Smilies
add_filter( 'emoji_svg_url', '__return_false');
remove_filter('comment_text', 'convert_smilies', 20);
remove_filter('the_excerpt', 'convert_smilies');
remove_filter('the_content', 'convert_smilies');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('admin_print_styles', 'print_emoji_styles');
remove_action('init', 'smilies_init', 5);

This is what that same section of the head looks like, without the emojis scripts:

Ah. Much better.

How to remove the remaining WordPress Header code

There are a number of other, miscellaneous items that WordPress brings into the header.

The ones I'm talking about here look like this:

The code we'll be removing looks like this:

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://localhost/demo/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://localhost/demo/wp-includes/wlwmanifest.xml" /> 
<link rel='prev' title='Hello world!' href='http://localhost/demo/2019/12/04/hello-world/' />
<link rel='next' title='Last Post' href='http://localhost/demo/2019/12/06/last-post/' />
<meta name="generator" content="WordPress 5.3" />
<link rel='shortlink' href='http://localhost/demo/?p=8' />
<link rel="alternate" type="application/json+oembed" href="http://localhost/demo/wp-json/oembed/1.0/embed?url=http%3A%2F%2Flocalhost%2Fdemo%2F2019%2F12%2F05%2Fnext-post%2F" />
<link rel="alternate" type="text/xml+oembed" href="http://localhost/demo/wp-json/oembed/1.0/embed?url=http%3A%2F%2Flocalhost%2Fdemo%2F2019%2F12%2F05%2Fnext-post%2F&#038;format=xml" />

To do it in one fell swoop, add this code to the functions.php file of your Child Theme, or read on to match each to an action:

// Remove Unneccessary Header Code
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10);
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wp_shortlink_wp_head', 10);
remove_action('wp_head', 'wp_oembed_add_discovery_links');

"RSD" stands for "Really Simple Discovery". You might need to keep this line if you're using a remote service to post content to your website. If you're not doing that, you don't need this line.

To remove the line:

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://localhost/demo/xmlrpc.php?rsd" />

Add this code to functions.php.

remove_action('wp_head', 'rsd_link');

How to remove the WLW Manifest Link

This line is only used by the Windows Live Writer application. If you're not using that, there's no reason to keep this line. To remove the line:

<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://localhost/demo/wp-includes/wlwmanifest.xml" /> 

Add this code to functions.php.

remove_action('wp_head', 'wlwmanifest_link');

How to remove the Previous and Next Links

If you're running a gallery-heavy website, you might want to keep these lines to allow for preloading. Otherwise, you can get rid of them. To remove these lines:

<link rel='prev' title='Hello world!' href='http://localhost/demo/2019/12/04/hello-world/' />
<link rel='next' title='Last Post' href='http://localhost/demo/2019/12/06/last-post/' />

Add this code to functions.php.

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

How to remove WordPress Generator meta link

If your WordPress site hasn't been updated in awhile, this line is a shining beacon to any hackers as to what exploits they should use. To remove the line containing the WordPress version:

<meta name="generator" content="WordPress 5.3" />

Add this code to functions.php.

remove_action('wp_head', 'wp_generator');

I've never understood what the purpose of the shortlink is supposed to be. To remove this line:

<link rel='shortlink' href='http://localhost/demo/?p=8' />

Add this code to functions.php.

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

How to remove the WordPress JSON Oembed Lines

These lines allow other websites to do that nice looking WordPress embed. But I don't see a scenario where I want my website embedded in another.

To remove these lines:

<link rel="alternate" type="application/json+oembed" href="http://localhost/demo/wp-json/oembed/1.0/embed?url=http%3A%2F%2Flocalhost%2Fdemo%2F2019%2F12%2F05%2Fnext-post%2F" />
<link rel="alternate" type="text/xml+oembed" href="http://localhost/demo/wp-json/oembed/1.0/embed?url=http%3A%2F%2Flocalhost%2Fdemo%2F2019%2F12%2F05%2Fnext-post%2F&#038;format=xml" />

Add this code to functions.php.

remove_action('wp_head', 'wp_oembed_add_discovery_links');

That's all there is to it.

After you've made the changes to functions.php, make sure to clear any caches, then reload your page to check everything's still working properly.

If you notice any missing functionality that you want back, just go through this post again and see what you removed.

Leave a Comment