# JavaScript embed

> Add the Bookbag chat widget to any website with a single script tag. Configure color and position with data attributes, and learn how the loader and iframe work.

The fastest way to put a Bookbag agent in front of customers is the embed script. It injects a chat bubble in the corner of your page; clicking it opens the agent in a sandboxed iframe. No build step, no API key.

> **LOOKING FOR THE NO-CODE PATH?:** The dashboard generates this exact snippet for you under Deploy. See [Website widget](/docs/deploy/web-widget) for the click-through setup.

## Install

Paste the script anywhere before the closing `</body>` tag, replacing `YOUR_AGENT_ID` with your agent's id:

```html
<script
  src="https://app.bookbag.ai/widget/embed"
  data-agent-id="YOUR_AGENT_ID"
  defer
></script>
```

> **CHECK:** Reload the page — a chat bubble appears in the corner and answers from your agent's knowledge.

## Configuration attributes

The loader reads optional `data-` attributes off its own `<script>` tag:

| Attribute | Required | Default | Description |
| --- | --- | --- | --- |
| data-agent-id | Yes | — | The numeric id of the agent to load. Without it the loader logs an error and does nothing. |
| data-color | No | #3b82f6 | The accent color of the launcher bubble (any CSS color). |
| data-position | No | right | `right` or `left` — which corner the bubble sits in. |

```html
<script
  src="https://app.bookbag.ai/widget/embed"
  data-agent-id="123"
  data-color="#0f766e"
  data-position="left"
  defer
></script>
```

> **BRAND COLORS AND WELCOME TEXT:** Most of the agent's appearance — avatar, welcome message, suggested prompts, and whether the "Powered by Bookbag" badge shows — is set in the dashboard and served from the agent's public config, not from the embed tag.

## How it works

1. **The loader runs** — The script at `/widget/embed` is a tiny loader. It finds its own tag, reads the data attributes, and creates a launcher button and a hidden iframe.
2. **The iframe holds the chat UI** — The iframe points at `/widget/frame?agentId=...`. Running the chat in an iframe isolates its styles and scripts from your page.
3. **Clicking toggles the panel** — The launcher button shows and hides the iframe. The chat UI inside talks to the public chat runtime to stream answers.

Because the chat lives in an iframe, it will not inherit or pollute your site's CSS. The launcher uses a very high `z-index` so it stays clickable above page content.

## Frameworks

In single-page apps, add the script once at the app shell level (e.g. in the document head/body template) rather than inside a component that mounts and unmounts. In Next.js, use the `next/script` component with the `afterInteractive` strategy and pass the data attributes through.

## Troubleshooting

**The bubble never appears.**

Open the console. If you see "[Bookbag] data-agent-id required", the `data-agent-id` attribute is missing or empty. Confirm the agent id is correct and the agent is not archived.

**It works locally but not in production.**

Check that your Content Security Policy allows loading the script from `app.bookbag.ai` and framing `app.bookbag.ai` (the chat runs in an iframe).

**Can I open or close the widget from my own code?**

See [Event listeners](/docs/developers/event-listeners) for the client-side patterns around the embedded widget.

- [Website widget setup](/docs/deploy/web-widget) — The dashboard walkthrough and appearance settings.
- [Event listeners](/docs/developers/event-listeners) — React to the widget in the browser.
- [Identity verification](/docs/developers/identity-verification) — Personalize chat for logged-in users.
