onEvent callback. Both hosted surfaces accept it: WaniWani.chat.init({ onEvent }) on the script embed, and the onEvent prop on the React component.
The embed mounts in your page’s DOM (the shadow root isolates styles only), so the callback runs in your page’s own JS context. Forward events straight into window.amplitude, window.analytics, or gtag and your page-side analytics SDK attaches its own user identity automatically — no server-side identity plumbing, and no Amplitude/Segment SDK is ever loaded inside the widget.
When to use which channel.
onEvent mirrors widget activity into your analytics on the host page — it never leaves the browser unless your callback sends it somewhere. It is separate from platform ingest tracking (WaniWani.chat.track, funnel events, the typed event catalog), which sends events to the Waniwani platform for funnel analytics. Use onEvent to see chat activity next to your existing product analytics; use tracking events to power Waniwani funnels. The two channels are independent and can be used together.The events
Do not assume
chat.opened precedes the first message.sent: a send from the docked bar opens the panel and sends in one action, and the open transition is reported after the send.
Separate from the
track() taxonomy. Some onEvent names (session.started, link.clicked) also exist as event names in the hosted track() funnel taxonomy — same concepts, but a separate client-side channel with different payload shapes. onEvent events are not client.track() events, do not feed the platform funnel dashboard, and should not be forwarded into client.track() as-is even where names coincide.The payload
Every callback receives aWidgetEvent — exported from @waniwani/sdk/chat alongside WidgetEventName and WidgetMode:
mode is the embed surface: "floating" for the floating bar, "inline" for an in-page mount. <WaniwaniChat> reports "inline" — it is an in-page mount, and this is the same mode tag its server-side events (chat requests, page.viewed) carry, so both streams correlate.
Narrowing on name types properties automatically:
Script embed → Amplitude
onEvent is programmatic-only on the script embed: a function cannot be expressed as a data-* attribute, so pass it to WaniWani.chat.init().
React → Segment
TheWaniwaniChat component takes the same callback as an onEvent prop (chat.opened/chat.closed are floating-embed-only and never fire here):
Privacy
Message content never passes through this channel.message.sent and message.received tell the host that a message was exchanged, never what was said. The one text field that does flow through is suggestion.clicked’s text — suggestion pills are operator-authored config, not user input.