API v 1.2
JavaScript

Presence

Presence enables clients to be aware of other clients that are currently “present” on a channel. Each member present on a channel has a unique self-assigned client identifier and system-assigned connection identifier, along with an optional payload that can be used to describe the member’s status or attributes. Presence allows you to quickly build apps such as chat rooms and multiplayer games by automatically keeping track of who is present in real time across any device.

The Presence object provides a straightforward API to subscribe to presence events such as members entering or leaving, retrieve a list of members present, or register the connected client as “present” on a channel. Here is a simple presence example using the presence property of the Channel object to enter a channel and subscribe to presence events.

JavaScript
var realtime = new Ably.Realtime({ key: '<loading API key, please wait>', clientId: 'bob' } ); var channel = realtime.channels.get('mud-ate-ago'); channel.presence.subscribe('enter', function(member) { alert('Member ' + member.clientId + ' entered'); }); channel.presence.enter();
Demo Only
Copied!

Note that all examples on this page assume you are running them within an EventMachine reactor. Find out more in our Realtime usage documentation

If you would prefer to just dive into code and see some examples of how to use presence via the Realtime API, then we recommend you take a look at our Realtime tutorials.

In order to be present on a channel, a client must be identified by having a client ID, have permission to be present, and be attached to the channel. For simplicity, the library will implicitly attach to a channel when entering or subscribing to presence events. Clients are assigned a clientId when using token authentication, find out more about token authentication.

A single clientId may be present multiple times on the same channel via different client connections. As far as Ably is concerned, these are different members of the presence set for the channel, however they will be differentiated by their unique connectionId. For example, if a client with ID “Sarah” is connected to a chat channel on both a desktop and a mobile device simultaneously, “Sarah” will be present twice in the presence member set with the same client ID, yet will have two unique connection IDs. A member of the presence set is therefore unique by the combination of the clientId and connectionId strings.

Whenever a member enters or leaves a channel, or updates their member data, a presence event is emitted to all presence subscribers on that channel. Subscribing to presence events makes it incredibly easy to build an app that shows, in real time, any changes to clients connected to Ably and present on a channel.

The following presence events are emitted:

enter
A new member has entered the channel
leave
A member who was present has now left the channel. This may be a result of an explicit request to leave or implicitly when detaching from the channel. Alternatively, if a member’s connection is abruptly disconnected and they do not resume their connection within a minute, Ably treats this as a leave event as the client is no longer present
update
An already present member has updated their member data. Being notified of member data updates can be very useful, for example, it can be used to update the status of a user when they are typing a message
present
When subscribing to presence events on a channel that already has members present, this event is emitted for every member already present on the channel before the subscribe listener was registered

View a presence states and events example

In addition to the clientId for members on a channel, it is also possible to include data when entering a channel. Clients can update their data at any point which will be broadcasted to all presence subscribers as an update event.

JavaScript
/* Subscribe to presence enter events */ channel.presence.subscribe('enter', function(member) { console.log(member.data); // => not moving }); /* Subscribe to presence update events */ channel.presence.subscribe('update', function(member) { console.log(member.data); // => travelling North }); /* Enter this client with data and update once entered */ channel.presence.enter('not moving', function(err) { channel.presence.update('travelling North'); });
Copied!

The Presence object exposes a get method allowing a client to retrieve an array of all members present on the channel. The Ably client is responsible for keeping track of the presence set from the time that the channel is attached; an up to date presence set is pushed to the client following attach and the presence set is updated on each subsequent presence event. Thus get returns the already-known presence set retained in memory and does not trigger a new request to the Ably service.

JavaScript
channel.presence.get(function(err, members) { console.log('There are ' + members.length + ' members on this channel'); console.log('The first member has client ID: ' + members[0].clientId); });
Copied!

The Presence object exposes a history method allowing a client to retrieve historical presence events on the channel.

History provides access to instantaneous “live” history as well as the longer term persisted history for presence channels. If persisted history is enabled for the channel, then presence events will typically be stored for 24 – 72 hours. If persisted history is not enabled, Ably retains the last two minutes of presence event history in memory.

The following example retrieves the first two pages of historical presence events.

JavaScript
channel.attach(function() { var presence = channel.presence; presence.history({}, function(err, resultPage) { if(err) { console.log('Unable to get presence history; err = ' + err.message); } else { console.log(resultPage.items.length + ' presence events received in first page'); if(resultPage.hasNext()) { resultPage.next(function(err, nextPage) { ... }); } }); });
Copied!

See the presence history documentation for further details of the supported query parameters.

 Tip

Each unique clientId may only be present once when entering on behalf of another client as the unique identifier for each member in a presence set is the combined clientId and shared connectionId>

An Ably client instance might, if on an application server for example, publish messages and be present on channels on behalf of multiple distinct client IDs. The channel’s Presence object therefore also supports methods that enable presence messages to be emitted for a clientId specified at the time of the call, rather than implicitly based on the clientId specified when the library is instantiated or authenticated.

In order to be able to publish presence changes for arbitrary client IDs, the client library must have been instantiated either with an API key, or with a token bound to a wildcard client ID.

JavaScript
var rest = new Ably.Rest({ key: '<loading API key, please wait>' }); /* request a wildcard token */ rest.auth.requestToken({ clientId: '*' }, function(err, token) { var realtime = new Ably.Realtime({ token: token }); var channel = realtime.channels.get('realtime-chat'); channel.presence.subscribe('enter', function(member) { console.log(member.client_id + 'entered realtime-chat'); }); channel.presence.enterClient('Bob'); // => Bob entered realtime-chat channel.presence.enterClient('Mary'); // => Mary entered realtime-chat });
Demo Only
Copied!

Any time a channel is re-attached and the presence set is re-synced, e.g. after a short disconnection, the client will check whether any members it has entered into the presence set are there. If not, it will automatically re-enter them. This means that if a channel loses continuity (for example, because a client was disconnected from Ably for more than two minutes before reconnecting), then after the channel automatically re-attaches, any presence members it had previously entered will be restored.

The exception is if you use the recover feature to resume a previous connection with a fresh client library instance (for example, to have continuity over a page refresh). In that case you will need to explicitly re-enter presence after you re-attach to the channel, due to the loss of client library internal state.

Clients that are part of a presence set remain present for 15 seconds after they are abruptly disconnected, for example where the internet connection suddenly drops or the client is changing networks. This delay is to avoid repeated leave and enter events being sent when a client is experiencing an unstable connection.

The Ably client library will attempt to reconnect after a disconnect. If the connection is reestablished before 15 seconds have passed, a leave event will not be sent. If the connection is reestablished after 15 seconds, a leave event will be sent and the presence set will need to be rejoined.

Note that the 15 second delay from being removed from the presence set is only for abrupt or unplanned disconnects. If a client calls leave() or close() they immediately send a leave event.

The time taken before a leave event is sent in the case of an abrupt disconnect can be reduced to a minimum of 1 second by setting a value for remainPresentFor, in milliseconds. This property is set within the transportParams property of the clientOptions object.

It is important to note that it can initially take up to 30 seconds to identify that a client has been abruptly disconnected. Shorten the amount of time taken to identify abrupt disconnects using the heartbeatInterval property if your app needs to quickly identify presence set members being abruptly disconnected.

The following example code demonstrates establishing a connection to Ably with remainPresentFor set to 1 second:

JavaScript
const ably = new Ably.Realtime( { key: '<loading API key, please wait>', transportParams: { remainPresentFor: 1000 } } );
Demo Only
Copied!

View the Presence API Reference.