How to setup WP posts as Subdomains

Setting up WP posts as subdomains is not as easy task. In fact it is quite possible one of the most misunderstood tasks in WordPress. Many people confuse having WP posts as subdomains to building a multisite WordPress install. In multisite configuration you can have a structure like this:

site1_name.url/site1_post1/
site1_name.url/site1_post2/
site2_name.url/site2_post1/
site2_name.url/site2_post2/

etc., when we actually look to accomplish something like:

post1.site_url/
post2.site_url/
etc.

Don’t flush rewrite rules on init

Let’s show an old way to take care of our task. An old and very wrong way actually. Many plugins found in the WordPress repository that deal with subdomains tend to use a little hack. They rewrite the rules for the current page on every page load by hooking into the init action. First they manage to get the subdomain part of the url and then they add a rewrite rule for the current page to index.php, something like: $rules["$"] = "index.php?p=" . $this->slug;.

However this approach is wrong in every way. According to the codex flushing the rewrite rules on init action is bad practice. Not only that flushing the rewrite rules is an expensive operation, but when more pages load at the same time you may end up with the contents of a different page as the rules don’t flush fast enough. For example imagine trying to access a post and getting the index page even though you accessed the proper url. Bad for the end user and especially bad when search engines index the wrong page.

The proper way to setup your posts as subdomains

The next steps must be followed to the teeth. If you skip any of them you will end up with various issues, each explained further down. You will need to be able to edit your DNS configuration as well as modify your Apache or Nginx config files. It is best to set your site into maintenance mode while you navigate yourself through the list.

1. Use Post name as Permalinks

This is not we expect to end up with, but merely a prerequisite to our goal. Go to your WP admin > Settings > Permalinks and check the ‘Post name’ option.

2. Add a wildcard DNS record

It is obvious without the wildcard DNS any post.sitename.extension url can not be reached. So go to your hosting account and add an ‘A’ record, choosing ‘*’ as host name and pointing it to your ip. The new line in your domain’s zone file should look something like: * A 198.58.110.151

3. Edit .htaccess / nginx.conf

Next we need to tell our HTTP server (Apache, Nginx) what to do when a subdomain is accessed by modifying its config. These modifications depend entirely on your current setup, so you may need to tweak them a little to suit your needs. For Apache add something like this to your .htaccess file:

RewriteCond %{HTTP_HOST} !^www\.sitename\.extension$ [NC]
RewriteCond %{HTTP_HOST} ^(.*)\.sitename\.extension$ [NC]
RewriteRule ^$ index.php?p=%1 [NC,QSA,L]

For Nginx in your sitename.extension.conf file add another server block, identical to the main one already present. Within the new server block delete the index directive if present (the index index.php index.html index.htm; line) and change the server_name to

server_name ~^(www\.)?(?.+)\.sitename\.extension$

Obviously change sitename.extension to your own url, but keep subdomain unchanged. Lastly modify your Location block for / into:

location / {
rewrite ^(.*)/$ /index.php?$args last;
}

4. Edit class-wp.php

Now that we edited our DNS and HTTP server file, all our pages can be accessed. However we still need to change the way WordPress processes our request. We need to force it to run the correct WordPress query by tweaking the ‘parse_request’ function in the ‘WP’ class. Open your wp-includes/class-wp.php and find the line: $req_uri = str_replace($pathinfo, '', $req_uri);. Add this after it:

$pieces = explode( '.', $_SERVER['HTTP_HOST'] );
$subdomain = array_shift( $pieces );
if( strcasecmp( $subdomain, "www" ) != 0 && strcasecmp( $req_uri, "/" ) == 0 ) $req_uri = $subdomain;

Now all our post.sitename.extension pages display the proper content. However there’s still one more thing left to do: get the right permalink. If you look at your page’s source you will notice the canonical link is still site.extension/postname/. We will fix that next.

5. Add a plugin to fix the permalink

Add the following plugin to get the correct permalink for a subdomain based structure.

<?php
/**
* Setup wp posts as subdomains
*
* @package sbd
* @author theWPinfo
*
* @wordpress-plugin
* Plugin Name: Posts as subdomains by theWPinfo
* Plugin URI: http://www.thewp.info/how-setup-wp-posts-subdomains/
* Description: Easy way to setup your wordpress posts as subdomains, change http://www.site_url/post_name/ to http://post_name.site_url/
* Version: 1.0
* Author: theWPinfo
* Author URI: http://www.thewp.info/
**/

add_action( 'plugins_loaded', 'sbd_activation' );

function sbd_activation() {
add_filter( 'post_link', 'sbd_post_link', 10, 3 );
}

function sbd_post_link( $permalink, $post, $leavename = false ) {
if( $post->post_type != 'post' ) return $permalink;
if( stripos( $permalink, '?p=' ) !== false ) return $permalink;
$permalink = trim( $permalink, '/' );
$location = strripos( $permalink, '/' );
$url = substr( $permalink, $location + 1 );
$permalink = substr( $permalink, 0, $location + 1 );
$permalink = str_replace( '://www.', '://', $permalink );
$permalink = str_replace( '://', '://' . $url . '.' , $permalink );
return $permalink;
}

You can download a zipped-version of the plugin here.

It may look as if we are done, however there is one more step to do.

6. Disable auto-updates

We need to disable the auto-updates because on each core update the class-wp.php file will get updated. Even though not on the list of files changed, class-wp.php is checked for integrity and if it does not match the one in the update, it gets overwritten. Left without the code in point 4, our whole site structure crumbles making our pages unreachable. So we really need to get rid of all auto-updates.

Open your wp-config.php file and add the following line define( 'AUTOMATIC_UPDATER_DISABLED', true ); at top of it.

How to manual update your site if auto-updates are disabled

Disabling auto-updates is a bit of a pita. Make sure to check for WP updates regularly and manual update as soon as possible. Since you may lose sight of the updates or maybe go on vacation without the means to manually update, it is recommended to keep your site’s security really tight to mitigate 0-day attacks.

The steps to manually update your site after choosing our method for subdomain-based WordPress structure are the following:

  1. Enter your site into maintenance mode
  2. Go to WP admin > Dashboard > Updates and update everything
  3. Redo the editing of class-wp.php described above at point 4
  4. Disable maintenance mode

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *