Adding Ajax to Your WordPress Plugin

By Yojance Rabelo

Using Ajax in your WordPress website is easier than you think. With jQuery on your side, you can submit data, as well as receive data. Communicating with WordPress is performed through a special Ajax dedicated WordPress action that is capable of handling the server side aspect of it.

WordPress and Ajax

Ajax occurs usually after a form submission, or by pressing a button, enabling you to send bits of data to the server in order to be processed. As an example, please consider the following snippet of code:

var data {
	action: 'spyr_plugin_do_ajax_request',
	var1: 'value 1',
	var2: 'value 2'

Using our friend jQuery, we are going to POST this to the server and get a server response. In WordPress, all Ajax requests are sent to admin-ajax.php for processing. This file resides within the /wp-admin directory of your WordPress site. Even though the file resides in the admin area of your site, you can use it to process interactions from the front-end, as well as the back-end.

The Action Parameter

In our previous example, the action parameter spyr_plugin_do_ajax_request is responsible for making the connection between the JavaScript file and the PHP code. It’s recommended to prefix all action, including this one; so that it is unique and identifiable. Make it look like it belongs to your WordPress plugin.

WordPress’ Dedicated Ajax Actions

There are two WordPress dedicated Ajax actions that we can use.

The first is wp_ajax_$action which handles the Ajax request if the user is logged in.

The second is wp_ajax_nopriv_$action which handles the Ajax request if the user is not logged in and has no privileges at all.

Following our previous examples, we would add these action hooks to our plugin like so:

add_action( 'wp_ajax_spyr_plugin_do_ajax_request', 'spyr_plugin_do_ajax_request' );
add_action( 'wp_ajax_nopriv_spyr_plugin_do_ajax_request', 'spyr_plugin_do_ajax_request' );

Now that we know the basics of how an Ajax event interacts with WordPress, let’s see a real world example. Let’s build a simple plugin which will allow administrators to delete a certain post from the front-end.

Ajax Post Delete Plugin

We can now start building a sample plugin, which will delete Posts via Ajax. Since this article is meant to introduce you to the inner-workings of processing an Ajax request, I feel this plugin will allow you to get your hands dirty without adding any type of confusion. Our plugin will consist of:

  • Adding the JavaScript file with the Ajax script
  • Adding a link to every post that when clicked, it will delete the post
  • Handling the Ajax request with PHP
  • Handling the button click with jQuery
  • Enqueuing our script
// Add script on single post only, if user has Admin rights
add_action( 'template_redirect', 'spyr_add_js_single_posts' );
function spyr_add_js_single_posts() {
	// We only want to add the script if is_single()
	// and can manage options (Admins)
	if( is_single() && current_user_can( 'manage_options' ) ) {

		// Get the Path to this plugin's folder
		$path = plugin_dir_url( __FILE__ );

		// Enqueue our script
		wp_enqueue_script( 'spyr_ajax_delete_posts', 
							$path. 'js/ajax-delete-posts.js',
							array( 'jquery' ),
							'1.0.0', true );

		// Get the protocol of the current page
		$protocol = isset( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';

		// Set the ajaxurl Parameter which will be output right before
		// our ajax-delete-posts.js file so we can use ajaxurl
		$params = array(
			// Get the url to the admin-ajax.php file using admin_url()
			'ajaxurl' => admin_url( 'admin-ajax.php', $protocol ),
		// Print the script to our page
		wp_localize_script( 'spyr_ajax_delete_posts', 'spyr_params', $params );

Security is always important. So, we need to check whether the current user has sufficient permissions to see the ‘Delete’ link or not. We also need to ensure that we are viewing a single post, otherwise there is no point adding the ‘Delete’ link.

If both conditions are true, proceed enqueuing the script that contains the JavaScript code to handle what happens when the link is clicked. Pay close attention to how the protocol is being used in the front-end of the website. We must do this because of the same origin policy that Ajax requests and responses are subjected to. All Ajax requests and responses have to be processed from the same domain; and the protocols must match too.

In WordPress, it is possible to force the https protocol in the admin section of your site by setting ‘FORCESSLADMIN’ to ‘true’ in your WordPress configuration file. Sending a request from http://example.com/sample-post/ to https://example.com/wp-admin/admin-ajax.php won’t work. Even if we are forcing https:// on the back-end, we can make the call to admin-ajax.php without https://.

Finally, the last meaningful line in the code outputs our dynamic variables for us to use in ajax-delete-posts.js.

<script type='text/javascript'>
/* <![CDATA[ */
var spyr_params = {"ajaxurl":"http:\/\/example.com\/wp-admin\/admin-ajax.php"};
/* ]]> */

Add Delete Link to Content

// Add an admin link to each post
add_filter( 'the_content', 'spyr_add_content_delete_link' );
function spyr_add_content_delete_link( $content ) {
	if( is_single() && current_user_can( 'manage_options' ) ) {
		// Get current post
		global $post;

		// Create a nonce for this action
		$nonce = wp_create_nonce( 'spyr_adp-delete-' . $post->ID );
		// Get link to adminn page to trash the post and add nonces to it
		$link = '<a href="'. admin_url( 'post.php?post='. $post->ID .'&action=trash&nonce=' .$nonce ) .'" 
				class="spyr_adp_link" data-nonce="'. $nonce .'" data-id="'. $post->ID .'">Delete Post</a>';

		// Append link to content
		return $content . '<p>'. $link .'</p>';

Short and simple. Check for permissions again, and make sure you are viewing a single post. These security measures are necessary and it’s something you are going to have to get used to. Next, create your nonce and tie it to an action; note the the special format. It uses the following structure, prefix_plugin-action-identifier, where spyr is the prefix, adp = Ajax Delete Post, delete is our action, and the post ID is the identifier. This is not necessary but it’s recommended when writing plugins. Note that we are also adding the Post’s ID and nonce value to the link using HTML5 data attributes. The last step is to attach your formatted link to the content.

Handling the Ajax Request with PHP and WordPress

We are now half way through the article. What follows is the code that actually handles the submission of your Ajax Request. Pay close attention since it relies on how you name the data submitted by the jQuery request to get the post ID (pid) and nonce value.

// Ajax Handler
add_action( 'wp_ajax_spyr_adp_ajax_delete_post', 'spyr_adp_ajax_delete_post' );
function spyr_adp_ajax_delete_post() {
	// Get the Post ID from the URL
	$pid = $_REQUEST['pid'];

	// Instantiate WP_Ajax_Response
	$response = new WP_Ajax_Response;

	// Proceed, again we are checking for permissions
	if( current_user_can( 'manage_options' ) && 
		// Verify Nonces
		wp_verify_nonce( $_REQUEST['nonce'], 'spyr_adp-delete-' . $pid ) &&
		// Delete the post
		wp_delete_post( $pid ) ) {
		// Build the response if successful
		$response->add( array(
			'data'	=> 'success',
			'supplemental' => array(
				'pid' => $pid,
				'message' => 'This post has been deleted',
		) );
	} else {
		// Build the response if an error occurred
		$response->add( array(
			'data'	=> 'error',
			'supplemental' => array(
				'pid' => $pid,
				'message' => 'Error deleting this post ('. $pid .')',
		) );
	// Whatever the outcome, send the Response back

	// Always exit when doing Ajax

spyr_adp_ajax_delete_post is the name of the action being passed on from the request of your JavaScript file. With this in mind, the full name for your action would be wp_ajax_spyr_adp_ajax_delete_post. The Post ID and nonce values are also passed on via the JavaScript file, and we can get them from $_REQUEST.

We are going to be instantiating WP_Ajax_Response which will allow us to return a nice XML response. You can then read and act upon what’s returned via jQuery. Once again, you need to verify that the user is an Administrator, and try to match nonce values before deleting the post. You need to build different Responses for each scenario so that you know for sure if the Post was deleted or not. You can then attach a brief and concise message describing the result so that you can provide extra feedback to the user. Finally, you send the Response back to the browser and exit. Always remember to exit when you are doing Ajax Requests.

The Request, as it will be sent to the server for processing, is as simple as this:


An example of the formatted XML file returned in the Response can be explored below:

	<response action="spyr_adp_ajax_delete_post_0">
		<object id="0" position="1">
				<message>This post has been deleted</message>

Handling the Button Click with jQuery

The only thing left to do now is write the JavaScript code, which will send the request and parse the response. The code itself is pretty self explanatory but I’ve gone ahead and added inline comments to make it easier to understand.

jQuery( document ).ready( function() {
	jQuery( '.spyr_adp_link' ).click( function( e ) {
		var link = this;
		var id   = jQuery( link ).attr( 'data-id' );
		var nonce = jQuery( link ).attr( 'data-nonce' );

		// This is what we are sending the server
		var data = {
			action: 'spyr_adp_ajax_delete_post',
			pid: id,
			nonce: nonce
		// Change the anchor text of the link
		// To provide the user some immediate feedback
		jQuery( link ).text( 'Trying to delete post' );

		// Post to the server
		jQuery.post( spyr_params.ajaxurl, data, function( data ) {
			// Parse the XML response with jQuery
			// Get the Status
			var status = jQuery( data ).find( 'response_data' ).text();
			// Get the Message
			var message = jQuery( data ).find( 'supplemental message' ).text();
			// If we are successful, add the success message and remove the link
			if( status == 'success' ) {
				jQuery( link ).parent().after( '<p><strong>' + message + '</strong></p>').remove();
			} else {
				// An error occurred, alert an error message
				alert( message );
		// Prevent the default behavior for the link

Parsing the XML with jQuery is straightforward using jQuery.find(); look through the XML for an element as if you were trying to find an element in an HTML document.


As you can see, performing Ajax requests in your plugins and themes is a very straightforward process in WordPress. This is notably easier to achieve, thanks to the two dedicated actions: wp_ajax_$action and wp_ajax_nopriv_$action. This is just the beginning of a path of awesome code writing that will save page re-loads and add interactivity to your WordPress theme or plugin. What will you do next?

If you’re looking for more information on this topic, make sure you check out the WordPress Codex page on Ajax and Ajax in Plugins.

  • seangore

    You can imagine my disappointment when I saw that you get XML back from the Ajax request. I guess this just goes to show WordPress’s age.

    • http://yojance.net Yojance Rabelo

      This is just one way of getting your data back. I’m working on a second article involving Ajax, too; and it returns JSON. instead of XML.

      • http://www.mzoo.org/ Mike Ill Kilmer

        Is the JSON post done yet?

  • dojoVader

    Gosh this is daunting, this means you can call add_action anywhere in your code and when it fails how do you trace this,nice article out of courtesy, WordPress is just not it now.

  • http://nyasro.com/ Nyasro

    I like the way you use WP_Ajax_Response class for ajax call. I have never used this class but I think I should take look and try.

    • http://yojance.net Yojance Rabelo

      Thank you, Nyasro.

  • http://www.lowcostseo.co/ Aman Bansal

    Thank you for the great information. It’s interesting to see how long this specific post has been generating responses. I look forward to putting your ideas into action.

    Cheap SEO Services India

  • Lyricsmp3songs

    This is very true and helpful..Try it

  • http://w3guy.com Agbonghama Collins

    Great article.. way easy to comprehend than the codex documentation.

    Thank you.

  • desi

    I am new to WP. Please let me know the end to end complete example that uses wp_send_json_. Somehow I am able to make call to php but I am not getting anything back. On the server side it is making entries to the db as desired.

  • http://www.websiterox.com/ Websiterox

    Nice Tutorial.It really works.
    Using AJAX In WordPress

  • http://facebook.com/mark.clotfelter Mark K. Clotfelter

    Is there a download of this available?



Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in WordPress, once a week, for free.