App Context events

Showing JavaScript examples.
Starting a new app? Use DataSync

DataSync is the successor to App Context. It does everything App Context does for users, channels, and memberships, and adds typed schemas, partial updates with ETags, field-level access control, and per-class expiry. Refer to How DataSync compares to App Context for a feature-by-feature comparison.

DataSync is currently available to new accounts and to accounts that are not actively using App Context. If your keysets already use App Context, keep using it for now. App Context remains fully supported and these pages stay accurate.

An App Context event is the real-time notification App Context sends when a user's, channel's, or membership's stored metadata changes.

It travels through the same subscription and event listener infrastructure as a message or a presence update, arriving through a handler PubNub's docs call onObjects. This page explains:

  • the fields the payload carries, and how they differ from the raw event PubNub puts on the wire
  • why the payload only ever reports set or delete, never a separate "created"
  • why the payload's entity-type field reads uuid instead of user
  • how the payload's data differs between a user, a channel, and a membership event
  • why one SDK delivers every App Context event to a single handler while another splits it into several
  • how the server-side events Events & Actions generates from the same change relate to this one

Receiving any of this requires App Context enabled on your keyset, and the matching User Metadata Events, Channel Metadata Events, or Membership Events toggle turned on for that entity type. For where each event type lands and how to turn those toggles on, refer to Real-time updates when metadata changes. For the procedure that registers a handler, refer to Event listeners.

SDKs unwrap the event before your handler sees it​

An App Context event starts life as an ordinary message on the wire. It's internally typed, so a client can tell it apart from a regular published message before inspecting the payload. That raw form nests the App Context-specific fields inside a message object, alongside a source and version marker that identify the API that produced it:

1{
2 "channel": "my_channel",
3 "message": {
4 "source": "objects",
5 "version": "2.0",
6 "event": "set",
7 "type": "channel",
8 "data": { "id": "my_channel", "name": "Main channel" }
9 },
10 "subscription": "my_channel",
11 "timetoken": "17511946699655811"
12}

Most SDKs flatten this before your handler sees it, promoting event, type, and data to top-level fields alongside the channel, subscription match, and timetoken:

FieldDescription
channelThe channel the event was delivered on
subscriptionThe channel group or wildcard subscription match, if any
timetokenWhen the change was recorded
publisherThe User ID that made the change
eventset or delete
typeWhich entity changed: uuid, channel, or membership
dataThe metadata that changed

Not every SDK flattens or exposes every field the same way.

JavaScript keeps the App Context payload under event.message. In an onObjects handler, read event.message.event, event.message.type, and event.message.data. The delivery metadata stays at the top level in event.channel, event.subscription, and event.timetoken.

Field names and types are per SDK, not platform-wide. For the exact shape your handler receives, refer to the API reference for your platform in Available SDKs.

An event only ever says set or delete​

event has exactly two values, and neither one distinguishes a brand-new record from a change to an existing one. Setting a user's metadata for the first time and updating it a week later both arrive as set. A subscriber that needs to tell "this user just joined" from "this user's profile changed" has to keep its own record of what it already knew. The event alone doesn't say.

That's a deliberate difference from the server-side events Events & Actions generates from the same underlying change, which do separate a first set from a later one. Refer to Client-side and server-side events observe the same change independently below.

Why type says uuid​

A change to a user's metadata reports type: "uuid" rather than type: "user". The value still identifies the same entity.

The data field's shape follows the entity​

data carries a different record depending on what type says changed. The following illustrates a set event for each entity type, matching the record shape the corresponding get call returns:

1{
2 "channel": "test-user-1",
3 "subscription": "test-user-1",
4 "timetoken": "17511946699655811",
5 "publisher": "test-user-1",
6 "event": "set",
7 "type": "uuid",
8 "data": {
9 "id": "test-user-1",
10 "name": "John Doe",
11 "email": "johndoe@pubnub.com",
12 "custom": null,
13 "updated": "2019-02-20T23:11:20.893755",
14 "eTag": "MDcyQ0REOTUtNEVBOC00QkY2LTgwOUUtNDkwQzI4MjgzMTcwCg=="
15 }
show all 16 lines

A delete event's data carries little or nothing, since the record it refers to no longer exists to describe. Field names inside data are per SDK like everything else on this page. Check your platform's API reference before relying on one literally.

One handler, or several, depending on your SDK​

Every other client-side event type gets one dedicated handler per type. App Context is the exception some SDKs make. Because one change can be a user, a channel, or a membership, an SDK hands it to you in one of three ways:

  • One combined handler. A single handler receives every entity type, and your code branches on type itself. Kotlin, C#, Swift, Objective-C, and Unity all follow this pattern.
  • Several separate handlers. One handler per entity, so your code never checks type at all. Java, Go, and Python all split this way, though the mechanism differs.
  • The same handler as any other message. Dart and PHP deliver an App Context event through the same generic handler you'd use for an ordinary published message. Your code has to inspect the payload itself to tell the two apart.

None of these change what data reaches you, only how many places you write code to receive it. The following shows each SDK's own listener code.

1const subscription = pubnub.channel('channel_1').subscription();
2
3subscription.onObjects = (event) => {
4 const { event: action, type, data } = event.message;
5
6 if (type === 'uuid') {
7 console.log('User metadata event:', action, data);
8 } else if (type === 'channel') {
9 console.log('Channel metadata event:', action, data);
10 } else if (type === 'membership') {
11 console.log('Membership event:', action, data);
12 }
13};
14
15subscription.subscribe();

Check your SDK's API reference in Available SDKs to confirm which pattern it follows and the exact fields its result carries.

Client-side and server-side events observe the same change independently​

The same set or delete that produces an onObjects event also generates a server-side event. Events & Actions can act on that event, for example by triggering a webhook or writing to a queue. These are two separate consumption paths for one underlying change, not one feeding the other. A client-side subscriber sees the event only if it's subscribed to the right channel and the keyset toggle for that entity is on. Events & Actions observes the platform directly instead, so it needs no subscription.

Events & Actions' CRUD event types name the same three entities, but split each into three distinct types instead of App Context's set and delete:

SourceEvent typeFires when
UsersUser createdUser metadata is set for the first time
UsersUser updatedExisting user metadata changes
UsersUser deletedUser metadata is removed
ChannelsChannel createdChannel metadata is set for the first time
ChannelsChannel updatedExisting channel metadata changes
ChannelsChannel deletedChannel metadata is removed
MembershipsMembership createdA membership record is set for the first time
MembershipsMembership updatedAn existing membership record changes
MembershipsMembership deletedA membership record is removed

The Users and Channels sources in Events & Actions also carry unrelated Presence-driven event types, such as a user's subscription starting or stopping. Only the CRUD-produced types listed above correspond to an App Context change. For the full event and action list, refer to Event / Action List.

Next steps​

  • App Context. The three entity types, how to turn on App Context, and where each event type is delivered.
  • Event listeners. How a handler is registered and what its scope is.
  • Events. How App Context events fit among PubNub's other client-side and server-side event types.
  • App Context filtering. Query App Context data instead of paging through everything.
  • Events & Actions. Configure a webhook, queue, or stream from a server-side event.
  • Core concepts. User IDs, channels, and memberships.

Was this page useful?

Last updated on