WordPress 3.6 introduced a new API called the “WordPress Heartbeat”. This is the API that behind a lot of the improvements in WordPress 3.6, including better revision tracking, user’s session management, and more. I’m going to show you a quick example of how you can use the API to perform “live” actions.

What is the Heartbeat API?

The Heartbeat API is very appropriately named. Think of it as a beating heart. Just as our human hearts beat and send out a pulse, the Heartbeat API sends out a pulse (technically called a “tick”) that can be latched onto in order to perform actions periodically.

One of the great aspects of the Heartbeat API is that it’s almost purely javascript based, which allows for actions to be performed not just behind the scenes but also on the screen the user is viewing. For example, using the Heartbeat API you could disable a notice on the screen anytime a value in the database changes. Doing something like this involves two parts:

1. Hooking into the “send”, or the start of the pulse, and attaching your data (probably retrieved from the database).

2. Hooking into the “tick” to receive the data, and modifying the user’s screen via Javascript.

As a real world example, let’s consider the implementation for Easy Digital Downloads where we are live updating our Dashboard Sales Summary dashboard widget as sales come in. Anytime a new sale is made, the summary widget automatically updates with the new sales and earnings stats.

The process for updating our sales summary looks about like this:

1. Hook into the heartbeat send and add a unique key that let’s us know when a response should include the payment data

2. Hook into the response data sent back from the server and include the sale count, but only if our key added in 1 is present

3. Read the data sent back and extract the sale count, then use Javascript to insert the new number in the summary widget

Let’s look at the code that makes this all work.

First we need to ensure the heartbeat JS is loaded:

1
2
3
4
5
6
7
8
<?php
// Load the heartbeat JS
function edd_heartbeat_enqueue( $hook_suffix ) {
    // Make sure the JS part of the Heartbeat API is loaded.
    wp_enqueue_script( 'heartbeat' );
    add_action( 'admin_print_footer_scripts', 'edd_heartbeat_footer_js', 20 );
}
add_action( 'admin_enqueue_scripts', 'edd_heartbeat_enqueue' );

We hook into the admin_print_footer_scripts action in order to inject our JS into the footer of the Dashboard, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
// Inject our JS into the admin footer
function edd_heartbeat_footer_js() {
    global $pagenow;
 
    // Only proceed if on the dashboard
    if( 'index.php' != $pagenow )
        return;
?>
    <script>
    (function($){
 
        // Hook into the heartbeat-send
        $(document).on('heartbeat-send', function(e, data) {
            data['edd_heartbeat'] = 'dashboard_summary';
        });
 
        // Listen for the custom event "heartbeat-tick" on $(document).
        $(document).on( 'heartbeat-tick', function(e, data) {
 
            // Only proceed if our EDD data is present
            if ( ! data['edd-payment-count'] )
                return;
 
            // Log the response for easy proof it works
            console.log( data['edd-payment-count'] );
 
            // Update sale count and bold it to provide a highlight
            $('.edd_dashboard_widget .b.b-sales').text( data['edd-payment-count'] ).css( 'font-weight', 'bold' );
 
            // Return font-weight to normal after 2 seconds
            setTimeout(function(){
                $('.edd_dashboard_widget .b.b-sales').css( 'font-weight', 'normal' );;
            }, 2000);
 
        });
    }(jQuery));
    </script>
<?php
}

This is where the bulk of the “magic” happens. On line 12 we append an edd_heartbeat key and set its value to dashboard_summary. This allows us to easily detect the kind of data we want to send back from the server (code coming shortly).

Line 18 is the part that listens for a tick coming from the server. With each tick is sent an array of data. It’s this array of data that we hook into (a little later) in order to add our own information. In this case, data[‘edd-payment-count’] simply contains an integer that represents the total number of sales in the system. We can then take this integer and modify the text value of our sales widget. A little CSS is added for effect, basically giving the sale count a pulse anytime it updates.

The data that is sent back from the server is setup in the heartbeat_received filter, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// Modify the data that goes back with the heartbeat-tick
function edd_heartbeat_received( $response, $data ) {
 
    // Make sure we only run our query if the edd_heartbeat key is present
    if( $data['edd_heartbeat'] == 'dashboard_summary' ) {
 
        // Retrieve payment count
        $payments = edd_count_payments();
 
        // Send back the number of complete payments
        $response['edd-payment-count'] = number_format_i18n( $payments->publish );
 
    }
    return $response;
}
add_filter( 'heartbeat_received', 'edd_heartbeat_received', 10, 2 );

Note that the very first thing we do is look for the edd_heartbeat key and ensure its value is equal to dashboard_summary. This ensures we only perform our query when it is needed.

Inside of the conditional, we do a simple query to return the number of payments in the store, then we pass it back as part of the response. This is the response data that our Javascript uses above.

That’s it, a complete implementation of the WordPress Heartbeat API.

You can download the complete example plugin from here.

  1. Chris Christoff

    We love pushing the boundaries of WordPress at EDD 🙂

  2. Phil Johnston

    How often does a heartbeat-tick happen?

    • Pippin

      Every 15 seconds by default.

  3. Andrew

    Great read, thanks. The possibilities of the Heartbeat API are exciting

  4. Devtard

    Didn’t know about this, thanks for sharing. 🙂

  5. Sean Davis

    Thanks, boss. Definitely worth playing with.

  6. Chris Mooney

    Thanks for the intro on this Pippin, there’s not many resources out there on this yet so this has been a big help in getting me started.

  7. Wil

    Pippin, do you know how much bandwidth (k) is sent over each heartbeat in a default WordPress installation?

    • Pippin

      It depends on whether there is data attached to a heartbeat. When there’s nothing attached, it’s extremely tiny. So small that you probably couldn’t even detect it. When there’s data attached, it just depends on how much data there is.

  8. Travis Smith

    Pippin, this is a great write-up! Thanks for sharing this.

  9. Anirudh Babbar

    Hey Pippin, I read an article somewhere else about heartbeat and how to stop that….

    I wanted to stop heartbeat, because my site was taking much time to load and pingdom said its because of admin-ajax.php… So i stopped heartbeat and my site speed was reduced by 3 seconds.. What your suggestion, should we stop it or not…

    • Pippin

      Are you using the heartbeat on the frontend of your site?

    • Juan

      If you dont use it, then disable it.. anyway, its impossible that a heartbeat is taking 3 seconds just by itself. If that were the case, your site would take ages to load.

  10. Evan Herman

    Hey Pippin,

    Thanks for this post, it’s helping out quite a bit in understanding the inner workings of the heartbeat API. I’m working on getting it implementing in our MailChimp plugin to update account activity in real time (new user subscribes, unsubscribes etc). This certainly helps out, thanks again. Keep up the great work (and great talk at WCNYC on ‘Sane Plugin Updates’).

  11. Jmizpah

    Thanks for this. Very useful resource. !

  12. Collins Agbonghama

    Just when I started playing with the Heartbeat API and trying to figure out how it works, you came to my rescue Pippin. Yet again.

    Great and easy to follow walkthrough.

  13. Justin Lindsay

    Why do people make crap “How to articles” that include things like PHP inline scripts. Ever heard of wp_enqueue_script and localize_script? No? Didn’t think so. Go out and google them and start using them, and PLEASE stop teaching bad habits by putting this kind of bad code into help articles typically read by beginner dev’s. It’s lazy, un-maintainable, un-portable and just generally horribly bad.

Comments are closed.