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.

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) {
	 	return false;

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.

This function will load the JS scripts:

function test_ajax_load_scripts() {
	// load our jquery file that sends the $.post request
	wp_enqueue_script( "ajax-test", plugin_dir_url( __FILE__ ) . '/ajax-test.js', array( 'jquery' ) );
	// make the ajaxurl var available to the above script
	wp_localize_script( 'ajax-test', 'the_ajax_script', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );	
add_action('wp_print_scripts', 'test_ajax_load_scripts');

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.

function text_ajax_process_request() {
	// first check if data is being sent and that it is the data we want
  	if ( 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 end
		echo $response;
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.

    • Pippin

      @Jonathan – more coming soon πŸ™‚ the last two weeks have been really slow due to the launch of a massive project that has been in the works for a year and a half

  1. Gabu

    Thanks a LOT! Pippin
    Just get my Ajax working in fronted Via Plugin ….

    & I get this at right time .. I need to learn properly & now I get all form it,
    By the way I nice tutorial & code paste here
    may be helpful for other like me,…

  2. Alex

    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’

    • Pippin

      That’s a bug in the code. Thanks for noticing.

  3. geneellis

    Can you show how this is implemented on the front end? Where can I put the link? I am using this as a plugin but have no idea where to put the link so that jquery can see it…thanks

    • Pippin

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

    • geneellis

      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.

  4. geneellis

    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..


    • Pippin

      Got it. I understand your question now. In this case what you need to do is create a link like this:

      Click Me

      When you click any link with the class of “ajax-link”, you should trigger the ajax request.

      Make sense?

    • geneellis

      Yes. I couldn’t figure out how to get the link to display, but I took a look at your “love it” plugin and figured it out. It’s all working now. Thanks!!

  5. Sascha

    you should add usage of nonce. Its a builtin feature of wp to add more security.

    kind regards

    • Pippin

      Nonces should only be used in the admin, so if you are doing a front end request there is no need for one.

  6. Chetan

    HI ,
    I have try this code . But I got 0 in response . why this happen ?

    • Pippin

      That usually happens because your security (nonce) check failed. Can you confirm whether it is working or not?

    • Chetan

      Thanks Pippin … But I’m new in WordPress ….Can you please guide me where to set security (nonce) check ? or How I can solve this issue ?

  7. Chris

    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!!!

    • Pippin

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

  8. Chris

    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 –


    • Pippin

      Please post your code to an external service like snippi.com and then share the link.

  9. Kevin Pace

    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.

    Thanks for the article.

    • Pippin

      1. It can go in just about any file of your plugin. By utilizing the WordPress wp_ajax_ system, our code doesn’t have to go in a specific file.

      2. By echoing the data you want returned inside of the function that is connected to the wp_ajax_YOUR_ACTION hook.

      3. It illustrates how you can display an alert when an ajax action is complete.

  10. Michael

    Really clean explanation Pippin, thanks.

    If you have a moment, could you suggest how to load a wordpress post into a element? I would think this would require a nonce as well.

    My initial thought would be to replace the post_var with ‘$(this).attr(“id”)’ which would contain the post ID in the link. E.g (post-1).

    Then in the process_request() function trim the post_var and execute WP_Query and return the_content() in the response.

    Or should you always use the href attribute to load the content?

    • Pippin

      There are multiple ways to do it, but both methods you mentioned should work fine.

  11. Michael

    I found with the first method that, no shortcodes would be executed in the_content().

  12. Suzanne

    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.

    • Pippin

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

    • Suzanne

      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

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

  13. John

    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?

    Thanks, Anyway πŸ˜€


    • Pippin

      Yep, just do it inside of the processing function.

  14. John

    Hi Pippin,

    How can I pass the variable to the text_ajax_process_request()?

    Sorry Im newbie in this field.



  15. Matthew

    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!

    • Pippin

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

  16. Matthew

    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!!

    • Matthew

      Sorry didn’t mean to spam!

  17. Vajrasar Goswami

    This is more of a dumb ques I guess. Sorry if it is.

    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?

    if it was 2, what reason was it?

    Thanks for the tut.

    • Pippin

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

    • Vajrasar Goswami

      @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

      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?

  18. Matthew

    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.

    Stack exchange person’s answer:

    Don’t echo things in the AJAX callback. JavaScript should handle that.

    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.

    Thank-you for your time!

    • Pippin

      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().

  19. mks

    hi i want to call ajax in my plugin in front end.I implemented your way but getting -1 as response!, but when i login as admin then test in front end page then works.

    • Pippin

      That means you added the “wp_ajax_{your action name” hook but not also the “wp_ajax_nopriv_{your action name}” hook.

  20. jeroen

    Hi pippin,

    This is working like a charm. Been looking for this for hours. You saved my day


  21. Wade

    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


    • Pippin

      It’s available in the admin, so you don’t need to do it there, but you still need to on the frontend.

  22. Amanda

    This is awesome! I’ve been trying to figure out how to pass back stuff to the php for 2 days now.

  23. Edo Lando


    this is not working on firefox and safari for me.
    works perfectly on chrome though.
    any idea?

    • Edo Lando

      the alert returns “0”.

    • Pippin

      That usually means your action name is incorrect. Make sure the action you pass in your JS matches what you use in add_action( ‘wp_ajax_’ .$action ….);

  24. Kunal Nath

    Hi Pippin,

    How do I get $_POST[“post_var”]; in the template file? Please let me know, It’s urgent.

  25. Muftau

    This is an extremely important analysis on this part of wp. It is the actual article I have looking. Nice touch of technique via the breakdown of the parts.
    Keep it up dude.

Comments are closed.