> ## 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.

# Open chat from your own button

> Open the Sagepilot chat from any button, link, or banner on your site.

Any element on your site can open the chat, for example a **Chat with us** link in your header, an **Ask an expert** button on product pages, or a help prompt inside a cart drawer.

## Open chat from a button

This example assumes you installed the widget with the snippet in [Installation](/sdks/web/installation), which creates `window.sagepilotWidgetReady`.

<Steps>
  <Step title="Mark the elements that open chat">
    Add the `data-sagepilot-open` attribute to any button or link. You can use it on as many elements as you like.

    ```html theme={null}
    <button type="button" data-sagepilot-open>Chat with us</button>
    <a href="#" data-sagepilot-open>Need help choosing a size?</a>
    ```
  </Step>

  <Step title="Handle the click">
    Add this once per page, after the widget snippet.

    ```html theme={null}
    <script>
      document.addEventListener("click", async function (event) {
        if (!event.target.closest("[data-sagepilot-open]")) return;
        event.preventDefault();
        await window.sagepilotWidgetReady;
        window.ChatWidget.open();
      });
    </script>
    ```
  </Step>
</Steps>

The handler listens on the whole page, so it also works for elements your theme or apps add later, such as a slide-out cart or a popup. If a visitor clicks before the widget has finished loading, the chat opens as soon as it is ready.

## Hide the floating launcher

If only your own buttons should open the chat, add `hideNativeLauncherButton: true` to the `init()` call. This hides the launcher in the corner of the page and its welcome popup. `ChatWidget.open()` still works.

```js theme={null}
window.ChatWidget.init({
  host: "https://app.sagepilot.ai",
  key: "WORKSPACE_ID:CHANNEL_ID",
  hideNativeLauncherButton: true
});
```

<Note>
  The unread-message badge appears only on the Sagepilot launcher. If you hide it, visitors see new replies when they open the chat.
</Note>

## If you cannot change the install snippet

Use this version if the widget is already installed and you cannot edit its snippet, for example when it was installed with the Sagepilot Shopify app embed, through a tag manager, or with the one-line script from **Embed Code**. It does not need `window.sagepilotWidgetReady`.

```html theme={null}
<script>
  function openSagepilotChat() {
    var attempts = 0;
    (function tryOpen() {
      if (window.ChatWidget && window.ChatWidget.open()) return;
      if (++attempts < 40) setTimeout(tryOpen, 250);
    })();
  }

  document.addEventListener("click", function (event) {
    if (!event.target.closest("[data-sagepilot-open]")) return;
    event.preventDefault();
    openSagepilotChat();
  });
</script>
```

`ChatWidget.open()` returns `false` until the widget is ready, so the helper retries every 250 ms for up to 10 seconds. While it retries, the browser console may show `[ChatWidget] Widget not initialized` warnings. These are expected.

Do not add a second copy of the widget script to reach the API. The widget must be loaded only once per page.

## Complete example

A Shopify theme that shows its own **Ask the concierge** button and no floating launcher. Add this to `layout/theme.liquid` before `</body>`, and put the button wherever it should appear in your theme.

```html theme={null}
<button type="button" class="concierge-button" data-sagepilot-open>
  Ask the concierge
</button>

<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",
        hideNativeLauncherButton: true
      }).then(resolve, reject);
    };
    script.onerror = function () {
      reject(new Error("Sagepilot widget failed to load"));
    };
    document.head.appendChild(script);
  });

  document.addEventListener("click", async function (event) {
    if (!event.target.closest("[data-sagepilot-open]")) return;
    event.preventDefault();
    await window.sagepilotWidgetReady;
    window.ChatWidget.open();
  });
</script>
```

## Close and toggle the chat

| Call                         | What it does                                                                                                                      |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `window.ChatWidget.open()`   | Opens the chat. Returns `true`, or `false` if the widget is not ready.                                                            |
| `window.ChatWidget.close()`  | Closes the chat. Returns `true`, or `false` if the widget is not ready.                                                           |
| `window.ChatWidget.toggle()` | Opens the chat if it is closed and closes it if it is open. Returns `true` when it opened the chat and `false` when it closed it. |
| `window.ChatWidget.isOpen()` | Returns `true` if the chat is open.                                                                                               |

For example, a button that switches between open and closed:

```js theme={null}
document.getElementById("help-toggle").addEventListener("click", async function () {
  await window.sagepilotWidgetReady;
  window.ChatWidget.toggle();
});
```

## How opening behaves

* `open()` always opens the full chat. It skips the welcome popup and the two-step intro card.
* Calling `open()` while the chat is already open does nothing. Repeated clicks do not create extra windows or new conversations.
* Opening the chat does not send a message. To prefill or send one, see [Draft and send messages](/sdks/web/sending-messages).
* Visitors who have chatted before on the same browser see their existing conversations.
* On screens 768 px wide or narrower, the chat opens full screen. Visitors close it with the close button inside the chat.

## Verify the setup

1. Open your site in a private browser window.
2. Click your button. The chat should open.
3. Click it again several times. The same chat should stay open.
4. Close the chat and click the button again. It should reopen.
5. Repeat on a phone, or with your browser's device toolbar set to a phone width.
6. In your browser's developer tools, throttle the network to a slow connection, reload, and click the button immediately. The chat should open once the widget finishes loading.

If nothing happens, see [Troubleshooting](/sdks/web/troubleshooting).
