Skip to content

Events ​

The widget emits a small set of events through window.zeeker.on(event, handler). Handlers are called with a payload object specific to the event.

js
window.zeeker.on('ready', state => console.log(state));

Lifecycle ​

ready ​

Fired once when boot completes (config fetched, iframe loaded, public API drained).

ts
{ postId: string, communityName: string | null, mode: 'floating' | 'fixed' | 'anchor' | 'pill' | 'trigger' }

open ​

The slide-in panel was opened (or the anchor / fixed thread became visible). Payload:

ts
{ mode: 'floating' | 'fixed' | 'anchor' | 'pill' | 'trigger' }

close ​

Slide-in panel closed. Same payload shape as open.

Auth ​

auth ​

Fired whenever auth state flips, regardless of path (anonymous → signed in, signed in → signed out).

ts
{ isAuthenticated: boolean }

identify ​

Host called window.zeeker.identify(jwt). Fires immediately, before the JWT is exchanged.

ts
{ hasToken: boolean }

sso-required ​

The widget needs a fresh SSO assertion for sign-in or session renewal. Fetch a new JWT from your authenticated backend and call identify().

ts
{
  provider: string, // typically 'jwt-bridge'
  auto?: boolean,
  automatic?: boolean,
  reason?: 'session_refresh',
  communityId?: string,
  requestId?: string
}

auto is true for the initial automatic request on boot. automatic: true with reason: 'session_refresh' renews an existing session two minutes before its access token expires. Handle renewal silently while your publisher session remains signed in; do not open a login modal for an automatic request. Mint a fresh JWT each time, and call window.zeeker.logout() when the publisher signs out. Requests retry at most every 30 seconds while the page is visible.

auth-required ​

The embed is configured with host_managed sign-in and needs the host application to authenticate a gated read or action. The host should run its own login/session check, mint a community SSO JWT on its backend, and call window.zeeker.identify(jwt).

ts
{
  method: 'community_sso' | 'either',
  reason: string,
  requestId?: string,
  communityId?: string
}

requestId and communityId correlate requests originating in the active nested Zeeker surface. Use the public event; do not listen for or forward raw iframe messages.

sso-success ​

The SSO JWT was exchanged successfully. The widget is now acting as your user.

ts
{ user: { id: string, username: string, name: string, avatar_url?: string } | null }

sso-error ​

Exchange failed. Payload contains a human-readable error.

ts
{ error: string }

sso-pending ​

Zeeker ID is completing a first-time profile or existing-account attachment.

ts
{ kind: 'onboarding' | 'attach' }

sso-cancelled ​

The user dismissed an existing-account attachment. First-time account creation does not expose a dismiss action.

ts
{ kind: 'attach' }

logout ​

Host called window.zeeker.logout() or the session expired.

No payload.

Interactions ​

reaction ​

The visitor sent or removed a reaction. The event is emitted after the Social API confirms the mutation; failed attempts are not emitted.

ts
{ type: string, removed: boolean }

reply ​

The visitor posted a reply. The event is emitted after the Social API confirms the reply and includes the committed post ID.

ts
{ postId: string }

reply-count ​

The reply count for the bound post changed (live websocket update).

ts
{ postId: string, count: number }

save ​

The visitor saved the post.

ts
{ postId: string, saved: boolean }

theme ​

The widget's effective theme changed. Host color-scheme changes produce this only when the embed theme is Auto; an explicit Light or Dark embed remains fixed.

ts
{ theme: 'light' | 'dark' }

Custom analytics integration ​

A common pattern is to forward widget events to your own analytics:

js
window.zeeker?.on('ready',    ev => analytics.track('zeeker_widget_ready', ev));
window.zeeker?.on('open',     ev => analytics.track('zeeker_widget_open',  ev));
window.zeeker?.on('reaction', ev => analytics.track('zeeker_reaction',     ev));
window.zeeker?.on('reply',    ev => analytics.track('zeeker_reply',        ev));

The widget already records config-wide daily telemetry server-side, including impressions, trigger and nudge clicks, panel opens/closes, real chat opens, and successful reply/reaction creations. Hidden action frames, unopened preloads, and signed dashboard previews do not create view/open telemetry. The public events above let you correlate activity with your own page-level funnels; Zeeker's config aggregate does not retain host-page URLs or visitor IDs.