> ## Documentation Index
> Fetch the complete documentation index at: https://docs.weav.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Programmable Chatbot

## Overview

The Weav Chatbot Widget is a lightweight, embeddable chat interface that lets you add AI-powered customer support to any website.

It renders a customizable launcher button that opens a chat interface in an iframe, and it can be controlled through a simple JavaScript API.

<Info>
  The configuration options below are to provide developers with more flexibility of the Weav chatbot experience. Most of these features can be controlled within the Weav application for non developers.
</Info>

## Features

* Fully customizable appearance, including colors, icons, text, position, and theme
* Mobile responsive with optimized layouts
* Accessible, including ARIA labels and keyboard support with the `Esc` key
* Lightweight with minimal performance impact
* Secure iframe isolation
* JavaScript API for initialization, teardown, and event handling

***

## Installation

### Basic usage

1. Include the widget script near the end of your `<body>` tag.
2. Call `window.WeavWidget.init()` once the script has loaded.

```html theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    if (!window.WeavWidget) {
      console.error('Weav Chat Widget failed to load')
      return
    }

    window.WeavWidget.init({
      agentSlug: '{agent slug}',
    })
  })
</script>
```

The widget automatically injects its mount node and lazy-loads the iframe the first time it opens.

## Quick start example

```html theme={null}
<!DOCTYPE html>
<html>
  <head>
    <title>My Website</title>
  </head>
  <body>
    <!-- Your page content -->

    <script src="https://app.weav.com/widget.js" defer></script>
    <script>
      document.addEventListener('DOMContentLoaded', () => {
        window.WeavWidget?.init({
          agentSlug: '{agent slug}',
          branding: {
            accent_color: '#007bff',
          },
        })
      })
    </script>
  </body>
</html>
```

***

## JavaScript API

Once loaded, the script registers a single global object: `window.WeavWidget`.

| Method                              | Description                                                                                                                                                               |
| :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `init(options?: InitializeOptions)` | Mounts the widget with the provided configuration. Calling `init()` again tears down the current instance and mounts a fresh one with the new options.                    |
| `destroy()`                         | Unmounts the widget, clears queued actions, and removes any DOM nodes created by the widget.                                                                              |
| `open()`                            | Programmatically opens the widget. Throws if called before `init()`.                                                                                                      |
| `close()`                           | Programmatically closes the widget. Throws if called before `init()`.                                                                                                     |
| `sendMessage(message: string)`      | Sends a message to the chat on behalf of the visitor. Call `open()` first if the widget is not already visible. Throws if called before `init()` or with an empty string. |
| `on(event, listener)`               | Subscribes to widget lifecycle events: `opened` and `closed`. Returns an unsubscribe function.                                                                            |
| `off(event, listener)`              | Unsubscribes a previously registered listener.                                                                                                                            |
| `isInitialized()`                   | Returns `true` when the widget is currently mounted.                                                                                                                      |

***

## Configuration options

Pass configuration through the object supplied to `init()`.

`agentSlug` is required. All other properties are optional.

### Top-level options

| Option           | Type          | Default      | Description                                                                                                                      |                                   |
| :--------------- | :------------ | :----------- | :------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `agentSlug`      | `string`      | **Required** | Unique identifier for your AI agent. You can get this from [https://app.weav.com/agents](https://app.weav.com/agents) → Chat tab |                                   |
| `launcherZIndex` | \`number      | string\`     | `2147483000`                                                                                                                     | CSS `z-index` for widget elements |
| `launcherHidden` | `boolean`     | `false`      | Hides the launcher button when set to `true`. The widget can still be opened programmatically with `open()`                      |                                   |
| `mountElement`   | `HTMLElement` | Auto-created | Optional DOM node to render into instead of creating one automatically                                                           |                                   |

### Branding options

Use the `branding` object to customize the launcher button.

| Option                  | Type     | Default   | Description                                      |                                                                               |
| :---------------------- | :------- | :-------- | :----------------------------------------------- | ----------------------------------------------------------------------------- |
| `branding.accent_color` | `string` | `#0f172a` | Primary accent color for the launcher background |                                                                               |
| `branding.icon`         | \`string | null\`    | `null`                                           | Icon shown on the launcher. Can be an emoji, text, or an image URL            |
| `branding.name`         | \`string | null\`    | `null`                                           | Name used in the launcher button ARIA label, such as `Chat with AI Assistant` |

### Widget options

Use the `widget` object to customize behavior and appearance.

| Option                       | Type     | Default        | Description                        |                                                |
| :--------------------------- | :------- | :------------- | :--------------------------------- | ---------------------------------------------- |
| `widget.mode`                | `enum`   | `light`        | Visual theme of the widget         |                                                |
| `widget.button_icon`         | `enum`   | `chat`         | Icon type for the launcher button  |                                                |
| `widget.button_position`     | `enum`   | `bottom-right` | Position of the launcher button    |                                                |
| `widget.welcome_message`     | \`string | null\`         | `Hello! How can I help you today?` | Welcome message shown in the chat interface    |
| `widget.message_placeholder` | \`string | null\`         | `Ask me anything...`               | Placeholder text for the message input         |
| `widget.footer_text`         | \`string | null\`         | `null`                             | Custom footer text shown in the chat interface |

***

## Widget modes

| Value   | Description                         |
| :------ | :---------------------------------- |
| `light` | Light theme with a white background |
| `dark`  | Dark theme with a dark background   |

## Button icons

| Value  | Description       |
| :----- | :---------------- |
| `chat` | Default chat icon |

## Button positions

| Value          | Description                         |
| :------------- | :---------------------------------- |
| `bottom-right` | Bottom-right corner of the viewport |
| `bottom-left`  | Bottom-left corner of the viewport  |

## Examples

### Minimal configuration

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({ agentSlug: '{agent slug}' })
  })
</script>
```

### Custom branding

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      branding: {
        accent_color: '#8b5cf6',
        icon: '🤖',
        name: 'AI Assistant',
      },
    })
  })
