How to Hide The Fact That You’re Using WordPress

This post contains information on how to clean up WordPress code output. The methods described below do not prevent actual fingerprinting and shouldn’t be looked at as any sort of security measure.

In the Roots Theme we’re taking several steps to help make it not so obvious that you’re using WordPress:

  1. Cleaning up the output of wp_head and removing the generator from RSS feeds
  2. Hiding /wp-content/ by rewriting static theme assets (CSS, JS, images), rewriting the plugins directory, and also changing the location of WordPress uploads
  3. Cleaning up the output of navigation menus with a custom walker
  4. Bonus: root relative URLs

Clean Up wp_head

You’re probably used to viewing the source of your WordPress site and seeing some not-so-pretty code:

<!DOCTYPE html>
<!--[if IE 6]>
<html id="ie6" dir="ltr" lang="en-US">
<![endif]-->
<!--[if IE 7]>
<html id="ie7" dir="ltr" lang="en-US">
<![endif]-->
<!--[if IE 8]>
<html id="ie8" dir="ltr" lang="en-US">
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8)  ]><!-->
<html dir="ltr" lang="en-US">
<!--<![endif]-->
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Example Site | Just another WordPress site</title>
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" media="all" href="http://example.com/wp-content/themes/twentyeleven/style.css" />
<link rel="pingback" href="http://example.com/xmlrpc.php" />
<!--[if lt IE 9]>
<script src="http://example.com/wp-content/themes/twentyeleven/js/html5.js" type="text/javascript"></script>
<![endif]-->
<link rel="alternate" type="application/rss+xml" title="Example Site » Feed" href="http://example.com/feed/" />
<link rel="alternate" type="application/rss+xml" title="Example Site » Comments Feed" href="http://example.com/comments/feed/" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://example.com/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://example.com/wp-includes/wlwmanifest.xml" />
<meta name="generator" content="WordPress 3.4.2" />
  <style type="text/css">.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style>
</head>

WordPress’s tagline is “Code is Poetry” but usually after taking a quick look at the output of the default theme you might think otherwise. It’s probably much worse once you’ve activated some plugins which likely enqueue CSS and scripts all over the place.

If you look at the output of a default Roots theme setup then you’re going to be looking at almost an exact match of HTML5 Boilerplate’s:

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <title>Example Site</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <script src="/assets/js/vendor/modernizr-2.6.2.min.js"></script>

  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
  <script>window.jQuery || document.write('<script src="/assets/js/vendor/jquery-1.8.2.min.js"><\/script>')</script>

  <link rel="stylesheet" href="/assets/css/bootstrap.css">
  <link rel="stylesheet" href="/assets/css/bootstrap-responsive.css">
  <link rel="stylesheet" href="/assets/css/app.css">
  <script type='text/javascript' src='/assets/js/plugins.js'></script>
  <script type='text/javascript' src='/assets/js/main.js'></script>
  <link rel="canonical" href="http://example.com/">

  <link rel="alternate" type="application/rss+xml" title="Example Site Feed" href="http://example.com/feed/">
</head>

Here’s what we do to clean up wp_head:

Remove Unnecessary Functions

<?php
function roots_head_cleanup() {
  remove_action('wp_head', 'feed_links', 2);
  remove_action('wp_head', 'feed_links_extra', 3);
  remove_action('wp_head', 'rsd_link');
  remove_action('wp_head', 'wlwmanifest_link');
  remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);
  remove_action('wp_head', 'wp_generator');
  remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0);

  global $wp_widget_factory;
  remove_action('wp_head', array($wp_widget_factory->widgets['WP_Widget_Recent_Comments'], 'recent_comments_style'));

  add_filter('use_default_gallery_style', '__return_null');
}
add_action('init', 'roots_head_cleanup');
?>

Hide /wp-content/

Hiding the wp-content directory makes your source code look more elegant. You can setup rewrites for your static theme assets and plugins directory and change the default location of WordPress uploads.

Rewrites

Want to rewrite your static theme assets and the plugins directory? Refer to the latest Roots rewrites.php file for implementation.

WordPress Uploads

Default WordPress settings will have all of your uploads going into /wp-content/uploads/ and also organized by date which can be changed in the admin under Settings > Media.

In Roots we’re using a directory in the root of your WordPress install called /assets/ without the date organization by default.

Navigation Menus

Want to clean up the output of the default WordPress navigation menu? Refer to the latest Roots nav.php file for the cleaner nav walker.

Root Relative URLs

Refer to the latest Roots cleanup.php file for root relative URLs functionality.

Huge thanks to Scott Walkinshaw for contributing many of the code examples above and to all of the other Roots contributors.

Follow Roots development on GitHub