How To Use AJAX In WordPress

Advertisement

In the last few years, AJAX has crept onto websites and slowly become the way to create dynamic, user-friendly, responsive websites. AJAX is the technology that lets you update the contents of a page without actually having to reload the page in the browser. For example, Google Docs utilizes this technology when saving your work every few minutes.

sm-ajax-20111

While there are a number of ways to use AJAX in WordPress — and all are “correct,” in the loose sense of the word — there is one method that you should follow for a few reasons: WordPress supports it, it is future-proof, it is very logical, and it gives you numerous options right out of the box.

What Is AJAX?

If you’re not familiar with AJAX, I suggest continuing to the end of this article and then reading the Wikipedia article on AJAX2, followed by some tutorials3. This is a rare case when I recommend reading as little about it as possible before trying it out, because it confused the heck out of me at first; and the truth is, you will rarely interact with AJAX in its “raw” state — you will usually use helpers such as jQuery.

In a nutshell, AJAX is a combination of HTML, CSS and JavaScript code that enables you to send data to a script and then receive and process the script’s response without needing to reload the page.

If you are creating a page on your website where users can modify their profile, you could use AJAX to update a user’s profile without needing to constantly reload the page whenever they submit the form. When the user clicks the button, the data they have entered into the form is sent via AJAX to the processing script, which saves the data and returns the string “data saved.” You can then output that data to the user by inserting it onto the page.

The thing to grasp about AJAX is how not different it is from what you’re already doing. If you have a contact form, chances are that the form is marked up with HTML, some styles are applied to it, and a PHP script processes the information. The only difference between this and AJAX is how the information that the user inputs gets to the script and back to the user — everything else is the same.

To exploit the full potential of AJAX and get the most out of this article, you will need to be familiar with JavaScript (jQuery will suffice), as well as HTML, CSS and PHP. If your JavaScript knowledge is a bit iffy, don’t worry; you’ll still be able to follow the logic. If you need a hand, just submit a comment, and I’ll try to help out.

How Not To Use AJAX

One method that has been around, and which I used myself back in the bad old days, is to simply load the wp-load.php file at the top of your PHP script. This let’s you use WordPress functions, detect the current user and so on. But this is basically a hack and so is not future-proof. It is much less secure and does not give you some of the cool options that the WordPress system does.

How AJAX Works In WordPress Natively

Because AJAX is already used in WordPress’ back end, it has been basically implemented for you. All you need to do is use the functions available. Let’s look at the process in general before diving into the code.

Every AJAX request goes through the admin-ajax.php file in the wp-admin folder. That this file is named admin-ajax might be a bit confusing. I quite agree, but this is just how the development process turned out. So, we should use admin-ajax.php for back-end and user-facing AJAX.

Each request needs to supply at least one piece of data (using the GET or POST method) called action. Based on this action, the code in admin-ajax.php creates two hooks, wp_ajax_my_action and wp_ajax_nopriv_my_action, where my_action is the value of the GET or POST variable action.

Adding a function to the first hook means that that function will fire if a logged-in user initiates the action. Using the second hook, you can cater to logged-out users separately.

Implementing AJAX In WordPress

Let’s build a rudimentary voting system as a quick example. First, create an empty plugin and activate it. If you need help with this part, look at the tutorial on creating a plugin4. Also, find your theme’s single.php file, and open it.

Preparing to Send the AJAX Call

Let’s create a link that enables people to give a thumbs up to our articles. If a user has JavaScript enabled, it will use JavaScript; if not, it will follow the link. Somewhere in your single.php file, perhaps near the article’s title, add the following code:

<?php
   $votes = get_post_meta($post->ID, "votes", true)
   $votes = ($votes == "") ? 0 : $votes;
?>
This post has <div id='vote_counter'><?php echo $votes ?></div> votes<br>

