Appearance
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.