How To Change The WordPress Post Template Via URL Parameter
July 27th, 2011 by Stephen Cronin (Please wait) [Shortlink]Have you ever wanted to be able to serve up an alternative version of your posts, perhaps tweaking the layout or even the content of the posts? Not all the time, just in certain circumstances?
I’ve had two cases recently where I’ve needed to do this. My solution: to change the post template when a certain URL parameter is added to the URL.
When this technique is implemented, a user going to:
http://domain.com/postname/
will get the normal post in the normal template. A user going to
http://domain.com/postname/?template=basic
will be presented the post in an alternative layout or even with altered content.
To make what we’re trying to achieve clear, let me first outline my two use cases. After that, I’ll show you how to achieve this by a) serving up a different post template based on a URL parameter and b) creating the custom post template.
Use Case 1: Removing Headers, Footers And Sidebars
For one project I’m working on, I needed to serve up the post content only. Everything else, including the header, footer and the sidebars needed to be stripped out. I needed this ‘post content only’ version to be always available, for every post, but for the original fully styled posts to be available as well.
Here are some screenshots from my local development environment to demonstrate what I want to achieve. The full post lives at http://localhost/wprs-support/mark-webber/ and displays normally:
When ?template=basic is appended to the URL (ie http://localhost/wprs-support/mark-webber/?template=basic), the custom post template is triggered and just the content is displayed:
Why do I want to do this? I’ll be pulling in the content into another page, probably via an Ajax call (or possibly through an iFrame). I don’t need the headers, sidebars etc as they will already be displayed on the page I’m pulling the content into. It’s not possible to only pull in a section of a page in an iFrame or via Ajax, so I need to strip that stuff out.
Use Case 2: Changing Content
I’m the lead developer (but not the owner) of the WP Review Site plugin. I recently had a customer asking to get the average rating for a particular post, so they could display it in a banner on another site via an iFrame. There are other ways to achieve this, but the simplest is to use the URL Parameter and post template combination to serve up just the average rating, as follows:
The URL used here is the same as the one for the ‘post content only’ version shown above, but I’ve swapped out the custom post template. Rather than just stripping out the header, sidebar and footer, it’s actually serving up different content: the average rating for the post, instead of the post content.
How To Serve Up A Different Template
It’s reasonably easy to use a custom post template when a certain URL parameter is detected.
First we need to let WordPress know about the URL parameter so we can detect it later. We do this by adding the following code to your theme’s functions.php file:
function sjc_add_query_vars($vars) {
return array('template') + $vars;
}
add_filter('query_vars', 'sjc_add_query_vars');
We use the query_vars filter (line 4) to call a function (line 1) that returns the existing array of query vars with our new one added on the front (line 2). I’ve used ‘template’ as the URL parameter and have continued to use that below, but you can use what ever you want (as long as it’s not one that’s commonly used already).
http://domain.com/postname/template/basic/ instead of http://domain.com/postname/?template=basicNext, we check for the existence of the URL parameter / query_var, by adding the following code to your theme’s functions.php file (below the code given above):
function sjc_template($template) {
global $wp;
if ($wp->query_vars['template']=='basic') {
return dirname( __FILE__ ) . '/single-basic.php';
}
else {
return $template;
}
}
add_filter('single_template', 'sjc_template');
We use the single_template filter (line 10) to call a function called sjc_template (line 1). This function checks if the URL parameter is set (line 3) and, if so, returns the path to the single-basic.php template file (line 4). If the URL parameter doesn’t exist, the default template is returned unchanged (line 7).
Once again, I’ve used single-basic.php, but you can call this file whatever you want – as long as you are consistent with the name when creating the template file below.
Disclaimer: The above code will fail if the single-basic.php file(or whatever you’ve called it) doesn’t exist. We should probably use file_exists to check it’s there and error out nicely if not. I’d do that if I was publically releasing a theme or plugin or doing client work, but haven’t bothered in this case.
How To Create The Custom Post Template
Once we’ve told WordPress to use a custom post template instead of single.php, we need to create that custom post template.
In your theme folder you need to create a file called single-basic.php (you can call this whatever you want, as long as it matches the file name requested in the previous step).
What’s in this file? Whatever you want to tweak the post. For my ‘post content only’ format shown above, I used the following:
<div id="content"> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2 class="item"><span class="fn"><?php the_title(); ?></span></h2> <?php the_content(); ?> <?php endwhile; else: ?> <?php endif; ?> </div>
Note: this just creates part of the page. It doesn’t have html, head or body tags. That’s probably no good if you want people to actually visit this page in the browser, but in my case it’s primarily for me to pull the content in to be displayed in a page that already has a html, head and body tags. It’s better for me to have it ready to go.
If you need to have a full HTML page, simply add the tags to single-basic.php. You can probably get the basic code from your header.php file, leaving out the extra lines that aren’t necessary. You could even link to a custom CSS file if you just want to make style changes, although there is a better way to do that (without using custom post templates).
<meta name="robots" content="noindex"> to the head of the page (if you have that section) or to exclude pages with this paramters in robots.txt.For my ratings only example from above, my single-basic.php file contains the following:
<?php
if (function_exists('get_average_rating')) {
global $post;
echo round_to_half(get_average_rating($post->ID));
} ?>
I don’t need the post content. I just need the average rating, which I’m getting through the WP Review Site API. This will return a plain number, not wrapped in any HTML. Once again, if a full HTML page is required, you need to add the appropriate tags to the template file.
Final Thoughts
This technique has served me well on a number of occasions. It provides the flexibility to serve up altered content / layout for your posts, through the power of custom post templates.
Have you ever done something similar? If so, how did you do it?
Tags: layout, post templates, WordPress