<?php
   $nonce = wp_create_nonce("my_user_vote_nonce");
    $link = admin_url('admin-ajax.php?action=my_user_vote&post_id='.$post->ID.'&nonce='.$nonce);
    echo '<a class="user_vote" data-nonce="' . $nonce . '" data-post_id="' . $post->ID . '" href="' . $link . '">vote for this article</a>';
?>

First, let’s pull the value of the votes meta key related to this post. This meta field is where we will store the total vote count. Let’s also make sure that if it doesn’t exist (i.e. its value is an empty string), we show 0.

We’ve also created an ordinary link here. The only extra bit is a pinch of security, using nonces5, to make sure there is no foul play. Otherwise, this is simply a link pointing to the admin-ajax.php file, with the action and the ID of the post that the user is on specified in the form of a query string.

To cater to JavaScript users, we have added a user_vote class, to which we will attach a click event, and a data-post_id property, which contains the ID of the post. We will use these to pass the necessary information to our JavaScript.

Handling the Action Without JavaScript

If you click this link now, you should be taken to the admin-ajax.php script, which will output -1. This is because no function has been created yet to handle our action. So, let’s get cracking!

In your plugin, create a function, and add it to the new hook that was created for us. Here’s how:

add_action("wp_ajax_my_user_vote", "my_user_vote");
add_action("wp_ajax_nopriv_my_user_vote", "my_must_login");

function my_user_vote() {

   if ( !wp_verify_nonce( $_REQUEST['nonce'], "my_user_vote_nonce")) {
      exit("No naughty business please");
   }   

   $vote_count = get_post_meta($_REQUEST["post_id"], "votes", true);
   $vote_count = ($vote_count == '') ? 0 : $vote_count;
   $new_vote_count = $vote_count + 1;

   $vote = update_post_meta($_REQUEST["post_id"], "votes", $new_vote_count);

   if($vote === false) {
      $result['type'] = "error";
      $result['vote_count'] = $vote_count;
   }
   else {
      $result['type'] = "success";
      $result['vote_count'] = $new_vote_count;
   }

   if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
      $result = json_encode($result);
      echo $result;
   }
   else {
      header("Location: ".$_SERVER["HTTP_REFERER"]);
   }

   die();

}

function my_must_login() {
   echo "You must log in to vote";
   die();
}

First of all, we’ve verified the nonce to make sure that the request is nice and legit. If it isn’t, we simply stop running the script. Otherwise, we move on and get the vote count from the database; make sure to set it to 0 if there is no vote count yet. We then add 1 to it to find the new vote count.

Using the update_post_meta() function, we add the new vote count to our post. This function creates the post’s meta data if it doesn’t yet exist, so we can use it to create, not just update. The function returns true if successful and false for a failure, so let’s create an array for both cases.

I like to create these result arrays for all actions because they standardize action handling, giving us good debugging information. And, as we’ll see in a second, the same array can be used in AJAX and non-AJAX calls, making error-handling a cinch.

This array is rudimentary. It contains only the type of result (error or success) and the vote count. In the case of failure, the old vote count is used (discounting the user’s vote, because it was not added). In the case of success, we include the new vote count.

Finally, we detect whether the action was initiated through an AJAX call. If so, then we use the json_encode() function to prepare the array for our JavaScript code. If the call was made without AJAX, then we simply send the user back to where they came from; obviously, they should be shown the updated vote count. We could also put the array in a cookie or in a session variable to return it to the user the same way, but this is not important for this example.

Always end your scripts with a die() function, to ensure that you get back the proper output. If you don’t include this, you will always get back a -1 string along with the results.

The function to handle logged-out users is obviously poor, but it is meant merely as an example. You can expand on it by having it redirect the user to a registration page or by displaying more useful information.

Adding JavaScript to the Mix

Because we’ve now handled the user’s action using regular methods, we can start building in the JavaScript. Many developers prefer this order because it ensures graceful degradation. In order for our system to use AJAX, we will need to add jQuery, as well as our own JavaScript code. To do this, WordPress-style, just go to your plugin and add the following.

