Process Ajax Requests Correctly in WordPress Plugins

WordPress provides a set of great tools for processing ajax requests in plugins (and themes). I’m going to give you a quick example of how these tools can be used to accomplish a variety of tasks. For this example, We’ll just be using some simple alerts, but they will serve very well for demonstration purposes.
The first thing we will do is write our jQuery function. This will be used for interpreting a click event on the front end and sending the request to the server. Name your file ajax-test.js and place it in the root of your plugin folder, or wherever you wish.

1
2
3
4
5
6
7
8
9
10
11
12
13

jQuery(document).ready(function($){
$(".ajax-link").click(function(){var data ={
action:'test_response',
post_var:'this will be echoed back'};// the_ajax_script.ajaxurl is a variable that will contain the url to the ajax processing file
$.post(the_ajax_script.ajaxurl, data,function(response){
alert(response);});returnfalse;});});

What we have done in this bit of jQuery is pretty simple. First we run our function anytime that an anchor link with a class of “ajax-link” is clicked. Next, we set up a variable containing the POST variables and their values. Take careful note of our variable names: action, which is set to the value of “test_response”, and post_var, which has a value of “this will be echoed back”. We will use both of these var names in a bit.

Next we use the jQuery $.post() function to send the data variable to the server. Notice the the_ajax_script.ajaxurl parameter. This is a variable containing the url of the ajax processing file. We will set this variable in a little bit. Inside of the post function, we have setup an alert to happen when the request is finished, and we’re going to display the value of the response in our alert(). This will allow us to know if it really worked.

That’s it for the jQuery, so now we move on the PHP.

Inside of your plugin file, or theme file, you need to create two functions: one to load the jquery we just wrote, and one to process the request.

The first part of this function loads and initiates the jQuery file we just wrote. After that, we use wp_localize_script() to send the ajaxurl variable to our script. The first parameter of this function must match the first of the wp_enqueue_script() function.

After we’ve loaded the script and made the ajax url available for use, we make use of add_action() to load the scripts in our site’s header.

Now, we write our last function, which will receive the request sent by our jQuery script, and then send a response back to it. This is where we must remember the var names we used in our data variable in our jQuery.

1
2
3
4
5
6
7
8
9
10
11

