Advertisement
  1. Code
  2. Coding Fundamentals
  3. Game Development

Heartbeat API: Using Heartbeat in a Plugin

Scroll to top

In this tutorial we're going to create a simple plugin which uses the Heartbeat API. Our plugin will alert logged in users, via a growl-like notification, whenever another user logs in or out of the site.

Since this tutorial is focussed on the Heartbeat API, I shall leave out details about creating the plugin header or file structure: the plugin is very simple, and you can examine the source code in full at this GitHub repository.

A user will be deemed "logged in" when they log in and have been active within the last 24 hours. If a user logs out or is not active for 24 hours, they'll be considered to be offline. We'll keep tabs on the user's 'online' status and 'last active' timestamp to help determine who's currently online.


Logging-in and Logging-out

First we'll create a couple of functions hooked into wp_login and wp_logout hooks. These are triggered when a user logs in/out of WordPress. When a user logs in, we'll update their log in status (stored as user meta) to 'true' and update their last active timestamp.

1
2
function whoisonline_logged_in( $username, $user ) {
3
	update_user_meta( $user->ID, 'whoisonline_is_online', true );
4
	update_user_meta( $user->ID, 'whoisonline_last_active', time() );
5
}
6
add_action( 'wp_login', 'whoisonline_logged_in', 10, 2 );

Similarly, when a user logs out, we'll update their online status to false:

1
2
function whoisonline_logged_out() {
3
	$user_id = get_current_user_id();
4
	update_user_meta( $user_id, 'whoisonline_is_online', false );
5
}
6
add_action( 'wp_logout', 'whoisonline_logged_out' );

Who's Online?

Now let's create a function which returns an array of usernames of active users, indexed by user ID. We'll use the get_users() function to query all users who have been active in the last 24 hours (using the whoisonline_last_active meta key).

We'll then discard any users who have logged out by checking the whoisonline_is_online user / meta data.

1
2
function who_is_online( $args = array() ) {
3
4
	// Get users active in last 24 hours

5
	$args = wp_parse_args( $args, array(
6
		'meta_key' => 'whoisonline_last_active',
7
		'meta_value' => time() - 24 * 60 * 60,
8
		'meta_compare' => '>',
9
		'count_total' => false,
10
	) );
11
12
	$users = get_users( $args );
13
14
	// Initiate array

15
	$online_users = array();
16
17
	foreach ( $users as $user ) {
18
		if ( ! get_user_meta( $user->ID, 'whoisonline_is_online', true ) )
19
			continue;
20
21
		$online_users[$user->ID] = $user->user_login;
22
	}
23
24
	return $online_users;
25
}

Preparing for the Heartbeat API

Before we deal with the client-side part of the Heaertbeat API, let's deal with the server's response to a request for 'who's online'. As was covered in part 1 of this series, we'll hook onto the filter heartbeat_received (we don't need to trigger this for logged out users so won't use the heartbeat_nopriv_received filter).

First, we'll update the current user's activity timestamp, and ensure their status is set to 'online'. Next we'll check that a request for 'who's online' data has been made by looking for the who-is-online key (which we'll use later) in the received $data.

If it has, we'll respond with an array of logged in users of the form:

1
2
array( [User ID] => [User log in] )

As returned by who_is_online().

1
2
function whoisonline_check_who_is_online( $response, $data, $screen_id ) {
3
4
	// Update user's activity

5
	$user_id = get_current_user_id();
6
	update_user_meta( $user_id, 'whoisonline_last_active', time() );
7
	update_user_meta( $user_id, 'whoisonline_is_online', true );
8
9
	// Check to see if "who's online?" has been requested

10
	if ( ! empty( $data['who-is-online'] ) ) {
11
12
		// Attach data to be sent

13
		$response['whoisonline'] = who_is_online();
14
15
	}
16
17
	return $response;
18
}
19
add_filter( 'heartbeat_received', 'whoisonline_check_who_is_online', 10, 3 );
20
add_filter( 'heartbeat_received', 'whoisonline_check_who_is_online', 10, 3 );

Heartbeat API

Now create the JavaScript file who-is-online.js file in the root of your plugin folder. Below is the outline of the file.

First, we initiate our global variable whoisonline. whoisonline.online and whoisonline.onlinePrev are both 'associative arrays' (strictly speaking, in terms of JavaScript, they're objects) of users logins, indexed by user ID – corresponding to those users who are 'online' at the current / previous beat. This is used to determine when a user has logged in or out.

We then initiate our request for data on who's online with wp.heartbeat.enqueue and listen for the response by binding a callback to the event heartbeat-tick.whoisonline. In that callback we check for data returned by the server, perform any necessary actions and then ensure our request for data is queued for the next beat.

1
2
// Inititate variables

3
var whoisonline = { online: false, onlinePrev: false };
4
5
jQuery(document).ready(function() {
6
7
	//Set initial beat to fast - for demonstrative purposes only!

8
	wp.heartbeat.interval( 'fast' );
9
10
	//Enqueue are data

11
	wp.heartbeat.enqueue( 'who-is-online', 'whoisonline', false );
12
13
	jQuery(document).on( 'heartbeat-tick.whoisonline', function( event, data, textStatus, jqXHR ) {
14
		if ( data.hasOwnProperty( 'whoisonline' ) ) {
15
			// Perform actions with returned data

16
		}
17
18
		// In our example, we want to attach data for the next beat.

19
		// This might not be in the case in all applications: only queue data when you need to.

20
		wp.heartbeat.enqueue( 'who-is-online', 'whoisonline', false );
21
	});
22
});

Now, let's fill in the details of the logic inside our heartbeat-tick.whoisonline callback. Whenever data is received from the server we first check that it contains an array of logged in users (which would be given by the key 'whoisonline'), by checking data.hasOwnProperty( 'whoisonline' ). If so...

  • Update whoisonline.onlinePrev to reflect who was online at the last beat, and whoisonline.online to reflect who is online at the current beat.
  • Check for user IDs that appear in whoisonline.online, but are not in whoisonline.onlinePrev. These users have just logged in.
  • Check for user IDs that appear in whoisonline.onlinePrev, but are not in whoisonline.online. These users have just logged out.

The finished JavaScript file then looks like:

1
2
var whoisonline = { online: false, onlinePrev: false };
3
4
jQuery(document).ready(function() {
5
6
	// Set initial beat to fast

7
	wp.heartbeat.interval( 'fast' );
8
9
	// Enqueue are data

10
	wp.heartbeat.enqueue( 'who-is-online', 'whoisonline', false );
11
12
	jQuery(document).on( 'heartbeat-tick.whoisonline', function( event, data, textStatus, jqXHR ) {
13
14
		if ( data.hasOwnProperty( 'whoisonline' ) ) {
15
16
			if ( whoisonline.online === false ) {
17
				//If just loaded, don't say anything...

18
				whoisonline.online = data.whoisonline;
19
			}
20
			whoisonline.onlinePrev = whoisonline.online || {};
21
22
			for ( var id in whoisonline.onlinePrev ) {
23
				if ( ! whoisonline.online.hasOwnProperty( id ) ) {
24
					jQuery.noticeAdd( { text: whoisonline.onlinePrev[id] + " is now offline" } );
25
				}
26
			}
27
28
			for ( var id in whoisonline.online ) {
29
				if ( ! whoisonline.onlinePrev.hasOwnProperty( id) ) {
30
					jQuery.noticeAdd( { text: whoisonline.online[id] + " is now online" } );
31
				}
32
			}
33
		}
34
		wp.heartbeat.enqueue( 'who-is-online', 'whoisonline', false );
35
	});
36
});

Loading Our Scripts and Styles

This plugin will make use of the jQuery Notice add-on by Tim Benniks - a lightweight growl-like notification plugin for jQuery. Simply download it, and extract to the root of your plugin (it should consist of only two files: jquery.notice.js and jquery.notice.css)

Now that the jQuery plugin has been added, the last piece of the puzzle is to enqueue the necessary scripts and styles. We want this plugin to function both on the front-end and admin side, so we'll use both the admin_enqueue_scripts and wp_enqueue_scripts hook, but we only want to load the script for logged in users.

1
2
function whoisonline_load_scripts() {
3
4
	/* Ony load scripts when you need to - in this case, everywhere if the user is logged in */
5
	if ( is_user_logged_in() ) {
6
		wp_enqueue_script( 'whoisonline-jquery-notice', plugin_dir_url( __FILE__ ) . 'jquery.notice.js', array( 'jquery' ) );
7
		wp_enqueue_style( 'whoisonline-jquery-notice', plugin_dir_url( __FILE__ ) . 'jquery.notice.css' );
8
		wp_enqueue_script( 'whoisonline',  plugin_dir_url( __FILE__ ) . 'who-is-online.js', array( 'heartbeat', 'whoisonline-jquery-notice' ) );
9
	}
10
}
11
add_action( 'admin_enqueue_scripts', 'whoisonline_load_scripts' );
12
add_action( 'wp_enqueue_scripts', 'whoisonline_load_scripts' );

And that's the finished plugin.

You can see the code in full at this GitHub repository. There's plenty of room for improvement here (for instance display a list of users, and when they were last active), but hopefully this relatively simple plugin has demonstrated how the Heartbeat API works.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.