add_action( 'init', 'my_script_enqueuer' );

function my_script_enqueuer() {
   wp_register_script( "my_voter_script", WP_PLUGIN_URL.'/my_plugin/my_voter_script.js', array('jquery') );
   wp_localize_script( 'my_voter_script', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));        

   wp_enqueue_script( 'jquery' );
   wp_enqueue_script( 'my_voter_script' );

}

This is the WordPress way of including JavaScript files. First, we register the JavaScript file, so that WordPress knows about it (so make sure to create the file and place it somewhere in the plugin). The first argument to the wp_register_script() function is the “handle” of our script, which is a unique identifier. The second is the location of the script. The third argument is an array of dependencies. Our script will require jQuery, so I have added it as a dependency. WordPress has already registered jQuery, so all we needed to add was its handle. For a detailed list of the scripts that WordPress registers, look at the WordPress Codex6.

Localizing the script is not strictly necessary, but it is a good way to define variables for our script to use. We need to use the URL of our admin-ajax.php file, but because this is different for every domain, we need to pass it to the script. Instead of hard-coding it in, let’s use the wp_localize_script() function. We add the script handle as the first argument, an object name as the second argument, and we can add object members as an array in the third parameter. What this all boils down to is that, in our my_voter_script.js file, we will be able to use myAjax.ajaxurl, which contains the URL of our admin-ajax.php file.

Once our scripts have been registered, we can actually add them to our pages by enqueueing them. We don’t need to follow any particular order; WordPress will use the correct order based on the dependencies.

Once that’s done, in the my_voter_script.js JavaScript file, paste the following code:

jQuery(document).ready( function() {

   jQuery(".user_vote").click( function() {
      post_id = jQuery(this).attr("data-post_id")
      nonce = jQuery(this).attr("data-nonce")

      jQuery.ajax({
         type : "post",
         dataType : "json",
         url : myAjax.ajaxurl,
         data : {action: "my_user_vote", post_id : post_id, nonce: nonce},
         success: function(response) {
            if(response.type == "success") {
               jQuery("#vote_counter").html(response.vote_count)
            }
            else {
               alert("Your vote could not be added")
            }
         }
      })   

   })

})

Let’s go back to the basics. This would be a good time for those of us who are new to AJAX to grasp what is going on. When the user clicks the vote button without using JavaScript, they open a script and send it some data using the GET method (the query string). When JavaScript is used, it opens the page for them. The script is given the URL to navigate to and the same parameters, so apart from some minor things, from the point of view of the script being run, there is no difference between the user clicking the link and an AJAX request being sent.

Using this data, the my_user_vote() function defined in our plugin should process this and then send us back the JSON-encoded result array. Because we have specified that our response data should be in JSON format, we can use it very easily just by using the response as an object.

In our example, all that happens is that the vote counter changes its value to show the new vote count. In reality, we should also include some sort of success message to make sure the user gets obvious feedback. Also, the alert box for a failure will be very ugly; feel free to tweak it to your liking.

Conclusion

This concludes our quick tutorial on using AJAX in WordPress. A lot of functionality could still be added, but the main point of this article was to show how to properly add AJAX functionality itself to plugins7. To recap, the four steps involved are:

  1. Make the AJAX call;
  2. Create the function, which will handle the action;
  3. Add the function to the hook, which was dynamically created for us with the action parameter;
  4. Create success handlers as needed.

As mentioned, make sure everything works well without JavaScript before adding it, so that the website degrades properly for people who have disabled it.

Keep in mind that, because we are using hooks, we can also tie existing WordPress functions to our AJAX calls. If you already have an awesome voting function, you could just tie it in after the fact by attaching it to the action. This, and the ease with which we can differentiate between logged-in states, make WordPress’ AJAX-handling system very powerful indeed.

(al)

