PMG Digital Made for Humans

Using jQuery PJAX in Your WordPress Themes

5 MINUTE READ | February 28, 2012

Using jQuery PJAX in Your WordPress Themes

Author's headshot

Christopher Davis

Christopher Davis has written this article. More details coming soon.

PJAX is a jQuery extension that combines AJAX requests to HTML5 pushState. What this means is an AJAX website with a working back button. Think Twitter without ugly hash bangs (#!) in the URL**.

What AJAX, and by extension PJAX, does is allow for partial page reloads. The result is a much faster page load time – the browser doesn’t have to re-render the entire page. You can use PJAX out of the box in your WordPress theme, just specify which container is to be extracted from a full page request and the PJAX library extracts it and pops it into the page where you want it.

We’re going to go a bit beyond that here. Instead, we’ll hijack WordPress’ template system and include partial pages instead of complete pages – less stuff to send on every page load.

For this example, we’re going to create a Twenty Eleven Child Theme.

Using PJAX is very easy, and you can take a look at the docs to learn more. The JavaScript side of this tutorial is pretty unexciting.

jQuery(document).ready(function() {


jQuery('#main').bind('pjax:end', function(){

if(typeof(pjaxy_page_info) != 'undefined') {

jQuery('body').attr('class', pjaxy_page_info.body_class);

jQuery('head title').html(pjaxy_page_info.page_title);

if(pjaxy_page_info.header_img) {

jQuery('header#branding > a img').attr('src', pjaxy_page_info.header_img)

.attr('width', pjaxy_page_info.header_width)

.attr('height', pjaxy_page_info.header_height);






The first line inside our document ready call turns on the PJAX functionality. The rest of it is to replace various page elements outside the #main div with updated versions. We’ll need to update the <title> to let folks know they’ve moved to a new page. We also need to update the body class to make sure everything renders properly. I’ll explay the pjaxy_page_info JS object and how it gets generated a bit later on.

The PJAX library adds a X-PJAX header, which can use to detect whether a request was made via PJAX.

<?phpfunction is_pjax(){if( isset( $_SERVER['HTTP_X_PJAX'] ) && strtolower( $_SERVER['HTTP_X_PJAX'] ) == 'true' ) {return true;}return false;}

Next up, if we detect a PJAX request we want to ditch the normal templates and include a stripped down version. To do this we can hook into the various {$template_type}_template filters. If it’s the home page, for instance, the filter is home_template. Singular page templates are single_template.

Here’s an example.

<?phpadd_filter( 'single_template', 'pjaxy_singular_template' );function pjaxy_singular_template( $template ){if( is_pjax() ) {$post = get_queried_object();$temps = array( "single-{$post->post_type}.php" );$temps[] = 'single.php';if( $t = pjaxy_find_template( $temps ) ) {$template = $t;}}return $template;}

This is a blantant rip off of the WP core 

. As are the rest of the template filter functions in this file.

The difference is the pjaxy_locate_template function. Which is going to look for the correct theme file in the current child theme. If it doesn’t file one, it will fall back to the parent theme. We’re looking for our templates inside the pjax-templates folder of the child or parent theme.


function pjaxy_find_template( $templates )


$located = '';

foreach( (array) $templates as $t ) {

if( ! $t ) {


} elseif( file_exists( STYLESHEETPATH . '/pjax-templates/' . $t ) ) {

$located = STYLESHEETPATH . '/pjax-templates/' . $t;


} elseif( file_exists( TEMPLATEPATH . '/pjax-templates/' . $t ) ) {

$located = TEMPLATEPATH . '/pjax-templates/' . $t;




return $located;


This is, of course, ripped off from the WP core’s locate_template function.

PJAX templates will be a bit different than your normal WordPress template files. Basically what I did for the pjaxy theme was copy everything from the corresponding normal template files except the calls to get_header and the like. We don’t need all that extra stuff – just the content that will get plugged into the #main div.

You can view some examples on Github.

When a PJAX call completes it fires off the pjax:end event. You can use jQuery to listen in for this event (via jQuery('#main').bind('pjax:end')). With that done, it’s a simple matter of a bit of JavaScript to replace body classes and such.

At the top of every template file is a call to the function get_pjaxy_page_info which is just a wrapper around a require_once statement.


function get_pjaxy_page_info()


require_once( PJAXY_PATH . 'inc/page-info.php' );


If you want to use any of the above code in your theme, the page-info.php file will probably get changed. The only thing we’re doing here is creating a JavaScript object with the stuff we need to replace outside the #main div.


$header_src = get_header_image();

$header_width = HEADER_IMAGE_WIDTH;

$header_height = HEADER_IMAGE_HEIGHT;

if( is_singular() ) {

$post = get_queried_object();

if( $thumb_id = get_post_thumbnail_id( $post->ID ) ) {

$header_image = wp_get_attachment_image_src( $thumb_id, array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) );

if( $header_image[1] >= HEADER_IMAGE_WIDTH ) {

$header_src = $header_image[0];

$header_width = $header_image[1];

$header_height = $header_image[2];





<script type="text/javascript">

var pjaxy_page_info = {

body_class: "<?php echo esc_js( join( ' ', get_body_class( 'pjax-loaded' ) ) ); ?>",

page_title: "<?php echo esc_js( wp_title( '', false ) ); ?>",

header_img: "<?php echo esc_js( $header_src ); ?>",

header_height: "<?php echo esc_js( $header_height ); ?>",

header_width: "<?php echo esc_js( $header_width ); ?>"



What all this boils down to is figuring out to change how WordPress acts when a PJAX request is received. It’s a proof of concept, but it certainly speeds up page load times on the client side – take a look at the demo. Worth a look if you’re building a new theme!

Stay in touch

Bringing news to you

Subscribe to our newsletter

By clicking and subscribing, you agree to our Terms of Service and Privacy Policy

** Twitter is moving away from this at the time of writing.

Related Content

thumbnail image

SEO For ReactJS Websites

4 MINUTES READ | April 11, 2018

thumbnail image

A New Strategy for Testing Google AMP

3 MINUTES READ | July 13, 2017

thumbnail image

Optimizing for Amazon Echo Search

4 MINUTES READ | August 8, 2016

thumbnail image

Not a Publisher? AMP Pages for the Rest of Us

3 MINUTES READ | March 3, 2016

thumbnail image

How SEO's Can Use Python

5 MINUTES READ | October 24, 2011

thumbnail image

SEO Auto Linker

2 MINUTES READ | August 23, 2011