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

# Install on your site

> Embed your widget on your website. Single script tag, live in minutes.

<div className="simplified-only">
  Embedding Web Calling is one script tag, generated for you in Agent Studio.

  ## Step 1: Get your script tag

  1. Open your Web Calling widget under **Configure > Web Calling** in Agent Studio.
  2. Make sure [Styling and Content](/widgets/configure) are how you want them.
  3. Click **Save and publish**.
  4. Open the **Embed** tab.
  5. Copy the script tag. It looks like this:

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <script src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"></script>
  ```

  <Frame caption="Embed tab with the widget script tag">
    <img src="https://mintcdn.com/polyai/qUzW3UML6Ru8OVcR/images/widgets/embed-tab.png?fit=max&auto=format&n=qUzW3UML6Ru8OVcR&q=85&s=8ffbbd714fb4aa7ae12f9013a76710a6" alt="Embed tab with the widget script tag ready to copy" style={{ maxWidth: '720px', width: '100%', margin: '0 auto', display: 'block' }} width="2492" height="1502" data-path="images/widgets/embed-tab.png" />
  </Frame>

  The tag is bound to the widget's domain, variant, and environment. If any of those change, re-publish and re-embed.

  ## Step 2: Paste it on your site

  Pick one route. Most sites use the direct HTML embed.

  ### Option A: Direct HTML embed

  1. Open the HTML template that loads on **every page** (often your global layout or `index.html`).
  2. Paste the script tag **just before `</body>`**.
  3. Publish your website changes.

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <!DOCTYPE html>
  <html>
    <head>
      <!-- Your existing head content -->
    </head>
    <body>
      <!-- Your page content -->

      <!-- Paste the PolyAI widget script here, just before </body> -->
      <script src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"></script>
    </body>
  </html>
  ```

  You only embed the script once. Updates to styling, content, or the agent itself take effect on the next page load. No re-embed needed.

  <Note>
    Serve the host page over **HTTPS**. Browsers block microphone access on `http://`, so the call button stays disabled there.
  </Note>

  ### Option B: Tag Manager

  1. Open your tag manager (Google Tag Manager or similar) and create a new **Custom HTML** tag.
  2. Paste the script tag.
  3. Set the trigger to **All Pages** (or restrict to the pages where you want the widget).
  4. Publish the container.

  The widget appears on the next page load.

  <Note>
    Copy your actual script tag from **Configure > Web Calling > Embed**. The snippet here is illustrative.
  </Note>

  ## Step 3: Verify

  <Steps>
    <Step title="Widget appears">
      The launcher renders in the bottom-right corner of pages where the script is embedded.
    </Step>

    <Step title="Widget opens">
      Click the launcher; the call panel opens.
    </Step>

    <Step title="Place a call">
      Click **Start call**. The browser asks for microphone permission. Allow → the widget shows **Connecting…** then **In call** when the agent answers.
    </Step>
  </Steps>

  A few quick verification tips:

  * Open your site in a private/incognito window so you're not running on a cached script.
  * Hard-refresh (`Ctrl+Shift+R` / `Cmd+Shift+R`).
  * Test on a desktop browser (Chrome or Edge) and a mobile device (iOS Safari or Android Chrome).

  If something looks off, see [Troubleshooting](/widgets/troubleshooting).

  ## Cross-tab behavior

  If a visitor opens your site in multiple tabs, only one call can be active at a time. The widget writes a heartbeat to `localStorage`; other tabs show the call button disabled with a "Call active in another tab" message. Closing the active tab releases the lock within \~10 seconds. Automatic, no config.

  ## Re-embedding

  You only need to re-embed when **the script tag itself changes**. The Embed tab in Agent Studio shows a **Snippet changed** banner when that happens. Hand the new tag to your dev team or update your tag manager config.

  You do **not** re-embed when you change branding, CTA copy, disclaimer text, policy links, or the agent/variant. Those propagate on the next page load.
</div>

