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

# Chat widget quickstart

> Add the Circuit chat widget to your website: create an API key, allow your domains, and paste one script tag.

This guide takes you from nothing to a working chat widget on your site.

## Set up the widget

<Steps>
  <Step title="Create a chatbot key">
    In Circuit, open the agent you want to embed and go to its Chatbot settings. Create a new chatbot key with a descriptive name, for example "Company website".

    <Warning>
      The API key is visible in your page's HTML source. The allowed domains list you add in the next step is the control that limits which sites can use it.
    </Warning>
  </Step>

  <Step title="Add your domains to the allowed list">
    In the Allowed Website Domains section, add the hostname of every site that will embed the widget, for example `www.example.com`.

    This step is required. The server checks the `Origin` header on every request and rejects any hostname not on the list with 403. A key with an empty list rejects all requests.

    Domain matching rules:

    * Enter hostnames only: `www.example.com`, not `https://www.example.com` or `www.example.com:443`.
    * Each hostname must match exactly. `example.com` does not cover `www.example.com`. Add both if you serve both.
    * Matching is case-insensitive and ignores ports.
    * For local testing, add `localhost`.
  </Step>

  <Step title="Copy the script tag">
    The Chat Widget HTML section on the Chatbot settings page shows a ready-to-copy `<script>` tag. Paste it inside the `<body>` of your page, ideally near the closing tag:

    ```html theme={null}
    <script src="https://chat-embed.circuit.ai/launcher.js?apiKey=YOUR_AGENT_KEY" async></script>
    ```

    The `async` attribute keeps it off your critical render path. The script URL is stable and never changes.
  </Step>

  <Step title="Verify it works">
    Open your site in a browser. A bubble should appear in the corner of the page. Click it, send a test question, and confirm the agent streams back an answer.

    If the bubble is missing or messages fail, see [troubleshooting](/it/chat-widget/troubleshooting).
  </Step>
</Steps>

## Full page example

```html theme={null}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Company</title>
</head>
<body>
  <h1>Welcome to My Company</h1>
  <p>Click the chat button to ask a question.</p>

  <script src="https://chat-embed.circuit.ai/launcher.js?apiKey=YOUR_AGENT_KEY" async></script>
</body>
</html>
```

## Framework installs

The widget is framework-agnostic. Any approach that puts the script tag in the rendered page works.

<CodeGroup>
  ```html Plain HTML theme={null}
  <!-- Inside <body>, near the closing </body> -->
  <script src="https://chat-embed.circuit.ai/launcher.js?apiKey=YOUR_AGENT_KEY" async></script>
  ```

  ```tsx React theme={null}
  // Load once at the app root.
  import { useEffect } from 'react';

  export function CircuitChatWidget() {
    useEffect(() => {
      if (document.querySelector('script[src*="chat-embed.circuit.ai"]')) return;
      const script = document.createElement('script');
      script.src =
        'https://chat-embed.circuit.ai/launcher.js?apiKey=YOUR_AGENT_KEY';
      script.async = true;
      document.body.appendChild(script);
    }, []);

    return null;
  }
  ```

  ```tsx Next.js theme={null}
  // app/layout.tsx (App Router)
  import Script from 'next/script';

  export default function RootLayout({ children }: { children: React.ReactNode }) {
    return (
      <html lang="en">
        <body>
          {children}
          <Script
            src="https://chat-embed.circuit.ai/launcher.js?apiKey=YOUR_AGENT_KEY"
            strategy="lazyOnload"
          />
        </body>
      </html>
    );
  }
  ```
</CodeGroup>

<Note>
  In single-page apps, load the script once at the application root rather than inside a routed page component. The widget persists across client-side navigation. Re-injecting the script tag has no effect because the launcher is idempotent.
</Note>

## CMS and tag manager installs

<AccordionGroup>
  <Accordion title="Google Tag Manager">
    Create a new tag of type Custom HTML, paste the script tag, and set the trigger to All Pages. GTM injects the script on page load.
  </Accordion>

  <Accordion title="WordPress">
    Add the script tag to your theme's footer using your theme's custom code setting (often under Appearance) or a header/footer code plugin. Avoid pasting it into individual posts.
  </Accordion>

  <Accordion title="Shopify">
    In your admin, go to Online Store, then Themes, then Edit code. Open `theme.liquid` and paste the script tag immediately before the closing `</body>` tag. Add your `.myshopify.com` hostname to the allowed domains list if you need the widget to work in theme preview.
  </Accordion>

  <Accordion title="Webflow">
    In Site settings, open the Custom code tab and paste the script tag into the Footer code section, then publish. Add your `.webflow.io` staging hostname to the allowed domains list if you test on the staging URL.
  </Accordion>
</AccordionGroup>

Wildcard hostnames are not supported. Add exact hostnames, such as `your-store.myshopify.com` or `your-site.webflow.io`.

## Testing on staging and localhost

The allowed domains check applies everywhere the widget runs, including local and staging environments:

* Add `localhost` to test locally. Ports are ignored, so `localhost` covers `localhost:3000` and any other port.
* Add your staging hostname alongside your production hostname.
* Consider a separate key per environment so you can revoke or rotate it independently.

## Next steps

<CardGroup cols={2}>
  <Card title="Configuration" icon="sliders" href="/it/chat-widget/configuration">
    Customize branding, position, and welcome message.
  </Card>

  <Card title="Security" icon="shield" href="/it/chat-widget/security">
    What your security team needs to review before launch.
  </Card>
</CardGroup>