Footnotes

  1. 1 http://www.smashingmagazine.com/2011/10/18/how-to-use-ajax-in-wordpress
  2. 2 http://en.wikipedia.org/wiki/Ajax_(programming)
  3. 3 http://www.tizag.com/ajaxTutorial/
  4. 4 http://www.smashingmagazine.com/2011/09/30/how-to-create-a-wordpress-plugin/
  5. 5 http://markjaquith.wordpress.com/2006/06/02/wordpress-203-nonces/
  6. 6 http://codex.wordpress.org/Function_Reference/wp_enqueue_script#Default_scripts_included_with_WordPress
  7. 7 http://greennow.net/

↑ Back to topShare on Twitter

Daniel is not only a web developer who is in love with WordPress, but also the Editor of the Smashing WordPress section. He owns a company called Bonsai Shed where they make web apps and premium themes like Musico and Estatement.

Advertising
  1. 1

    You said nothing about the amount of memory used by this method – you load the whole WP (with all its plugins and themes) just to make some small thing like DB insert, update or select (mostly). Is this wise? Not sure. Is there another approach? Absolutely.
    Use your own ajax.php (or similar) and make direct calls to it from js, use jsonp to secure these calls, use include wp-config.php (with SHORTINIT defined before) OR raw php without WP (if you can). You will speed up your ajax up to 10 (ten) times – and the same for memory (ten times less).
    Just being ajaxified doesn’t mean to be cool.

    10
    • 2

      I have to agree with Kyle on this one. You are absolutely correct about the speed issue, but I would still recommend doing it the memory intensive way.

      If you want to start circumventing basic parts of the framework then there really is less and less of a point in using it. Also, if you start writing your own stuff no other developer will understand what you’re doing.

      Another problem is that if you do not load the WP core you can’t use any functions so you can’t really write WP standard code either.

      Resource usage is not everything, I don’t think that optimization should be sacrificed for utility. I’d rather spend 2x as much on server costs than having to deal with non standard code lumps. If you need a really AJAX heavy site, as Kyle suggests, use a more appropriate framework.

      2
      • 3

        Yes, Daniel, your points are clear and have their own life in the wild.
        But in your post and in my comments we are talking about WordPress, aren’t we? So in this case (and taking into account the topic of this SM subdomain) your and Kyle’s words about changing the framework are not in the loop…

        -1
        • 4

          My point was that even if it means a higher resource usage you should use the method described in the post.

          -3
    • 5

      AJAX on WordPress is generally slow no matter what. You always need wp-load.php bottomline and even that is not catered to AJAX. At some point, rather than fine tuning your AJAX on WordPress, you just need a more appropriate framework to start with.

      0
      • 6

        Unfortunately, that’s not always an option – to change a framework.
        So there are only 3 ways to use ajax with WP:
        1) described here;
        2) using external ajax-handler file with SHORTINIT defined AND include(‘./wp-config.php’). Will give access to $wpdb class and some other useful stuff;
        3) using external ajax-handler file that is independant from WP.
        All of them have their drawbacks. I’ve listed them in descending order of using php memory and response time.

        After all, we, developers, can do whatever we want. The limits are time and our will. And personal preferences :)

        5
        • 7

          I completely agree with all that, despite what I said below :) I’m not saying there is NEVER a cause for using an external handler, but I would think it is VERY rare where you could justify it to me.

          On the bright side, it’s not like you have to justify anything to me :D

          2
          • 8

            Ok, we all have own opinions – this is great!
            I think readers got the idea, let them make their own decisions – and that would be great too.

            Nevertheless, thank you, Daniel, for a useful post! It touched a coder inside me – and that’s awesome (for me).

            1
    • 9

      When you start worrying about resource usages and speed, you should start looking at another language all together. PHP is the worst performing language of all the popular scripting languages. Sure, resource usage should be looked at and optimized if possible but hardware is cheaper than developer hours and it’s easier to scale on an already existing API (WordPress’s provided one) than to try and maintain an AJAX API too.

      3
  2. 10

    Thanks!
    Nice introduction to AJAX with WordPress.

    2
  3. 11

    Hi Daniel,

    Thanks alot for taking the time to write this nice article.

    Could you please fix the “creating a plugin” link as it leads to an expired domain name?

    Thanks again, all the best.

    0
  4. 13

    Seems like you want to prevent the link from doing the default behavior. Something like this:

    jQuery(“.user_vote”).click( function(evt) {
    evt.preventDefault();
    // you other code…
    });

    5
  5. 15

    Hi!

    I’ve done a good amount of research to find a generic wp ajax-plugin for for loading ordinary posts or pages but found almost nothing. I think this is pretty odd since wp is so big and content loading with ajax even bigger. There are some outdated plugins and lots of snippets working under special cirkumstances/themes but that’s all.

    Could this be something for a part two article?

    1
    • 16

      There’s an all AJAX wp theme that may help you out. It’s called ‘All AJAX’ WordPress Theme and developed by DiW Theme Clubhouse.. Maybe this will help you out.

      0
  6. 17

    Hey there. I discovered your web site by means of Google while searching for a related matter, your web site came up. It seems great. I’ve bookmarked it in my google bookmarks to come back later.

    -1
  7. 18

    Thank you for such a great introduction! I do not know Javascript and I’m learning both AJAX and javascript as I go.

    I wanted to ask if you could please share with me how to create the same functionality but instead of passing data through a link with data- format, you can show me or direct me to the info on how to pass data via a form with various input hidden variables and one input field as type text.

    I currently have a form that shows up when a link is clicked and in Javascript is defined like this:

    When the user clicks saves, using your ajax method it calls the php function and this all works great without AJAX! The form is submitted and it is saved but it reloads the whole page.

    The thing that does not work is the AJAX sumit form part. Here is my javascript:

    //AJAX function to store data when field is edited
    jQuery(document).ready( function($) {

    $(‘#hm_button_savefield’).submit(function(event) {

    var input = $(this);
    var formElm = $(input).parents(‘form.hm_edit_field_form’);
    var tempHtml = formElm.html();
    formElm.html(”);

    var nonce = jQuery(this).attr(“data-nonce”);
    var postData = getPostData(‘#hm_edit_field_form *[name]‘);

    jQuery.ajax({
    type : “post”,
    dataType : “json”,
    url : HM_Ajax.ajaxurl,
    data : postData,
    success: function(response) {

    if(response.type == “success”) {
    document.getElementById(“hm_editfield-” + hm_field).innerHTML = response.field_value + “WE USED AJAX”;
    }
    else {
    alert(“Your vote could not be added”);
    }

    }

    }); //Close jQuery.ajax function

    }); //Close input click function

    //Get all POSTable data from form.
    function getPostData(selector){
    var postData = {};
    $.each($(selector), function(index,el){
    el = $(el);
    postData[el.attr('name')] = el.attr(‘value’);
    });
    return postData
    }

    }) //Close jQuery ready function

    Any help would be greatly appreciated!

    Thank you,
    Giovanni

    1
  8. 19

    This is interesting, but the necessity of creating a plugin in order to use ajax in wordpress makes it sound daunting to me. However I do understand that if you are building a theme or even a widget to put in your theme with ajax elements then this is probably the best way to go.

    I wrote an article about using ajax in a wordpress post using a small standalone javascript file instead of jquery (at http://www.wilycode.com/how-to-use-ajax-in-a-wordpress-post/), which I believe falls in slaFFik’s category 3 of memory usage/response time in their comment. The purpose was for a standalone simple ajax example. Like Daniel and Kyle alluded to, the method of implementation depends on functional requirements.

    0
  9. 20

    Some troubleshooting problem in my WordPress post comment…
    when i reply to posted comment. my comment form not move to selected comment reply portion. and reload full page. any solution..

    Present: reply URLs referencing comment ID (http://localhost/lessons/css-tricks-how-to-make-your-website-load-faster/?replytocom=2#respond)
    Present:
    Present: <li id="li-comment-2" …
    Present: encapsulating the comment form

    reply link:
    – Reply to this Comment

    0
  10. 21

    So, I’m curious here. I’m not new to AJAX, but I am relatively new to WordPress. Your call to wp_enqueue_script() is going to ensure that my_voter_script.js is included on every single page on your site. Even pages that make no use of this script are still going to download it. That seems like a waste. Have you given any thought to how to ensure that my_voter_script.js (or any js that is enqueued) could be configured to only get included on specific pages?

    Update: Nevermind, I’ve figured it out. In my_script_enqueuer(), you could use whatever conditional you wanted, like is_page(), is_post(), etc. to control when the script gets enqueued. One thing though, shouldn’t you be using the ‘wp_print_scripts’ hook instead of ‘init’?

    0
  11. 22

    so is there any way i can perform an ajax call to external forder php file in wordpress

    1
  12. 23

    Hello. Thank you for the tutorial. Do you have this entire plugin downloadable? I follow all the instructions, but it seems to not be using AJAX. I know this because after clicking the link, the page refreshes. Any idea what I could be doing wrong. Followed the tutorial step by step. Thank you.

    0
    • 24

      Hi Gene,

      take a look at Bob Cravens’ message:

      Seems like you want to prevent the link from doing the default behavior. Something like this:

      jQuery(“.user_vote”).click( function(evt) {
      evt.preventDefault();
      // you other code…
      });

      1
  13. 25

    Thank you, Daniel, for your very helpful tutorial. You’ve saved me time and frustration, and I truly appreciate your perspective re: future proofing, correctness, etc.

    I also wanted to give you a heads up regarding a missing semi-colon, which should be at the end of the second line if I’m not mistaken, on the code sample just below the “PREPARING TO SEND THE AJAX CALL” heading.

    0
  14. 26

    Thanks for this useful information…
    just want to share another tip:

    We can send a Jquery ajax request to a custom page, that handles the request.
    Ex:
    function delete_row(id) {
    jQuery.post(‘delete.php’, {id : id},
    function(data) {
    alert(data);
    }
    );
    }

    Here, ‘delete.php’ is a custom file in ‘wp-admin’, that handles the ajax action:
    require_once (‘admin.php’);
    global $wpdb;
    $id = $_POST["id"];
    $table = “wp_about”;
    $wpdb->query(“DELETE FROM “.$table.” WHERE id =”.$id);
    echo $wpdb->rows_affected;
    exit();

    0
  15. 27

    Panic… Incrementing twice for each vote :-( As well each time the page is loading for voting, hope it shouldn’t. Kindly suggest me.

    0
  16. 28

    This coding restrict users. Only registered user can only post the vote other can’t. Kindly suggest me how to make everyone to put vote.

    0
  17. 29

    Despite the use of nounces it would be even better to use $_POST or $_GET alone instead of $_REQUEST (that combines get, post and cookie data = GPC) . There are known XSS attack methods using cookies to override other values and doing some evil stuff.

    But it’s a very good article on wordpress ajax – the best I found so far. Thanks for sharing with us!

    0
  18. 30

    I’m running my own handler. I like KISS and the WordPress handling of AJAX is an overly complex mess. In my opinion.

    For admin tasks, I check that user can manage options, has the correct NONCE, and that the NONCE is less than hour old (I don’t use WordPress’s NONCE system, again, it is overly complex).

    Only if those three conditions pass does it continue, it doesn’t even load the include files for my class if those fail. Upon failure of any of those conditions, it sends a 403. Upon success, it immediately invalidates the NONCE – new one is generated later and sent with the response.

    Doing it myself is not only a lot simpler, but the performance is better too. WordPress needs to redesign their AJAX support from the ground up.

    In my opinion. Others of course are free to have others, and once (back in 1993 I believe) I was actually wrong about something. ;)

    1

↑ Back to top