</script>
```

### Custom icon using an image URL

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      branding: {
        accent_color: '#10b981',
        icon: 'https://example.com/logo.png',
      },
    })
  })
</script>
```

### Left-aligned launcher button

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      widget: {
        button_position: 'bottom-left',
      },
    })
  })
</script>
```

### Dark mode widget

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      widget: {
        mode: 'dark',
      },
    })
  })
</script>
```

### Custom widget messages

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      widget: {
        welcome_message: 'Welcome! How can we assist you?',
        message_placeholder: 'Ask a question...',
        footer_text: 'Powered by Weav',
      },
    })
  })
</script>
```

### High z-index for complex sites

```text theme={null}
<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      launcherZIndex: 999999,
    })
  })
</script>
```

***

## Programmatic control

* Use `window.WeavWidget.open()` to open the widget without user interaction
* Use `window.WeavWidget.close()` to close it programmatically
* Use `window.WeavWidget.destroy()` to remove the widget entirely
* Use `window.WeavWidget.init(newOptions)` at any time to re-initialize the widget with updated configuration\\

Queued `open()` and `close()` calls made immediately after `init()` run as soon as the React tree is ready, so you do not need to wait for a callback.

***

## Events

Use `on()` and `off()` to react to widget lifecycle events.

```text theme={null}
<script>
  document.addEventListener('DOMContentLoaded', () => {
    const widget = window.WeavWidget
    if (!widget) return

    widget.init({ agentSlug: '{agent slug}' })

    const unsubscribeOpened = widget.on('opened', () => {
      console.log('Chat widget opened')
    })

    const unsubscribeClosed = widget.on('closed', () => {
      console.log('Chat widget closed')
    })

    // Later
    // unsubscribeOpened()
    // unsubscribeClosed()
  })
</script>
```

Listeners run inside a guard so thrown errors are logged without breaking other listeners.

***

## Custom mount point

Provide `mountElement` if you want to render the widget inside your own container.

```text theme={null}
<div id="weav-mount"></div>

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const mount = document.getElementById('weav-mount')

    window.WeavWidget?.init({
      agentSlug: '{agent slug}',
      mountElement: mount,
    })
  })
</script>
```

The widget clears the provided element before rendering. Calling `destroy()` leaves the element in place so you can reuse it for future mounts.

***

## Triggering the widget from custom elements

You can open the widget and optionally send a pre-filled message from any element on your page.

This is useful when you want buttons, links, or other UI elements to start a specific conversation.

### Open and send a message by element ID

```text theme={null}
<button id="my-id">Ask about getting started</button>

<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({ agentSlug: '{agent slug}' })

    document.getElementById('my-id')?.addEventListener('click', () => {
      WeavWidget.open()
      WeavWidget.sendMessage('How do I get started?')
    })
  })
</script>
```

### Open and send a message by class name

```text theme={null}
<button class="my-class">Ask about getting started</button>

<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({ agentSlug: '{agent slug}' })

    document.querySelector('.my-class')?.addEventListener('click', () => {
      WeavWidget.open()
      WeavWidget.sendMessage('How do I get started?')
    })
  })
</script>
```

### Multiple trigger buttons

You can attach different messages to different elements.

```text theme={null}
<button class="weav-trigger" data-message="How do I get started?">Getting Started</button>
<button class="weav-trigger" data-message="How do I reset my password?">Reset Password</button>
<button class="weav-trigger" data-message="What pricing plans are available?">Pricing</button>

<script src="https://app.weav.com/widget.js" defer></script>
<script>
  document.addEventListener('DOMContentLoaded', () => {
    window.WeavWidget?.init({ agentSlug: '{agent slug}' })

    document.querySelectorAll('.weav-trigger').forEach((button) => {
      button.addEventListener('click', () => {
        const message = button.getAttribute('data-message')

        WeavWidget.open()

        if (message) {
          WeavWidget.sendMessage(message)
        }
      })
    })
  })
</script>
```

***

## Advanced usage

### Programmatic control only

The launcher button is visible by default.

To hide it and control the widget entirely through JavaScript, set `launcherHidden: true` and use `open()` and `close()`.

```text theme={null}
<button id="contact-support">Contact support</button>

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const widget = window.WeavWidget
    if (!widget) return

    widget.init({
      agentSlug: '{agent slug}',
      launcherHidden: true,
    })

    document.getElementById('contact-support')?.addEventListener('click', () => {
      widget.open()
    })
  })
</script>
```

When `launcherHidden` is `true`, the launcher button is completely hidden and the widget can only be opened with `window.WeavWidget.open()`.

This is useful when you want to integrate the widget into your own custom UI.

### Re-initializing with new options

```text theme={null}
window.WeavWidget.destroy()

window.WeavWidget.init({
  agentSlug: '{agent slug}',
  branding: {
    accent_color: '#22d3ee',
  },
})
```

Re-initializing ensures updated configuration values are applied cleanly.
