---
sidebar_position: 3
---

# Presence

A presence channel (`presence-…`) lists who is on it, to everyone on it: who is reading a post, who is in a support queue, who is typing.

## Who is a member

Your callback decides, as for a private channel ([channels](channels.md)), and also says what the others see:

```php
wordplus_realtime()->channel( 'presence-board-', function ( $user_id, $channel ) {
	if ( $user_id <= 0 ) {
		return false;
	}

	$user = get_userdata( $user_id );

	return array( 'info' => array( 'name' => $user->display_name, 'avatar' => get_avatar_url( $user_id ) ) );
} );
```

- **A member is a signed-in user,** under their user id, with their display name as `info` unless your answer gives other `info`.
- **A visitor needs an id of yours:** answer `array( 'id' => 'guest-81f2', 'info' => … )`. A visitor without one is refused a presence channel (`forbidden`).
- **`info`** is any JSON up to 1 KB. Everyone on the channel sees it, so put nothing in it the channel's members shouldn't see. It travels sealed with the channel's key, so the realtime servers don't ([encryption](encryption.md)).
- **For a user's name and avatar on any page,** whatever the channel, read the site's directory with `rt.users( ids )` ([encryption](encryption.md#the-sites-users)).

## In the browser

```js
const board = rt.subscribe( 'presence-board-1' );

board.on( 'realtime:subscribed', ( members ) => drawMembers( members ) );   // [ { id, info } ]
board.on( 'realtime:member_added', ( member ) => addMember( member ) );       // { id, info }
board.on( 'realtime:member_removed', ( member ) => removeMember( member.id ) );

board.members();      // everyone on it now: [ { id, info } ]
board.memberCount;    // how many, counting those not listed
```

- **The first 100 members** come with the subscription, and `memberCount` counts them all. Members who join later are added as they come.
- **A user is one member** however many tabs, devices or plugins they're on it from. `realtime:member_added` comes with their first connection, `realtime:member_removed` with their last.
- **Moves don't show anyone leaving.** When the connection moves to another server, the new connection joins before the old one leaves.
- **A server that dies** has its members taken off by the cluster within seconds.

## From your server

`channel_info()` reads a channel as the server holds it:

```php
$info = wordplus_realtime()->channel_info( 'presence-board-1' );
// array( 'ok' => true, 'subscriptions' => 3, 'members' => array( 'count' => 2, 'list' => array( array( 'id' => '7', 'info' => array( 'name' => 'Ann' ) ), … ) ) )
```

## Limits

1,000 members a presence channel; past it, a subscription is refused with `full`.