function text_ajax_process_request(){// first check if data is being sent and that it is the data we wantif(isset($_POST["post_var"])){// now set our response var equal to that of the POST var (this will need to be sanitized based on what you're doing with with it)$response=$_POST["post_var"];// send the response back to the front endecho$response;die();}}
add_action('wp_ajax_test_response','text_ajax_process_request');

This function does little more than check that the correct data is being sent, and then sends the response back. One of the really important things to notice here is the first parameter of the add_action() hook. It has the form of wp_ajax_{action_name} where {action_name} equals the value of the action var we set in our data variable.

Now, if all goes well, you will get a nice alert saying “this will be echoed back” when you click on your link. That’s great because now you can go much farther and beyond this example and utilize this same modal to do some really cool things in your plugins. I recently used this exact technique (and hardly much more code) to write a Mark as Read plugin.

In the test_ajax_load_scripts() function, plugin_dir_url(__FILE__) includes a trailing slash at the end (according to the Codex). Why would you include a forward slash before the js file name?
plugin_dir_url( __FILE__ ) . ‘/ajax-test.js’

I don’t understand your question. Are you asking how to process an ajax request on the front end from your plugin?

geneellis

November 8, 2012

Hmm….I think so. Such as I followed the tutorial step by step. The last thing you wrote is “Now, if all goes well, you will get a nice alert saying “this will be echoed back” when you click on your link.”

However, where is the link? Basically how can I test it? I have been studying AJAX and WP for a while now and believe I have the basics down. This is the last bit I am trying to understand so that I can build from it.

geneellis

November 8, 2012

Do you have this as a complete plugin so that I can download it and look at the source code? Like I said, the part that is messing me up is getting the display link into the front end. I click it and it doesn’t recognize it is AJAX. Same thing happened to me with another tutorial even though I copied it line by line. However when I install your plugin, it works fine. Not sure if the code is different or what..

Thank you for this!!
I followed your tutorial and got a calendar plugin I’d developed working with an ajax call but now I’m stuck on a few points.
For starters, I’m not sure how to now let users go forward or backward a month. Previously, that could be accomplished with
$html .= ‘Next month‘;
I”m not sure how to pass more than one variable to the ajax call via data ( example: data { month: parseInt(‘2′) } ( but I have month and year…) , or what the correct url is now since we’re relying on admin-axax.php for processing, or if there’s a cache that needs to be cleared once the action has been satisfied — with the calendar, the user should be able to keep incrementing/decrementing the month.
Please forgive me if I’m missing the obvious and thanks very much for any insights/help!!!

Could you show me the code you’re using so I have a little more to go off of?

Chris

April 10, 2013

Hi,
Thanks! I’m trying to figure out how to adapt my code to introduce ajax into the following plugin so that the whole page doesn’t need to reload when the user wants to go forward or backward a month. This plugin is working otherwise.
The calendar only needs two pieces of info: month and year.
Those variables only really need to be introduced to the ‘previous’ and ‘next’ links in bold below, which is why discovering your tutorial was so great for me, that the action was being triggered with a link.
I got your great tutorial working as is. However, if I hit the ajaxurl directly (mysite.com/wp-admin/admin-ajax.php?action=test_response I get a 0. My first challenge is understanding the right way to specify that url. Does it matter that this is a child theme? Then, what the url of the links to move the calendar forward and backward should be. I think I get how to pass the mon and year variables but won’t know until I know what url to specify. My next challenge would be to determine how to structure the functions and their calls. The calendar should load with a get request of today’s date and should move ahead or back with a posted request via the previous and next links… Thanks for any insights and for the great tutorial –

This is a good description but really hard to follow. Here’s some questions:

1. Where is the file that does the processing? ie. process.php
2. How do I get that data back to my front-end
3. Why are you displaying an Alert Box as the example? This doesn’t appear to be AJAX to me.

It seems all this example does is show an alert box. Please correct me if I am wrong.

Great write-up Pippen. AJAX confuses me every time I do a new implementation. I’m curious if you have insights into why the response would return the entire document ( not in your example, but in general ). This happened to me once before because I had a redirect for non-logged-in users preventing the admin-ajax from firing. But I have a new case with no active redirects, returning the entire document again. Uber frustrating.

My guess is that you have not included exit; or die(); at the end of the ajax processing function.

Suzanne

November 29, 2013

Believe it or not, it was an ID on the submit button that caused that. I never would have known that if it weren’t for the fact I reverse engineered my entire plugin by merging it with one that worked. Letter by letter, piece by piece I merged the two and the minute I added the ID to the button, poof, ajax threw up an alert with the raw document HTML.

Pippin

November 29, 2013

Ah! That makes sense actually because with an incorrect ID, your function that processes the request will simply be ignored.

John

January 20, 2014

Hi Pippin,

Thanks for your post, this is very helpful for everybody. 😀

I Would like to ask if How can I make a SQL/ $wpdb->insert or $wpdb->update? Am I going to insert the sql inside the text_ajax_process_request() function?

I’m very new to wordpress development. I was wondering why you have used wp_print_scripts as the action, & then wp_enqueue_script? Why didn’t you use wp_enqueue_scripts as the action? Thank-you. Very helpful tutorial!

They both work in this case. For the purpose of this tutorial, either works fine.

Matthew

February 25, 2014

I’m very new to wordpress development. I was wondering why you have used wp_print_scripts as the action, & then wp_enqueue_script? Why didn’t you use wp_enqueue_scripts as the action? Thank-you. Very helpful tutorial!!

We could have achieved the same pop-up initially by echoing the response ( which was echoed in text_ajax_process_request) directly by echoing it in first function that we set up in ajax-test.js. If am right, there could be two reasons of why we did this long way –

1. you wanted to show us how to use ajax and jquery combo when situation arises.
2. there was some specific reason using the combo in this particular example.

If it was 1, then what example situation (that you can suggest) could be where we are bound to to use ajax+jquery combo?

Do you mean by echoing out the javascript for the popup via the ajax response?

Vajrasar Goswami

March 6, 2014

@Pippin: I meant, we can’t produce a popup on a click event directly via jQuery, right? But you chose to show us the ajax method. So what example situation (that you can suggest) could be where we are bound to to use ajax+jquery combo instead of just jQuery?

Vajrasar Goswami

March 6, 2014

Sorry I meant to write CAN and wrote CAN’T. Re-framed reply –

@Pippin: I meant, we can produce a popup on a click event directly via jQuery, right? But you chose to show us the ajax method. So what example situation (that you can suggest) could be where we are bound to to use ajax+jquery combo instead of just jQuery?

It shows a popup notice once the ajax request (to bookmark an item) is successsful.

Matthew

March 5, 2014

Is this example outdated for 2014? I slightly modified your example, & posted a problem with it on stack exchange. I’m aware that your example doesn’t validate or sanitize, but I wondered what you thought of the feedback I got from the stack exchange person who answered me. I’m new to coding & wordpress, so slightly confused by the conflicting advice.

To send data in your callback, use wp_send_json() or the higher level functions wp_send_json_success() and wp_send_json_error(). All of them will die for you. No need to exit or die afterwards.

Data Validation and Sanitization is something you should take serious: $response = $_POST[“post_var”]; is extremely unsafe way to do things. If you already got hacked, then this would have been an open door. Use filter_var() or filter_var_array(), both native PHP functions, or esc_attr() and similar WordPress escaping functions.

AJAX and shortcodes are a very specific thing. Per default AJAX requests go through the admin interface (hence admin-ajax.php as handling route). And shortcodes aren’t needed in the admin UI. They get rendered during runtime when the content of a post gets rendered when looping.

The wp_send_json_error() is a great function that should definitely be used. It wasn’t used when this tutorial was written because it didn’t exist yet; it was introduced in WP 3.5, after this tutorial was published

Does the existence of wp_send_json_error() make echoing the data in the ajax callback wrong? Most definitely not.

He is absolutely right about sanitizing the data. I just updated the code to include a note about sanitizing. The exact way the data is sanitized depends largely on what the data is being used for.

For example, if you are taking input from a text field, you may want to use the sanitize_text_field() function. If you are taking a whole number, such as a post ID, you may want to run the post data through absint().

In the wordpress codex it states that “Since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php”

If I understand this correctly and if my test are accurate you no longer need to use the wp_localize_script to make the admin-ajax.php file available as it is already available by default and you can remove the_ajax_script from the ajax url