Using AJAX with WordPress for conditional loading

AJAX has become a big part of responsive design for me. I use it to load secondary content into larger viewports to make it easier to find/view than if it is behind a small link in the footer or somewhere like that.

In WordPress it's really easy to do, but this is one of those situations where I couldn't find a definitive guide to how it's done, so I've written this that will hopefully fix that.

Two steps:

  1. Build a PHP function that creates whatever it is you need.
  2. Build an AJAX request that goes and gets it.

WordPress handles everything else using /wp-admin/admin-ajax.php

As an example let's say we want the titles of the latest five posts to show up in a sidebar on each single post. It's not vital content and can easily be accessed by going to the top level page that shows the latest five, but it might be nice to have for some people and we have the room.

The first thing to do is create a PHP function in our theme's functions.php with a WordPress loop that creates the list.

function get_latest() {
	$args = array(
		'posts_per_page'  => 5,
		'category'        => 1,
	);

	$posts_array = get_posts($args);

	echo '<nav role="navigation">';

		echo '<h2>Latest News</h2>';

		echo '<ul>';

	foreach ($posts_array as $post):
		setup_postdata($post);
		echo '<li><a class="' . esc_attr("side-section__link") . '" href="' . esc_attr(get_page_link($post->ID)) . '">' . $post->post_title . '</a>';
	endforeach;

	echo '</ul>';

echo '</nav>';

	die();
}
// creating Ajax call for WordPress
add_action( 'wp_ajax_nopriv_get_latest', 'get_latest' );
add_action( 'wp_ajax_get_latest', 'get_latest' );

It's a straightforward WordPress function — it could be anything at all, even something as simple as echo '<a href="https://twitter.com/intent/user?user_id=123456789">follow me on twitter</a>. There are two things worth noting however.

The die() is necessary at the end to stop any further PHP processing in /wp-admin/admin-ajax.php which outputs 0. If we don't use die() at the end of our function a 0 will appear after our list.

The other thing to note is the block of two add_action() functions. This will not work without them.

Now to the front end. We need to create a JavaScript function that calls /wp-admin/admin-ajax.php and tells it which PHP function to run.

jQuery.ajax({
	type: 'POST',
	url: '/wp-admin/admin-ajax.php',
	data: {
		action: 'get_latest', // the PHP function to run
	},
	success: function(data, textStatus, XMLHttpRequest) {
		jQuery('#latest-news').html(''); // empty an element
		jQuery('#latest-news').append(data); // put our list of links into it
	},
	error: function(XMLHttpRequest, textStatus, errorThrown) {
		if(typeof console === "undefined") {
			console = {
				log: function() { },
				debug: function() { },
			};
		}
		if (XMLHttpRequest.status == 404) {
			console.log('Element not found.');
		} else {
			console.log('Error: ' + errorThrown);
		}
	}
});

All we need to do in here is tell the function which PHP function to run and where to put the output, in this case in a container element with id latest-news.

You can wrap the jQuery function in a matchMedia test or use a technique that uses JavaScript to test a CSS property value that only applies to larger viewports.

That's all there is to it. It's quick and easy but a reliance on jQuery might not be your bag. However AJAX is one thing jQuery is very good at getting working cross browser painlessly.