How AJAX Works In WordPress Natively

AJAX is already used in WordPress’ back end. All we need to do use the functions that’s available.
Every AJAX request goes through the admin-ajax.php file in the wp-admin folder. 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 (logged-in user initiates the action)
wp_ajax_nopriv_my_action (logged-out user initiates the action)
where my_action is the value of the GET or POST variable action.

WordPress AJAX action

add_action( 'wp_ajax_my_action', 'ajax_handler' );
add_action( 'wp_ajax_nopriv_my_action', 'ajax_handler' );

function ajax_handler(){

/* Output Something */

wp_die();
}

Download Ajax Source Code

Example:

single.php
Preparing to send the AJAX call

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

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.

<?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>';
?>

We’ve also created an ordinary link here. The only extra bit is a pinch of security, using nonces, 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 or 0. 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();
}

Adding javascript to the mix

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' );
}

my_voter_script.js

jQuery(document).ready( function() {
   jQuery(".user_vote").click( function(e) {
     e.preventDefault();
     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")
            }
         }
      })
   })
})