Presence Events
PubNub triggers presence events as users come online or go offline from the application.
Clients can receive these events directly or use webhooks to keep a user's online/offline status up to date. Use these events to keep track of active/inactive users and the total occupancy of the channel.
Presence webhooks
PubNub can invoke a REST endpoint on your server when presence events occur. For more information, refer to Presence Webhooks.
Presence Event Types
There are five main types of presence events:
Events | Description |
---|---|
join | Fires when a user subscribes to a channel. |
leave | Fires when a user unsubscribes from a channel. |
timeout | Fires when a connection to a channel is lost and the subscriber hasn't been seen in 300 seconds. |
state-change | Fires anytime the user's state is changed. |
interval | Fires in interval mode to provide an occupancy count and optionally include delta changes. |
Add Presence Listeners
The Event listener and its handlers are briefly mentioned in the Application Setup section. Receiving the Presence events requires a Presence handler in the listener. Presence events will be received in this handler for all channels on which the client is subscribed and has enabled Presence events. In this handler, you have the following data available to you:
User ID / UUID
User ID is also referred to as UUID
/uuid
in some APIs and server responses but holds the value of the userId
parameter you set during initialization.
Event Data | Description |
---|---|
action | The Presence event action type: join, leave, timeout, state-change, interval |
channel | The channel on which the Presence action happened |
occupancy | The total number of subscribers on the channel when the event occurred |
uuid | The User ID of the client that published the message |
timetoken | The timetoken when the Presence action took place (when PubNub published the event) |
data | The state of the client that changed |
subscription | The channel group or wildcard subscription pattern that the channel belongs to (if applicable) |
- JavaScript
- Swift
- Objective-C
- Android
- C#
- Python
pubnub.addListener({
presence: function(event) {
var action = event.action;
var channelName = event.channel;
var occupancy = event.occupancy;
var eventTimetoken = event.timetoken;
var occupantUserId = event.uuid;
var state = event.state;
var subscribeManager = event.subscription;
}
});
let listener = SubscriptionListener()
// Add listener event callbacks
listener.didReceiveSubscription = { event in
switch event {
case presenceChanged(event):
let action = event.action
let channelName = event.channel
let occupancy = event.occupancy
let eventTimetoken = event.timetoken
let occupantUserId = event.uuid
let state = event.state
let subscribeManager = event.subscription
}
}
show all 18 lines- (void)pubnub:(PubNub *)pubnub didReceivePresenceEvent:(PNPresenceEventResult *)event {
NSString *action = event.data.presenceEvent;
NSString *channel = event.data.channel;
NSString *occupantUserId = event.data.presence.uuid;
NSString *eventTimetoken = event.data.presence.timetoken;
NSInteger *occupancy = event.data.presence.occupancy;
NSDictionary *state = event.data.presence.state;
}
Reminder that SubscribeCallback
is a Java Abstract class and requires that you implement all Abstract methods of the parent class. Below sample code is only showing one of the methods.
@Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
String action = presence.getEvent();
String channel = presence.getChannel();
String occupantUserId = presence.getUuid();
String eventTimetoken = presence.getTimetoken();
String occupancy = presence.getOccupancy();
Object state = presence.getState();
}
SubscribeCallbackExt subscribeCallback = new SubscribeCallbackExt(
delegate (Pubnub pubnubObj, PNPresenceEventResult<object> event) {
string action = event.GetEvent();
string channel = event.GetChannel();
string occupantUserId = event.GetPublisher();
long eventTimetoken = event.GetTimetoken();
int occupancy = event.GetOccupancy();
object state = event.GetUserMetaData();
}
);
pubnub.AddListener(subscribeCallback);
class SubscribeHandler(SubscribeCallback):
def presence(self, pubnub, event):
action = event.event
channel = event.channel
occupantUserId = event.uuid
eventTimetoken = event.timetoken
occupancy = event.occupancy
state = event.user_metadata
pubnub.add_listener(SubscribeHandler())
Subscribe to Presence Channel
Once you've added presence listeners, call subscribe
with the withPresence
flag enabled to receive presence events. Your client will now start receiving presence events in real time as users join and leave channels.
When you enable the withPresence
flag, the SDK automatically subscribes you to presence channels. These channels are sister channels where presence events are published by PubNub. If you don't wish to subscribe to all presence channels in your list, you can subscribe to individual channels by appending pnpres
to the channel name. For example, the presence channel for ch1
is ch1-pnpres
.
- JavaScript
- Swift
- Objective-C
- Android
- C#
- Python
pubnub.subscribe({
channels: ["chats.room1", "chats.room2"],
withPresence: true
});
pubnub.subscribe(
to: ["chats.room1", "chats.room2"],
withPresence: true
)
[self.pubnub subscribeToChannels: @[@"chats.room1", @"chats.room2"] withPresence:NO];
pubnub.subscribe()
.channels(Arrays.asList("chats.room1", "chats.room2"))
.withPresence().execute();
pubnub.Subscribe<string>()
.Channels(new string[] {"chats.room1", "chats.room2"})
.WithPresence()
.Execute();
pubnub.subscribe()\
.channels("chats.room1", "chats.room2")\
.with_presence()\
.execute()
If you want to subscribe to a bunch of channels at once but you only want to listen for presence events on some of them, you'll invoke two separate subscribe requests.
- JavaScript
- Swift
- Objective-C
- Android
- C#
- Python
// do listen for presence events for these channels
pubnub.subscribe({
channels: ["chats.team1", "chats.dept5"],
withPresence: true
});
// do not listen for presence events for these channels
pubnub.subscribe({channels: ["alerts.system", "alerts.team1"]});
// do listen for presence events for these channels
pubnub.subscribe(
to: ["chats.team1", "chats.dept5"]
withPresence: true
)
// do not listen for presence events for these channels
pubnub.subscribe(to: ["alerts.system", "alerts.team1"])
// do listen for presence events for these channels
[self.pubnub subscribeToChannels: @[@"chats.team1", @"chats.dept5"] withPresence:true];
// do not listen for presence events for these channels
[self.pubnub subscribeToChannels: @[@"chats.team1", @"chats.dept5"] withPresence:false];
// do listen for presence events for these channels
pubnub.subscribe()
.channels(Arrays.asList("chats.team1", "chats.dept5"))
.withPresence();
// do not listen for presence events for these channels
pubnub.subscribe().channels(Arrays.asList("alerts.system", "alerts.team1"));
// do listen for presence events for these channels
pubnub.Subscribe<string>()
.Channels(new string[] {"chats.team1", "chats.dept5"})
.WithPresence()
.Execute();
// do not listen for presence events for these channels
pubnub.Subscribe<string>()
.Channels(new string[] {"alerts.system", "alerts.team1"})
.Execute();
# do listen for presence events for these channels
pubnub.subscribe()\
.channels("chats.team1", "chats.dept5")\
.with_presence()\
.execute()
# do not listen for presence events for these channels
pubnub.subscribe().channels("alerts.system", "alerts.team1").execute()
Presence Event Modes
The channel presence mode indicates when presence events are triggered for that channel. There are two modes: announce and interval. The mode is determined by the occupancy count (total actively subscribed clients on that channel) in relation to the Presence Announce Max setting on the Admin Portal.
This feature prevents high occupancy channels from becoming too noisy with presence events. If you require the announce mode to be in effect past 100 occupants, please contact PubNub Support.
Announce Mode
If the channel occupancy is less than the Announce Max setting (defaults to 20), the channel is in announce mode. In this mode, join
, leave
, timeout
and state-change
events are sent to subscribed clients as and when they're triggered.
User ID / UUID
User ID is also referred to as UUID
/uuid
in some APIs and server responses but holds the value of the userId
parameter you set during initialization.
- Join
- Leave
- timeout
- State Change
{
"action": "join",
"channel": "chats.room1",
"subscribedChannel": "chats.room1-pnpres",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user123",
"timestamp": 1511946669
}
{
"action": "leave",
"channel": "chats.room1",
"subscribedChannel": "chats.room1-pnpres",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user123",
"timestamp": 1511946669
}
{
"action": "timeout",
"channel": "chats.room1",
"subscribedChannel": "chats.room1-pnpres",
"timetoken": "15119466699655811",
"occupancy": 2,
"uuid": "user123",
"timestamp": 1511946669
}
{
"action": "state-change",
"channel": "room-1",
"subscription": null,
"actualChannel": null,
"subscribedChannel": "room-1-pnpres",
"state": {
"mood": "grumpy"
},
"timetoken": "15119477895378127",
"occupancy": 5,
"uuid": "user1",
"timestamp": 1511947789
}
Interval Mode
When a channel's occupancy exceeds the Announce Max setting, the channel goes into interval mode. In this mode, the join
, leave
, timeout
events are replaced by an interval
event which is sent every few seconds with the total occupancy on the channel. The Interval setting is also configurable for the settings page.
Triggering state-change
events
state-change
eventsThe state-change
events are always triggered regardless of which presence mode is active on a channel.
Presence Deltas
Additionally, you can enable the Presence Deltas setting from the Admin Portal. When this flag is enabled, interval
events will also include a list of clients (User IDs) that joined, left or timed-out since the last interval
event. The following is a simple representation of a Presence Delta event payload.
{
"action": "interval",
"channel": "chats.megachat",
"occupancy": 27,
"join": ["user123","user88"],
"leave": ["user20", "user11", "user14"],
"timeout": ["user42"],
"subscribedChannel": "chats.megachat-pnpres",
"timestamp": 1511947739,
"timetoken": "15119477396210903"
}
If a Presence Delta payload exceeds 32KB, the here_now_refresh
flag indicates that you should use the Here Now API if you wish to retrieve the list of client User IDs that may have triggered a join, leave or timeout since the last interval.