# Event listeners

> Listen for real-time chat events in the browser with window.bookbag.addEventListener — user messages, assistant replies, and tool calls — and use webhooks for reliable server-side events.

Once the [embed script](/docs/developers/javascript-embed) is on your page it exposes a global, `window.bookbag`, that emits real-time chat events. Register listeners to drive analytics, route leads, sync your UI, or react when the agent calls a tool. For reliable server-side awareness (a lead was captured even if the tab closed), use [webhooks](/docs/developers/webhooks).

## Registering listeners

```javascript
window.bookbag.addEventListener(eventName, callback);
window.bookbag.removeEventListener(eventName, callback);
```

Each callback receives an event object of the shape `{ type, data }`.

> **STORE THE FUNCTION REFERENCE:** Pass the same function to `addEventListener` and `removeEventListener`. Inline anonymous functions can be added but never removed — keep a reference if you need to clean up on navigation.

## Available events

| Event | Fires when | data |
| --- | --- | --- |
| `user-message` | The visitor sends a message. | `{ content }` |
| `assistant-message` | The agent finishes replying. | `{ content, messageId }` |
| `tool-call` | The agent calls a tool / action. | `{ id, name, args, type }` |
| `tool-result` | A tool returns a result. | `{ toolCallId, name, result, type }` |

## Example

```javascript
function onUserMessage(e) {
  console.log("User said:", e.data.content);
  window.analytics?.track("chat_user_message", { text: e.data.content });
}
function onAssistantMessage(e) {
  console.log("Agent replied:", e.data.content);
}

window.bookbag.addEventListener("user-message", onUserMessage);
window.bookbag.addEventListener("assistant-message", onAssistantMessage);

// Later (e.g. on SPA route change):
window.bookbag.removeEventListener("user-message", onUserMessage);
```

## Reacting to tool calls

`tool-call` and `tool-result` let you observe what the agent is doing. On Shopify, the storefront [cart bridge](/docs/integrations/shopify) uses `tool-call` to add items to the live cart — you can hook the same event to fire analytics when the agent recommends or adds a product.

## Controlling the widget

The same global opens, closes, and resets the widget — see [JavaScript embed](/docs/developers/javascript-embed#control-the-widget-from-your-code) for `window.bookbag('open')`, `('close')`, `('toggle')`, and `('resetChat')`.

## Server: webhooks for reliable events

Browser events live only as long as the tab is open. For anything you must act on — a lead was captured, a conversation ended — use [webhooks](/docs/developers/webhooks): server-to-server, signed, and delivered regardless of the browser.

| You want to know when... | Listen for |
| --- | --- |
| A visitor leaves their email/phone | `lead.created` webhook |
| A conversation ends | `conversation.ended` webhook |
| An action/tool runs | `action.run` webhook |

- [JavaScript embed & SDK](/docs/developers/javascript-embed) — Install + window.bookbag control methods.
- [Identity verification](/docs/developers/identity-verification) — Tell the agent who the signed-in user is.
- [Webhook guide](/docs/developers/webhooks) — Reliable server-side events with signature verification.
