WordPress Heartbeat vs AJAX Polling

If you purchase through a link on our site, we may earn a commission. Learn more.

WordPress 3.6 introduced the "Heartbeat API". This API is used internally by WordPress to keep track of logged in users and their active sessions. If you've ever been asked to log into WordPress while navigating the admin panel, then you've already experienced the API at work. The API uses Javascript polling, to constantly send data from our dashboard to WordPress' PHP backend. Developers are also allowed to hook in, adding and modifying the data sent through various filters. But when should you use the Heartbeat API in contrast to regular AJAX polling? To make an informed decision, we'll need to look at both approaches, understand how they work and how to use them, and the advantages and disadvantages for both.
Table of Contents
WP Engine High Performance Hosting
BionicWP Hosting

WordPress 3.6 introduced the “Heartbeat API”. This API is used internally by WordPress to keep track of logged in users and their active sessions. If you’ve ever been asked to log into WordPress while navigating the admin panel, then you’ve already experienced the API at work.

The API uses Javascript polling, to constantly send data from our dashboard to WordPress’ PHP backend. Developers are also allowed to hook in, adding and modifying the data sent through various filters.

But when should you use the Heartbeat API in contrast to regular AJAX polling? To make an informed decision, we’ll need to look at both approaches, understand how they work and how to use them, and the advantages and disadvantages for both.

WordPress Heartbeat API

With Heartbeat, WordPress polls the server every 15 seconds using AJAX. Each poll is called a “pulse”, verifying that the logged in user’s session still exists, performs auto saving if a post is being edited, updates the locks on posts if others are editing them and more. However, the API was designed so that plugin and theme developers can hook into the data that is sent and received with each pulse, as well as change the interval of each pulse from anything between 15 and 60 seconds.

The great thing about this API is that developers can hook in any data they want, allowing their plugin or theme to either perform auto saving the way WordPress does with posts, show updates on the user’s screen without the need to refresh, or even adjust the contents of the screen based on some event that occurred somewhere else on the site, like a user disabling an option in the settings.

Here’s a short example of how to hook into the API and add your own data. The below is the Javascript side of the polling logic.

(function($){

    // Hook into the heartbeat-send
    $(document).on( 'heartbeat-send', function(e, data) {
        data['my_data'] = 'hello';
    });

    // When a heartbeat tick (or pulse) is received
    $(document).on( 'heartbeat-tick', function(e, data) {
        // If our response is not included in Heartbeat, stop
        if ( !data['my-response'] ) return;
        // Get our response
        var response = data['my-response'];
        // Put the response in our element
        $('#my-element').append( response );
    });

}(jQuery));

And for the PHP side, we’ll enqueue our script, as well as receive the my_data that the script sends, and reply with my-response, which is what the script expects.

// Filter the Heartbeat data being sent to the client
add_filter( 'heartbeat_received', 'our_heartbeat_received', 10, 2 );
/**
 * Checks if the Heartbeat tick contains `my_data`, and adds a reply to
 * the Heartbeat response.
 */
function our_heartbeat_received( $response, $received ) {
    // Check if 'my_data' exists in the received data,
    // is not empty, and is "hello"
    if ( empty( $received['my_data'] ) && $received['my_data'] == 'hello' ) {
        // Add our response
        $response['my-response'] = 'Hi there!';
    }
    // Return the response
    return $response;
}



// Add an action to call our script enqueuing function
add_action( 'admin_enqueue_scripts', 'enqueue_my_heartbeat_script' );
/**
 * Enqueues our Heartbeat script
 */
function enqueue_my_heartbeat_script() {
    // Prepare the dependencies - our script requires jQuery and WordPress'
    // Heartbeat scripts.
    $depends = array( 'jquery', 'heartbeat' );
    // Enqueue our script, using the dependencies we declared above
    wp_enqueue_script( 'my-heartbeat-script', 'our/heartbeat/script.js', $depends );
}

All it takes is a script and two PHP functions, one if you are already grouping your script and style enqueues in a single function.

Now, every 15 seconds the script will send our my_data field, with the text hello, after which the server should reply with “Hi there!”, which is added to our #my-element element. If you leave the page open, you will see that a new “Hi there!” is added to the element every 15 seconds.

AJAX Polling

Asynchronous polling using Javascript has been around for quite a while. Libraries like jQuery have dedicated technologies for making AJAX calls incredibly easy and flexible. Let’s have a look at how AJAX can be implemented in WordPress.

We’ll start by enqueuing our script, using the same method as above.

