How to use AJAX on WordPress

If you already know what is an AJAX request please just jump right to the section where I will talk about how to start coding.

What is an AJAX request

First you will need to understand that an AJAX request is nothing more then a simple GET or POST to an URL that you defined, you will pass some parameters and this URL should answer you with some other data that you will be able to parse on the JavaScript and using it you will be able to give your users the needed visual feedback.

So when you visit a URL like http://bordoni.me on your browser you are doing a GET request without any parameters, if you visit http://bordoni.me/?p=216 you will do a GET to this Post on WordPress by passing the p parameter on the URL then WordPress will redirect you to the correct link because permalinks are active.

A GET request is limited to a few parameters so that's why it's always better to use POST when dealing with AJAX, so that we don't have to limit ourselves that much, the POST is limited by size, so we will only have a limit when we reach the MB scale.

See LimitRequestBody for Apache and client_max_body_size for NGINX.

WordPress backend 

Each and every system has it's own method of routing a request, in WordPress we send all the AJAX calls to a single URL, and then WordPress will route internally to the correct method based on a param that you will send along with your AJAX request.

First lets understand where we will call the WordPress backend and how to pass this variable (url) to the JavaScript side of our application.

Using the admin_url( 'admin-ajax.php' ) anywhere within our WordPress installation will return a string with the full URL to where we should do our AJAX request.

On my website the return would be http://bordoni.me/wp-admin/admin-ajax.php.

JavaScript actions

So that you can do the AJAX request you will need some JS action in here, what you need to is create a file which will be loaded on the page that you will fire the AJAX via some user interaction.

To enqueue a JavaScript file on your WordPress page you will need to referrer to wp_enqueue_script and wp_register_script, which will load a and register a script respectively.

The following script will allow you to do a simple AJAX request and print the output to the JavaScript browser console.

jQuery(document).ready(function($) {
    // Information of our Request
    var data = {
        'action': 'bordoni_query_posts',
        'post_type': 'post',
        'qty': 15
    };

    // The variable ajax_url should be the URL of the admin-ajax.php file
    $.post( ajax_url, data, function(response) {
        console.log( response );
    }, 'json');
});

I've used jQuery.post to make our lives easier.

If you are not going to use JSON as your response, you might want to check the documentation on which other types of response are allowed.

WordPress AJAX action Callback

After you've set a JavaScript action, you will need to intercept this action via an action to be able to print out the response you want.

Your WordPress will read which action you've send as information on your AJAX request and do an action based on that name, in our case we used bordoni_query_posts.

On this AJAX request I will pass some variables to a WP_Query and return the posts as JSON so that we can use that information on the FrontEnd. The variables I've decided to use for now are only a few, qty that will allow you to change how many posts you want and post_type that will allow me to query the needed type of information using WP_Query.

You should add the following PHP code to your plugin or functions.php from your theme to be able to see the JSON response on your browser console.


add_action( 'wp_ajax_bordoni_query_posts', 'bordoni_query_posts_callback' );
add_action( 'wp_ajax_nopriv_bordoni_query_posts', 'bordoni_query_posts_callback' );
function bordoni_query_posts_callback() {
    $response = array();

    // Never Use $_POST or $_GET variables without proper care Sanatization
    $query = new WP_Query( array(
        'posts_per_page' => absint( $_POST['qty'] ),
        'post_type' => wp_kses( $_POST['post_type'], array() ),
    ) );

    // If we don't have posts matching this query return status as false
    if ( ! $query->have_posts() ) {
        $response->status = false;

        // remember to send an information about why it failed, always.
        $response->message = esc_attr__( 'No posts were found' );
    } else {
        $response->status = true;

        // We will return the whole query to allow any customization on the front end
        $response->query = $query; 
    }

    // Never forget to exit or die on the end of a WordPress AJAX action!
    exit( json_encode( $response ) ); 
}

On our Javascript handler we are expecting a JSON response, we will exit the action printing the $response variable encoded as JSON.

Wrapping Up

If you still have questions on how to proceed on a specific situation that I did not cover on this guide, please hit me up on the comment section below and I will be able to try to help you.

Helpful links

Discussions — 6 Responses

  • Soggy Bullets March 26, 2015 on 2:03 am

    It would be great if you would include your complete code w/the wp_localize_script. I need to be able to display posts inside the function e.g. // while ( $posts->have_posts() ) { $posts->the_post(); } // etc. but I cannot figure out how to pass the information to the JS to know when there are no more posts (to hide a Load More button, for example). Any ideas?

    Reply
  • Nicolas Galano June 24, 2015 on 2:11 pm

    Hi, i have a problem, the functions.php is not recognizing the WP_Query, says it's undefined, i tried to add the "wp-load.php" to the functions.php but that didn't help, any idea? Thanks!

    Reply
    • Gustavo Bordoni Nicolas Galano June 25, 2015 on 9:16 pm

      Hi Nicolas, I just updated the code, it had a typo now it should work as expected.

      The problem was that I was using $query = WP_Query instead of the $query = new WP_Query.

      Hope this helps you! ?

      Reply
  • suprtickets December 15, 2015 on 10:54 am

    Hi, should there be a function named "bordoni_query_posts" here? The jQuery code references this for the action value.

    Reply
    • Gustavo Bordoni suprtickets December 18, 2015 on 6:20 am

      Hi Suprtickets,

      You don't need a function named after the action that we referenced in the jQuery code, rather will need a connection between that action and the function.

      That is created by using the WordPress actions:

      add_action( 'wp_ajax_bordoni_query_posts', 'bordoni_query_posts_callback' );
      add_action( 'wp_ajax_nopriv_bordoni_query_posts', 'bordoni_query_posts_callback' );

      See that the bordoni_query_posts_callback which is the function is linked twice, one for non-logged users (nopriv) and one for all the logged users.

      What actually makes that connection is the filter which should be formated as wp_ajax_{$your_action} and wp_ajax_nopriv_{$your_action}.

      Was I clear on the explanation? I mean AJAX on WordPress can be a little weird at first.

      Reply
  • Rodrigo May 31, 2017 on 9:28 pm

    Hi, I have a problem, the functions.php are not recognizing WP_Query, says it is undefined, I tried to add the "wp-load.php" to the functions.php, but that did not help, any ideas? Can I use this in any theme? Thank you! http://www.goldpixel.com.br

    Reply