Brief Introduction to PushState in WordPress

Yesterday, I was developing a WordPress website and I needed to incorporate PushState in order to properly fulfill particular specifications.

I think it took me a lot longer than I needed, partially because I didn’t come across any easy documentation to understand how to work with PushState. So, consider this an introductory guide to using PushState.

What is PushState?

PushState is DOM function that allows us to change the history of a browser and changes the URL on call.

If you open the console right now and type:

history.pushState({}, "page 2", "bar.html"); 

You’ll see the URL change to https://samuelpedraza/programming/wordpress-pushstate/bar.html

Neat huh? Let’s break down the function:

If you type history in the browser, it’ll show you a snapshot of where you’ve been and a few attributes like the length, state, and so forth.

When you execute history.pushState({}, "", "/bar.html"), it will essentially push whatever elements you include, into this History object.

Our first parameter in history.pushState is {}, which is an empty object. You can pass a value pair into the object, similar to { a : "b"}, execute pushState in the browser, and then type history.state to note that the state is indeed {a : “b”}.

The second parameter is the title of the webpage. However, this isn’t supported by Mozilla and seems to be overall discouraged in using.

The third parameter is fairly obvious, being the URL that you want to set.

Using PushState

Now it the fun part, where we actually incorporate PushState within an application.

First, check out this repository and clone it to your local computer or copy the code to an instance on This is the theme that we will use in order to demonstrate PushState.

Next, go to whatever WordPress instance you are running and create posts with the categories “fruit”, “cars”, and “animals”. Assign three posts per category.

Let’s go file by file with an explanation of how it all fits together, and then we’ll demo it.


Well, every theme needs a style.css file.


For the individual posts.


In this script, we grab all the radio buttons, and iterate through them, setting an eventlistener to execute our ugly function display_data on click.

Our display_data contains the bulk of the logic in our application. Let’s examine it now:

var get_data = this.value
history.pushState({page: get_data}, "", window.origin + "/" + get_data);

The first this we do is check to see if the radio button is checked, and if it is, then we grab the value of the radio button. Next, we execute the pushState function, changing the URL and passing the page data into the history object.

Note: We use window.origin in order to replace the entire URL. We don’t want to append over and over to the end of a URL.

var data = {
  action: "fetch_categories_post",
  category_slug: get_data

Next we prepare for the ajax post event by creating an object with an action field and a POST field of category_slug

// clear html
 // initialize variable
 var information = "";

We then clear out the #element area, and initialize an empty string variable. + "/wp-admin/admin-ajax.php", data, function(response){
	// get response and parse
	response = JSON.parse(response);

	// prepare to display links
	for(var response_iterate = 0; response_iterate < response.length; response_iterate++){
		information += "<a href='/" + get_data + "/" + response[response_iterate].post_name + "'>" + response[response_iterate].post_title + "</a> <br>";

	// display links

This is the last bulk of logic for our application. We post the data to the functions.php, get the response back, parse the response and then compile it into raw HTML, that we then append to webpage.

We then attach this function to the window “load” event, so we can display the proper links when the page is loaded.

Index.php & Categories.php

The index.php and categories.php webpage are very similarly structured.

 <?php wp_head(); ?>
 	<div class="form-group">
 			<input type="radio" name="display_cat" value="fruit" class="form-control" <?php $term = get_queried_object(); if($term->slug === "fruit"){ echo "checked"; } ?>>	
 	<div class="form-group">
 			<input type="radio" name="display_cat" value="cars" class="form-control" <?php $term = get_queried_object(); if($term->slug === "cars"){ echo "checked"; } ?>>
 	<div class="form-group">
 			<input type="radio" name="display_cat" value="animals" class="form-control" <?php $term = get_queried_object(); if($term->slug === "animals"){ echo "checked"; } ?>>
 <div id="element">

 <?php wp_footer(); ?>

This code is from the categories.php page. If the URL is animals, for example, the radio box will be checked.

When the webpage is loaded, the proper posts associated with that category, are then displayed.

The index.php page is almost exactly similar, but without the if statement, that checks for the URL of the page.


The Functions.php is a very straightforward file. We register the main.js file, and then we have a function to process the AJAX request.

function load_js(){
     wp_enqueue_script('jquery', '', '', '', TRUE);
     wp_enqueue_script('mainJS', get_template_directory_uri() . '/main.js', '', '', TRUE);
add_action('wp_enqueue_scripts', 'load_js');

Pretty straightforward code, registering the JavaScript and jQuery.

function fetch_categories(){
   $cat_slug = $_POST['category_slug'];

   $cat_posts = get_posts('category=' . get_cat_ID($cat_slug));

   echo json_encode($cat_posts);

This is fairly straightforward code. We get the POST request from the JS file, grab each post from the category, JSON encode it, and then send it back to the main.js file.


Overall, we’ve seen how to assemble a basic example of using PushState. We can grab and display different posts, without refreshing the entire page, while allowing the page to have indexable content.

One thought on “Brief Introduction to PushState in WordPress”

  1. Hi, Thank you for your post. I’ve followed the instruction but it doesn’t work on my machine. When selected the radio button, it doesn’t fetch all my post data.

Leave a Reply