When are join, leave, timeout and state-change events trigger for a client in channel presence?

A join event is fired when a user first subscribes to a channel.

A leave event is fired when the user cleanly exits (unsubscribes) from the channel.

A timeout event is fired when a connection to a channel is severed and the subscriber has not been seen in 320 seconds (just over 5 minutes). This timeout interval can be customized using the heartbeat and heartbeat interval settings (SDK v3.6 or later).

Note that sometimes connections are not closed cleanly, especially if there are internet connectivity issues when the browser or app is closed. In such cases, the subscription will time out within approximately 5 minutes and a timeout event will be fired instead of a leave event. And depending on the browser, closing a tab (rather than the browser) may not necessarily cause the user to unsubscribe from the channel and the connection is left open, until it times out.

state-change event will be fired anytime the state is changed using the state API (function signature varies by SDK). A state-change event is not fired when a user subscribes with state being passed in as a parameter of the subscribe call, rather, the state is passed along as part of the join event payload.

NOTE: There is a configurable property, Presence Announce Max, in the Presence panel in your account dashboard. This property is the occupancy threshold at which join, leave and timeout events are no longer fired as users subscribe and unsubscribe (or timeout) from channels. Instead, an occupancy count is sent every 10 seconds (the default setting for the Presence Interval property, which is also configurable in the Presence add-on panel in your account dashboard). However, if state is changed (via the state API), then a state-change event will ALWAYS be fired, regardless of this property's value and the current occupancy.