Skip to content

Slots Communication

Each slot of your extension runs in its own iframe. To send data between slots, the platform provides a whisper mechanism — a messaging system that lets your extension frames communicate with each other.

There are two whisper scopes:

RequestEventScope
v1.ext.whisperv1.ext.whisperedAll clients — broadcasts to every user (viewers + model) who has this extension loaded in the stream. Goes through the server.
v1.ext.whisper.localv1.ext.whisperedCurrent browser tab only — reaches other iframes of the same extension within the same tab. Stays client-side.

v1.ext.whisper (Broadcast)

Sends a message through the server to all clients in the stream that have this extension loaded. Every slot iframe of every user receives the v1.ext.whispered event.

When a user sends a broadcast whisper during a public show, the paymentData field is required. Obtain it from the v1.payment.tokens.spend.succeeded event. The model can whisper without paymentData. See Whisper with Payment Data for the full flow.

Use this when you need to synchronize state across all users — for example, broadcasting a game event, updating a shared scoreboard, or notifying everyone about a state change.

Sending

js
await ext.makeRequest('v1.ext.whisper', {
  data: {
    type: 'GAME_STARTED',
    round: 1,
  },
});

Receiving

js
ext.subscribe('v1.ext.whispered', (data) => {
  if (data.type === 'GAME_STARTED') {
    foo(data.round);
  }
});

v1.ext.whisper.local (Local)

Sends a message to other iframes of the same extension within the current browser tab. The message does not leave the client — it is not sent to the server and other users will not receive it.

Use this for coordination between your own slots — for example, the EXTENSION_SLOT_BACKGROUND slot telling EXTENSION_SLOT_RIGHT_OVERLAY to update its UI, or EXTENSION_SLOT_MAIN_GAME_FUN notifying EXTENSION_SLOT_BACKGROUND that the user performed an action.

Sending

js
await ext.makeRequest('v1.ext.whisper.local', {
  data: {
    type: 'UPDATE_UI',
    payload: { score: 42 },
  },
});

Receiving

js
ext.subscribe('v1.ext.whispered', (data) => {
  if (data.type === 'UPDATE_UI') {
    bar(data.payload.score);
  }
});

When to Use Which

ScenarioRequest
Notify all viewers about a game eventv1.ext.whisper
Sync shared state (scoreboard, timer) across all usersv1.ext.whisper
Coordinate between your own slots in the same tabv1.ext.whisper.local
EXTENSION_SLOT_BACKGROUND slot instructing EXTENSION_SLOT_RIGHT_OVERLAY to re-renderv1.ext.whisper.local
Model's action should be visible to all viewersv1.ext.whisper

Data Format

The data field accepts any JSON-serializable object:

js
await ext.makeRequest('v1.ext.whisper.local', {
  data: {
    type: 'MY_EVENT',
    payload: { /* any JSON-serializable data */ },
  },
});

TIP

Use a type field in your whisper data to distinguish between different message types. This makes it easy to handle multiple message types in a single subscriber.

Example: Background Slot as Coordinator

A common pattern is to use the EXTENSION_SLOT_BACKGROUND slot as a central coordinator. Since it is never unmounted, it can maintain state and relay messages between visual slots.

js
// background slot
const ext = createExtHelper();

let gameState = { round: 0, scores: {} };

ext.subscribe('v1.ext.whispered', (data) => {
  if (data.type === 'PLAYER_ACTION') {
    gameState = bar(gameState, data);

    // relay updated state to local UI slots
    ext.makeRequest('v1.ext.whisper.local', {
      data: { type: 'STATE_UPDATE', state: gameState },
    });
  }
});
js
// EXTENSION_SLOT_RIGHT_OVERLAY slot
const ext = createExtHelper();

ext.subscribe('v1.ext.whispered', (data) => {
  if (data.type === 'STATE_UPDATE') {
    foo(data.state);
  }
});

Whisper with Payment Data

When a user sends a broadcast whisper in a public show, the platform requires paymentData to validate the request. This means the user must first spend tokens via v1.payment.tokens.spend, then pass the resulting paymentData into the whisper call.

Example

js
const ext = createExtHelper();

// 1. Request a token spend
await ext.makeRequest('v1.payment.tokens.spend', {
  tokensAmount: 10,
  tokensSpendData: { action: 'spin_wheel' },
});

// 2. On payment confirmation, send the whisper with paymentData
ext.subscribe('v1.payment.tokens.spend.succeeded', async (data) => {
  await ext.makeRequest('v1.ext.whisper', {
    data: { type: 'SPIN_RESULT', value: 7 },
    paymentData: data.paymentData,
  });
});

// 3. All clients receive the whispered event
ext.subscribe('v1.ext.whispered', (data) => {
  if (data.type === 'SPIN_RESULT') {
    showResult(data.value);
  }
});