# Events

> Widget events for analytics and integrations, as callbacks and as window CustomEvents; payloads never contain personal data.

Source: https://shopassist.coec.dk/docs/widget/events · Updated 2026-10-01

Subscribe with `ShopAssist.on(event, callback)` or listen for the window event `shopassist:{event}` (a `CustomEvent` with the same `detail`). Payloads never contain message text, emails, identity or order data, or tokens.

```ts
/**
 * Events delivered to `on()` callbacks and dispatched as `window` CustomEvent `shopassist:{event}` with the same
 * `detail` (08 §15.3). Payloads never contain message text, emails, identity data, order data or tokens.
 */
interface ShopAssistEvents {
  ready: { status: WidgetStatus }
  open: { source: OpenSource }
  close: Record<string, never>
  "conversation.started": { conversation_id: string }
  "message.sent": { conversation_id: string; message_id: string; has_attachments: boolean; trigger: string | null }
  "message.received": {
    conversation_id: string
    message_id: string
    role: "assistant" | "agent" | "system"
    is_ai_generated: boolean
  }
  "product.clicked": { product_id: string; url: string }
  "cart.added": {
    client_action_id: string
    status: "succeeded" | "failed"
    lines: { variant_id: string; quantity: number }[]
  }
  "cart.updated": { items_count: number | null }
  "checkout.clicked": { url: string }
  "handoff.requested": { handoff_id: string }
  "handoff.state": { state: HandoffStateName }
  "lead.captured": { lead_id: string }
  "identity.changed": { level: IdentityLevel }
  "consent.changed": { preferences: boolean; analytics: boolean; marketing: boolean }
  error: { code: string }
}
```

```js
const off = ShopAssist.on("cart.added", ({ status, lines }) => {
  if (status === "succeeded") window.dataLayer?.push({ event: "assistant_add_to_cart", items: lines.length })
})
window.addEventListener("shopassist:checkout.clicked", (event) => console.log(event.detail.url))
```

Callbacks run in `try/catch`: an error in your code never affects the widget. Respect your shoppers' consent before forwarding events to analytics tools.
