Using a Different Wordpress Theme on a Subdomain

(2013)

A situation I've encountered twice now is the need to serve a site's content from a subdomain using a different Wordpress Theme. In the first case, the subdomain was a mobile site and the alternate theme was optimized for mobile with a simplified layout and fewer images. In the second case, the subdomain was created after a major redesign so that the new theme and old theme could run side-by-side for a few weeks as a trial period. There are plugins that can handle this, but it's pretty easy and more tweakable if you set it up yourself.

Basically, you setup your subdomain as a CNAME pointing to the original domain. Then, detect whether or not your visitor is on the subdomain by looking at $_SERVER['SERVER_NAME']. Finally, you use 3 Wordpress filters to hijack the theme when appropriate.

One tricky bit: all links on the subdomain will still point to the regular domain because of the site_url setting. You probably don't want that and there are several ways to fix it. In the code below, I've used PHP's output buffering trick to rewrite all the URLs with one big str_replace, but that may not be appropriate in every situation. I've also made liberal use of globals to focus on the important bits and keep the code as short as possible, but in practice, you'll probably want to wrap this up in a class or perhaps some configurable options.

// in functions.php

// regular site url
$my_url = 'http://mysite.com';

// subdomain you want a different theme on
$my_sub_url = 'http://sub.mysite.com';

// subdomain prefix, used to test whether primary or subdomain
$my_prefix = 'sub.';

// folder name of theme to use instead on subdomain
$my_theme_name = 'my_mobile_theme';

// these 3 filters swap out the theme
add_filter( 'template'          , 'my_change_theme' );
add_filter( 'option_template'   , 'my_change_theme' );
add_filter( 'option_stylesheet' , 'my_change_theme' );

// these 2 actions rewrite all urls in the body
// from http://domain.com to http://sub.domain.com
add_action( 'wp_head'           , 'my_buffer_start' );
add_action( 'wp_footer'         , 'my_buffer_end' );

// TRUE, if this is the subdomain, false otherwise
public function my_is_subdomain() {
    global $my_prefix;
    if( strpos( $_SERVER['SERVER_NAME'], $my_prefix ) !== FALSE ) {
        return TRUE;
    }
    return FALSE;
}

// if this is the subdomain, return new theme
// otherwise, return original theme
public function my_change_theme( $theme ) {
    global $my_theme_name;
    if( my_is_subdomain() ) {
        return $my_theme_name;
    }
    return $theme;
}

public function my_buffer_start() {
    ob_start('my_buffer_cb');
}

public function my_buffer_end() {
    ob_end_flush();
}

// replace primary url with subdomain url in body
// so that all links keep user on the subdomain
public function my_buffer_cb( $buffer ) {
    global $my__url, $my_sub_url;
    if( ! my_is_subdomain() ) {
        return $buffer;
    }

    // replace http://mysite.com with http://sub.mysite.com
    $buffer = str_replace( $my_url, $my_sub_url, $buffer);

    // !!! NOTE - you may not want to replace EVERY instance
    // for example, you may want to keep social media urls
    // intact, or rel="canonical", or links specifically
    // designed to switch between the primary and subdomain

    return $buffer;
}

And.. that's it.

Of course you'll need 2 themes and a subdomain setup for this to work. This code would go in the functions.php of the primary theme.

References