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

# Installation

> Add the Sagepilot Web SDK to a website, single-page app, tag manager, or Shopify store.

Install the widget once per page. After it loads, `window.ChatWidget` is available to your code.

## Find your widget key

1. In Sagepilot, open **Channels** and click your **Website Widget** channel.
2. Open **Embed Code**.
3. Copy the key from the launcher script. It has the format `workspace_id:channel_id`.

The key is public. It identifies the channel and is safe to include in frontend code.

## Add the script

Paste this before the closing `</body>` tag. On Shopify themes, that is usually in `layout/theme.liquid`.

```html theme={null}
<script>
  window.sagepilotWidgetReady = new Promise(function (resolve, reject) {
    var script = document.createElement("script");
    script.src = "https://app.sagepilot.ai/chat-widget.js";
    script.async = true;
    script.onload = function () {
      window.ChatWidget.init({
        host: "https://app.sagepilot.ai",
        key: "WORKSPACE_ID:CHANNEL_ID"
      }).then(resolve, reject);
    };
    script.onerror = function () {
      reject(new Error("Sagepilot widget failed to load"));
    };
    document.head.appendChild(script);
  });
</script>
```

Replace `WORKSPACE_ID:CHANNEL_ID` with your widget key. To change how the widget starts, add options to the `init()` call. See [Configuration](/sdks/web/configuration).

<Note>
  If your workspace is hosted in the EU region, you sign in at `eu.sagepilot.ai`. Replace `app.sagepilot.ai` with `eu.sagepilot.ai` in both the script URL and `host`.
</Note>

### Wait for the widget before calling it

`window.sagepilotWidgetReady` is created as soon as the snippet runs, before the widget has finished loading. Any code that uses `window.ChatWidget` can wait on it:

```js theme={null}
await window.sagepilotWidgetReady;
window.ChatWidget.open();
```

Methods called before the widget is ready do not wait or queue. For example, `open()` returns `false` and `sendMessage()` returns `not_initialized`. Always wait on the promise first.

<Note>
  The launcher script shown in **Embed Code** is a shorter one-line version. It works for the floating launcher, but it does not create `window.sagepilotWidgetReady` until the script has downloaded. Use the snippet above when your own code calls the widget. If you cannot change an existing installation, see [Open chat from your own button](/sdks/web/opening-chat#if-you-cannot-change-the-install-snippet).
</Note>

## Single-page apps

In React, Next.js, Vue, and similar apps, load the widget once for the whole app, not once per route or component render.

* Add the snippet to your root HTML template, or run it once from your app's entry point.
* Do not call `ChatWidget.init()` again when routes change. A second call is ignored and logs a warning.
* Keep a single `window.sagepilotWidgetReady` promise and wait on it wherever you call the widget.

For example, in a Next.js App Router project, load it from the root layout:

```tsx app/layout.tsx theme={null}
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script id="sagepilot-widget" strategy="afterInteractive">
          {`
            window.sagepilotWidgetReady = window.sagepilotWidgetReady || new Promise(function (resolve, reject) {
              var script = document.createElement("script");
              script.src = "https://app.sagepilot.ai/chat-widget.js";
              script.async = true;
              script.onload = function () {
                window.ChatWidget.init({
                  host: "https://app.sagepilot.ai",
                  key: "WORKSPACE_ID:CHANNEL_ID"
                }).then(resolve, reject);
              };
              script.onerror = function () {
                reject(new Error("Sagepilot widget failed to load"));
              };
              document.head.appendChild(script);
            });
          `}
        </Script>
      </body>
    </html>
  );
}
```

## Tag managers

You can add the snippet as a **Custom HTML** tag in Google Tag Manager or a similar tool. Fire it on all pages where chat should appear, and fire it only once per page load.

## Shopify

You can install the widget on a Shopify store in two ways.

| Method              | When to use it                                                                                                                                                                                                                                                       |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sagepilot app embed | Recommended for most stores. Connect the channel to your store under **Channels** > your widget > **Shopify**, then turn on the Sagepilot app embed in the Shopify theme editor and save the theme. Sagepilot supplies the widget key, so you do not paste any code. |
| Theme code          | Use when your developers want full control of the `init()` options, for example to hide the floating launcher. Paste the snippet above into `layout/theme.liquid` before `</body>`.                                                                                  |

Use one method per store. Do not add the snippet to a theme that also has the Sagepilot app embed turned on.

## Inline embed

To place the chat inside a section of a page instead of as a floating launcher, use an iframe:

```html theme={null}
<iframe
  src="https://app.sagepilot.ai/chat-widget/CHANNEL_ID?wid=WORKSPACE_ID&hideCloseButton=true"
  title="Chat with us"
  style="width: 100%; height: 700px; border: 0; border-radius: 12px; overflow: hidden;"
  allow="clipboard-write"
></iframe>
```

You can copy this with your IDs filled in from **Embed Code** > **Inline Iframe Embed**. The `window.ChatWidget` API does not control inline embeds.

## Verify the installation

1. Open your site in a private browser window.
2. Confirm the launcher appears, unless you hid it.
3. In the browser console, run `await window.sagepilotWidgetReady` and then `window.ChatWidget.open()`. It should return `true` and open the chat.
4. Send a test message and confirm a ticket appears in Sagepilot on the Website Widget channel.

If the widget does not load, see [Troubleshooting](/sdks/web/troubleshooting).