// Add an action to call our script enqueuing function
add_action( 'admin_enqueue_scripts', 'enqueue_my_scripts' );
/**
 * Enqueues our scripts
 */
function enqueue_my_scripts() {
    // Enqueue our script, using the jQuery dependency
    wp_enqueue_script( 'my-script', 'path/to/script.js', array('jquery') );
}

Now for the Javascript polling. Using jQuery makes this ridiculously easy.

(function($){

    $(document).ready( function() {
        // Call updateVotes for the first time
        updateVotes();
    });

    // Function to update the votes shown on screen
    var updateVotes = function() {
        // Prepare the data to send.
        // The "action" is the name of the action hook to trigger.
        // Anything else is data that we want to pass to the PHP function.
        // Here, I am adding the text of the #votes element
        var data = {
            action: "my_voting_ajax",
            current: $('#votes').text()
        };

        // Send a POST request to the ajaxurl (WordPress variable), using the data
        // we prepared above, and running the below function when we receive the
        // response. The last parameter tells jQuery to expect a JSON response
        $.post( ajaxurl, data, function( response ) {
            var votes = response.votes;
            $('#votes').text( votes );
            // Wait 2 seconds, and run the function again
            setTimeout( updateVotes, 2000 );
        }, 'json' );
    };

})(jQuery);

In the above code, we are sending an AJAX call to WordPress every 2 seconds, giving it an action to trigger, and expect a JSON response. jQuery will automatically parse the JSON into an object, which we are using to retrieve the number of votes.

WordPress will call an action with a hook name identical to the action that we sent in our AJAX request, with a wp_ajax_ prefix. All we need to do in our PHP is hook into this action. In our case, the action is called wp_ajax_my_voting_ajax.

add_action( 'wp_ajax_my_voting_ajax', 'ajax_update_votes' );
/**
 * Gets the number of votes from the database, and sends it
 * back to the client script as JSON.
 */
function ajax_update_votes() {
    // Get the 'current' data that the AJAX call sent
    if ( isset( $_POST['current'] ) ) {
        $current = $_POST['current'];
        // Do something with it ...
    }

    // Get the number of votes from the database
    $votes = get_option( 'our_votes', 0 );

    // Prepare the data to sent back to Javascript
    $data = array(
        'votes'    =>    $votes,
        // Any other data we want
    );
    
    // Encode it as JSON and send it back
    echo json_encode( $data );
    die();
}

The result is a vote counter, that updates every 2 seconds. If you leave the page open and look at the vote counter, you will see the votes go up every 2 seconds, without the need to refresh the page. Other people on the site can be voting at the same time you are viewing the page, and their votes will be reflected on your page on the next poll.

The Verdict

The obvious difference between the two methods is the delay. WordPress Heartbeat’s minimum pulse interval is 15 seconds and its maximum is 60 seconds. Using our own AJAX code gives us the liberty of using any interval we want, be it as little as 1 second or as long as 10 minutes.

The other difference which might not be immediately noticeable is the flexibility in the response handling. With our AJAX code, we can opt to use the jQuery ajax function, which unlike the post function, allows us to specify what type we are recieving (text, JSON, XML, etc..) and functions to run if an error is encountered.

On the other hand, if these are not things you are concerned about, the WordPress Heartbeat API will still be polling very 15 seconds, even if you did not hook in to attach any data. Hooking into the API, rather than using your own AJAX code, will result in less requests being sent to the server.

It all comes down to your particular use case and what you want to achieve. Showing updating sales count, statistics data, views for a page or maybe even a broadcasted message is best done through the WordPress Heartbeat API, where 15 seconds is quite reasonable. Updating content that needs to be reflected “live” or close to real-time, such as progress bars, monitoring a running operation and even chatting, is best done using standard AJAX polling.

If you enjoyed this post, make sure to subscribe to WP Mayor’s RSS feed.

Miguel Muscat

Miguel is a passionate software developer who loves to tinker, reverse-engineer, and learn new skills. He has spent the past 10 years working with RebelCode to build amazing WordPress plugins that serve thousands of users worldwide.

Discover more from our archives ↓

Popular articles ↓

One Response

  1. It may not be true now, You can pass `wp.heartbeat.interval( ‘long-polling’ );` for polling.

Share Your Thoughts

Your email address will not be published. Required fields are marked *

Claim Your Free Website Tip 👇

Leave your name, email and website URL below to receive one actionable improvement tip tailored for your website within the next 24 hours.

"They identified areas for improvement that we had not previously considered." - Elliot

By providing your information, you'll also be subscribing to our weekly newsletter packed with exclusive content and insights. You can unsubscribe at any time with just one click.