<div className="full-only">
  Once your widget is configured, getting it live is a single script tag. Paste it on your site, publish, and your visitors can start using it. The install flow is identical for Phone and Chat widgets.

  ## Installation methods

  Pick **one** route:

  * **Option A: Direct HTML embed**, recommended for most sites.
  * **Option B: Tag Manager**, when your organization manages scripts through Google Tag Manager or similar.

  <Tip>
    Not sure which route to take? Start with **Option A**. It's the fastest path to live.
  </Tip>

  ## Step 1: Generate a widget tag

  1. Go to **Configure > Web Calling** in Agent Studio and open your widget.
  2. Configure [Styling and Content](/widgets/configure).
  3. Click **Save and publish**.
  4. Open the **Embed** tab.
  5. Copy the unique script tag. It looks like this:

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <script src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"></script>
  ```

  <Frame caption="Embed tab with the widget script tag">
    <img src="https://mintcdn.com/polyai/qUzW3UML6Ru8OVcR/images/widgets/embed-tab.png?fit=max&auto=format&n=qUzW3UML6Ru8OVcR&q=85&s=8ffbbd714fb4aa7ae12f9013a76710a6" alt="Embed tab with the widget script tag ready to copy" style={{ maxWidth: '720px', width: '100%', margin: '0 auto', display: 'block' }} width="2492" height="1502" data-path="images/widgets/embed-tab.png" />
  </Frame>

  The tag is bound to the widget's domain, variant, and environment. If any of those change, re-publish and re-embed.

  ## Option A: Direct HTML embed

  1. Open the HTML template that loads on **every page** (often called your global layout, base template, or `index.html`).
  2. Paste the script tag **just before the closing `</body>` tag**.
  3. Publish your website changes.

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <!DOCTYPE html>
  <html>
    <head>
      <!-- Your existing head content -->
    </head>
    <body>
      <!-- Your page content -->

      <!-- Paste the PolyAI widget script here, just before </body> -->
      <script src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"></script>
    </body>
  </html>
  ```

  You only need to embed the script once. Updates to styling, content, or the agent take effect on the next page load. No re-embed required.

  <Note>
    Serve the host page over **HTTPS**. Browsers block microphone access on `http://`, so Phone widget call buttons stay disabled there.
  </Note>

  ## Option B: Tag Manager

  1. Open your tag manager (e.g., Google Tag Manager) and create a new **Custom HTML** tag.
  2. Paste the script tag.
  3. Set the trigger to **All Pages** (or restrict to the pages where you want the widget).
  4. Publish the container.

  The widget appears on the next page load.

  <Note>
    Copy your actual script tag from **Configure > Web Calling > Embed**. The snippet here is illustrative.
  </Note>

  ## Script-tag attributes (Chat widgets)

  Chat widgets accept optional `data-*` attributes on the `<script>` tag, read once at load time, no JavaScript required. Phone widgets don't use these. Their behavior is configured entirely in the editor and driven by call state.

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <script
    src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"
    data-platform="web"
    data-render-mode="default"
    data-auto-open="false"
    data-show-icon="true"
    data-show-header="true"
  ></script>
  ```

  | Attribute          | Values                  | Default   | Effect                                                                                                                                                                                                                                                    |
  | ------------------ | ----------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `data-platform`    | `web`, `ios`, `android` | `web`     | Use `ios` or `android` inside a native WebView (`WKWebView` on iOS, `WebView` on Android). `ios` automatically applies fullscreen and hides the header. Sessions are reported as `ios-web` or `android-web` to distinguish them from native SDK sessions. |
  | `data-render-mode` | `default`, `fullscreen` | `default` | `fullscreen` makes the chat fill the viewport, useful for dedicated chat pages or native app screens.                                                                                                                                                     |
  | `data-auto-open`   | `true`, `false`         | `false`   | Opens the chat as soon as the widget initializes.                                                                                                                                                                                                         |
  | `data-show-icon`   | `true`, `false`         | `true`    | Show or hide the floating launcher. Combine with a custom button calling `WebchatAPI.openWidget()` for a bespoke trigger.                                                                                                                                 |
  | `data-show-header` | `true`, `false`         | `true`    | Show or hide the chat header. Defaults to `false` when `data-platform="ios"`.                                                                                                                                                                             |

  ## Widget positioning (Chat widgets)

  After installing a Chat widget, you can control its position with CSS. The widget renders inside a `#poly-ai-chat` element. Add a `<style>` block in the `<body>` of your page:

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <style>
    #poly-ai-chat {
      bottom: 1rem;
      right: 1rem;
    }
  </style>
  ```

  Adjust `bottom` and `right` to avoid overlap with cookie banners, navigation bars, or other fixed UI.

  ### Widget icon sizes

  | Device  | Icon size   |
  | ------- | ----------- |
  | Desktop | 60px × 60px |
  | Mobile  | 44px × 44px |

  Account for these dimensions when positioning the widget.

  ## Re-embedding

  You only need to re-embed when **the script tag itself changes**. The Embed tab in Agent Studio shows a **Snippet changed** banner if the published script differs from the version your team has on the site. Hand the new tag to your dev team or update your tag manager configuration.

  You do **not** need to re-embed when you change:

  * Branding (header text, logo, agent name, primary color).
  * CTA copy or disclaimer.
  * Policy links.
  * The agent or variant the widget connects to (within the same widget configuration).

  ## Verifying the install

  <Steps>
    <Step title="Widget appears">
      The launcher renders in the bottom-right corner of pages where the script is embedded.
    </Step>

    <Step title="Widget opens">
      Clicking the launcher opens the widget panel.
    </Step>

    <Step title="Phone: place a call">
      Click **Start call**. The browser asks for microphone permission. Allow → the widget shows **Connecting…** then **In call** when your agent answers.
    </Step>

    <Step title="Chat: send a message">
      Type a message. The agent should respond with the configured greeting and answer subsequent messages.
    </Step>
  </Steps>

  ### Quick verification tips

  1. Open your website in a **private/incognito window**.
  2. Hard refresh (`Ctrl+Shift+R` or `Cmd+Shift+R`) to bypass cached scripts.
  3. Test on a desktop browser (Chrome or Edge) and a mobile device (iOS Safari or Android Chrome).

  If anything looks off, see [Troubleshooting](/widgets/troubleshooting).

  ## Cross-tab behavior (Phone widgets)

  When a visitor opens your site in multiple tabs, Web Calling keeps things clean: one active call per browser. The widget writes a heartbeat to `localStorage` while a call is live, and other tabs show the call button disabled with a "Call active in another tab" message. Closing the active tab releases the lock within \~10 seconds.

  It's automatic. No configuration needed.

  ## Next steps

  <CardGroup cols={2}>
    <Card title="Test your widget" href="/widgets/test" icon="circle-play">
      Walk through a real call from the editor preview link (Phone widgets).
    </Card>

    <Card title="Troubleshooting" href="/widgets/troubleshooting" icon="wrench">
      Common installation issues and fixes.
    </Card>
  </CardGroup>
</div>
