How can you detect when a user goes online or offline, or how do you know whether a client device is connected and when it disconnects? PubNub presence lets you track who is connected to your channels in real-time and alerts you when their connection status changes.
Please note that how the presence options are displayed in the portal has changed since this video was recorded, however the options retain the same names and functionality.
The presence system is very flexible and enables use cases such as:
- Monitoring when users join or leave a chat conversation
- Detecting when a user is online or offline
- Determining whether an IoT device is connected and available
- Counting how many clients are connected to a channel (channel occupancy count)
You can also define some state information (metadata) to accompany the client’s presence that will be received by all interested recipients; for example, although the client’s presence is ‘online,’ the User can choose to set their custom status as ‘away’ or ‘do not disturb.’
To enable PubNub presence, log into the admin portal, navigate to the app and keyset you want to enable presence on, select the 'Presence' option from the Configuration section, and toggle the presence switch in that keyset’s configuration screen:
You will be prompted to confirm that you want to enable presence.
Be aware that enabling presence can result in significantly more transactions, especially for those on a transaction-based pricing plan. To control the number of transactions, you can use the ‘Presence management’ feature, explained later in this article.
Be sure to save any changes whenever you make modifications to your keyset configuration.
Announce Mode
Once enabled, PubNub will automatically generate presence events as clients (users or devices) subscribe to or unsubscribe from any channel.
When a client subscribes to a channel, it will generate a join
event:
{
"channel": "<name of channel that was joined>",
"action": "join",
"occupancy": 2, // Channel occupancy
"uuid": "<userid of client who joined>",
"timetoken”: "<When the join occurred>"
}
When a client unsubscribes from a channel, it will generate a leave
event:
{
"channel": "<name of channel that was left>",
"action": "leave",
"occupancy": 1, // Channel occupancy
"uuid": "<userid of client who left>",
"timetoken": “<When the leave occurred>"
}
Consider a web client connected to a channel, and the user forcibly closes the tab instead of allowing the client to unsubscribe:
If the client does not explicitly unsubscribe but is detected as not being present after a period of time (300 seconds by default), a timeout
event is triggered:
{
"channel": "<name of channel connection that timed out>",
"action": "timeout",
"occupancy":1, // Channel occupancy
"uuid": "<userid of client who timed out>",
"timetoken": "<When the timeout occurred>"
}
Generate Leave on TCP FIN or RST
Instead of waiting for the timeout event in the above scenario, another option is to detect at the network level when a client leaves the channel. By enabling the ‘Generate Leave on TCP FIN or RST’ option on the keyset, forcibly closing the browser tab in this scenario will now generate a leave
event which is fired immediately, instead of a timeout
event.
Debounce
Sometimes, clients will rapidly join
and leave
channels, either because of network issues or your application design. To avoid excessive join
and leave
events, specify a debounce
value in seconds. After a client generates a join
event, they will not be allowed to generate another join
event for another two seconds, for example.
Interval Mode
Announce Max
The join
and leave
events will triggered immediately as long as the number of clients in the channel remains below the ‘Announce Max’ setting, which defaults to 20.
As the number of occupants in a channel increases, the number of join
and leave
events will also increase, but at some point, it becomes wasteful for a client to attempt to maintain all these events in real-time. Consider a group chat with 200 participants; does the client need to update the online state of every one of those participants as they go online or offline? It would be more information than the human user could keep track of.
You can configure Announce Max
between 1 and 100. Once the number of clients in a channel exceeds ‘Announce Max,’ the join,
leave,
and timeout
events are no longer generated but are replaced by the interval
event:
{
"channel: "<name of channel the event applies to>",
"action": "interval",
"occupancy": 4, // Channel occupancy
"timetoken": "<When the interval event occurred>"
}
Interval
You can configure how often the interval event will fire by modifying the Interval
configuration option. Values between 10 seconds to 300 seconds (5 minutes) are allowed.
The interval
event will only notify you of the channel occupancy unless you enable ‘Presence Deltas’
Presence Deltas
With ‘Presence Deltas’ enabled, the interval
event will also include information about which users have joined or left the channel since the previous interval
event.
{
"channel": "<name of channel the event applies to>",
"action": "interval",
"occupancy": 3, // Channel occupancy
"join": ["member4"],
"leave": ["member3"],
"timetoken": "<When the interval event occurred>"
}
Other Settings
Active Notice Channel
You might not be interested in how many clients are connected to a channel or who those clients are, but instead, you might only care about whether or not anybody is subscribed to a channel. If a channel has 0 subscribers, it is considered inactive
. A channel with 1 or more subscribers is considered active
.
You can register to receive notice when a channel becomes ‘active’ or ‘inactive’ by specifying an ‘Active Notice Channel’.
If specified, you will receive messages on this channel (in this example, the channel name that receives the messages is "notice_channel"):
{
"channel": "<name of the channel which has become active or inactive>",
"status": "active", // or inactive
"precise_timestamp": "<When the interval event occurred>"
}
Note that active
events are sent as soon as the channel occupancy rises above 0, but channel inactive
events will only fire if the channel has an occupancy of 0 for 300 seconds or more.
Stream Filtering
The option to disable stream filtering is retained for legacy reasons, and developers will gain little benefit from turning this setting off. Stream Filtering will include Presence metadata in events published to the presence channels, allowing client filters to be applied to these presence events. Disabling stream filtering does not reduce the number of presence events; it only allows the client to filter out which events they receive - to reduce the number of presence events you should use Presence Management, explained later in this article.
Webhooks
Previously, the keyset configuration page allowed you to specify multiple webhooks that would be fired when any of the following events occurred:
join
event firedleave
event firedtimeout
event firedinterval
event firedstate-change
event firedchannel active
orchannel inactive
event fired.
These webhooks are no longer part of the keyset configuration but have been migrated to the Events & Actions feature. Webhooks will not be discussed in the scope of this article, but for more information, please refer to the Webhook Payload action section of the Events & Actions documentation.
State Change
If you want to exchange some metadata associated with the client’s presence, the best way to achieve that is with the Presence State feature. For example, although the join
and leave
events discussed previously will tell you whether the client is online or offline, that does not let you know if the user is ‘busy’ or ‘do not disturb.’
A client can use the PubNub SDK to set a custom state on a specific channel
or channel group
. Once set, this state is propagated to other clients and received as a state-change
event.
{
"channel": "<name of channel associated with the state change>",
"uuid": "<ID of client the state applies to>"
"action": "state-change",
"state": {<JSON Object defining the state>}
"occupancy": 3, // Channel occupancy
"timetoken": “<When the state change occurred>"
}
State change is very flexible and can be used to exchange any serializable data; for example, our collaboration demo uses presence state to notify listeners when a draw
event occurs, allowing a collaborative drawing application, with doodles being shown to all viewers in real time
"state": {"x": 5, "y": 10, "color":"#FFFF00"} // Example state payload for a drawing application
The only caveat with state-change events is that they do not persist, so they should only be used for ephemeral data or data each client is expected to keep track of.
Controlling which Events you receive using Presence Management
As mentioned earlier, it is easy for the number of presence events to get very large as your user base grows. To give you greater control over which events fire on any specified channel, we have introduced the self-service ‘Presence Management’ tool, which allows you to create rules that control which presence events will fire:
You can access the tool from the left-hand menu under the ‘BizOps Workspace’ section.
Please refer to the Presence Management documentation for a full description of how to configure your management rules, but in summary:
- Create a new rule; you can have multiple rules to fully define the presence events you want to trigger for your application.
- Specify the events you want this rule to control, including
join,
leave,
timeout,
state-change,
andinterval.
This article has covered what these rules are and when they fire. - Specify a wildcard pattern to define the channel or channel groups that this rule applies to; for example
personal-*
will apply to all channels that startpersonal-
- Click ‘Create’ and define the order in which your rules should apply.
Presence Management through the PubNub API
You can receive presence events through any of our SDKs. This article has focused chiefly on Presence events, which are received through the SDK event listener, but our APIs also support additional functions to determine who is listening on a specific channel (here now
) and where a particular user is subscribed (where now
)
In JavaScript, the hereNow API can be called as follows to determine who is subscribed to the specified channel:
1 2 3 4 5 6 7 8 9 10
try { const result = await pubnub.hereNow({ channels: ["my_channel"], includeState: true, includeUUIDs: true }); console.log(“total occupancy: “ + result.totalOccupancy) } catch (status) { console.log(status); }
More Resources
Presence is one of the most valuable and flexible features of the PubNub platform. Knowing exactly who is online and having that status update in real-time has enabled our customers to build some intriguing solutions over the years.
- Our Presence Basics documentation is a good starting point to understand the concepts of Presence.
- Our Subscribe documentation will give examples showing how to subscribe to a channel with
presence
enabled and refer to the SDK-specific documentation for API examples showing how to add a listener callback for presence events (e.g., this page for our JavaScript SDK). - To get more hands-on, most of our tutorials will include presence, and a good starting place for new developers is our Getting Started tutorial, which covers several programming languages. The tutorials will also cover other presence features, such as the ‘here now’ API, to determine who is listening on a channel.
Finally, if you need help or support, feel free to reach out to our dedicated pubnub support team or email our developer relations team at devrel@pubnub.com