# Install the widget on Shopify

> Add the AgentMySite support chat to a Shopify online store theme or to an embedded Shopify app built with Remix.

Source: https://agentmysite.com/docs/guides/install/shopify/

You can add the AgentMySite support chat in two places on Shopify:

- **Your online store**: the chat appears on your storefront for shoppers.
- **Your embedded Shopify app**: if you build a Shopify app with Remix, the chat appears inside your app for the merchants who use it.

<Aside>
Looking for a shopping assistant that knows your products and orders? That's **AgentMyShop**, a separate Shopify app. Its guides are coming later.
</Aside>

## Before you begin

- [Create your site](/docs/get-started/quickstart/#2-create-your-site) and [add content](/docs/guides/content/upload-documents/).
- Copy your embed snippet from **Site Settings** > **Site key & embed snippet**.

<Tabs>
<TabItem label="Online store theme">

## Add the chat to your online store

<Steps>

1. In AgentMySite, go to **Site Settings** > **Allowed domains** and add every hostname your store uses, for example `your-store.myshopify.com` and `www.your-store.com`.

2. In your Shopify admin, go to **Online Store** > **Themes**. Next to your current theme, open the **⋯** menu and select **Edit code**.

3. Open `layout/theme.liquid`.

4. Paste your embed snippet just before the closing `</body>` tag, then select **Save**.

   ```html title="layout/theme.liquid"
   <script async src="https://widget.agentmysite.com/loader/widget.js" data-site-key="YOUR_SITE_KEY" data-api-base="https://api.agentmysite.com" data-iframe-origin="https://widget.agentmysite.com"></script>
   </body>
   ```

5. Open your storefront. The chat button appears in the bottom-right corner.

</Steps>

</TabItem>
<TabItem label="Embedded app (Remix)">

## Add the chat to an embedded Remix app

This is for developers of Shopify apps built with Remix. Merchants who use your app see the chat inside your app, and the assistant answers from the content you added to AgentMySite, such as your app's help articles.

### Use one site for your whole app

Create **one** AgentMySite site for your app, not one per merchant. Chat history is kept separate for each store with the `data-shop-domain` attribute, so each merchant only sees their own store's conversations.

### 1. Add a loader component

Remix navigates on the client. A plain `<script>` tag in `root.tsx` only runs on a full page load, so the widget can fail to appear after navigation. Inject the loader from a component instead:

```jsx title="app/components/AgentMySiteChat.jsx"

const LOADER_SRC = "https://widget.agentmysite.com/loader/widget.js";
const SITE_KEY = "YOUR_SITE_KEY"; // from your embed snippet, or an env var
const API_BASE = "https://api.agentmysite.com";
const IFRAME_ORIGIN = "https://widget.agentmysite.com";

export function AgentMySiteChat() {
  useEffect(() => {
    if (document.querySelector("script[data-agentmysite-loader]")) return;
    // Embedded apps receive the store's myshopify domain as the ?shop= parameter.
    const shop = new URLSearchParams(window.location.search).get("shop") || "";
    const s = document.createElement("script");
    s.src = LOADER_SRC;
    s.async = true;
    s.setAttribute("data-agentmysite-loader", "");
    s.setAttribute("data-site-key", SITE_KEY);
    s.setAttribute("data-api-base", API_BASE);
    s.setAttribute("data-iframe-origin", IFRAME_ORIGIN);
    if (shop) s.setAttribute("data-shop-domain", shop); // keeps each store's history separate
    document.body.appendChild(s);
    return () => {
      for (const sel of [
        "script[data-agentmysite-loader]",
        '[data-testid="agentmysite-bubble"]',
        '[data-testid="agentmysite-widget-iframe"]',
      ]) document.querySelectorAll(sel).forEach((el) => el.remove());
    };
  }, []);
  return null;
}
```

Read the site key from an environment variable if your staging and production apps use different sites.

### 2. Mount it in your app layout

Render the component in your authenticated app layout, after `<Outlet />`, so the chat is on every page of your app:

```jsx title="app/routes/app.jsx"

// ...inside the layout component's return, after <Outlet />:
<AgentMySiteChat />
```

### 3. Allow your app's domain

An embedded app's pages are served from **your** domain, such as `your-app.fly.dev`, not from `admin.shopify.com`. In AgentMySite, go to **Site Settings** > **Allowed domains** and add:

- every hostname your app is served from, for example `your-app.example.com`
- `localhost` for local development. Ports are ignored, so don't add one.

### 4. Allow AgentMySite in your Content Security Policy

If your app sets a strict `Content-Security-Policy`, add these sources. If you only set Shopify's `frame-ancestors`, you don't need to change anything.

```text title="Content-Security-Policy"
script-src  'self' https://widget.agentmysite.com;
connect-src 'self' https://api.agentmysite.com;
frame-src   https://widget.agentmysite.com;
```

### Optional: hide the conversation list

Add `data-single-conversation="true"` to show only the current conversation and hide the list of past conversations.

### Next: let the assistant take actions

To let the assistant do things in your app, such as look up orders, see [AgentActions](/docs/developers/agentactions/).

</TabItem>
</Tabs>

## Check that it works

<Steps>

1. Open a page where you added the widget. The chat button appears in the corner.

2. Ask a question your content answers.

3. In your browser's developer tools, open **Network**. You should see `widget.js` with status 200, then `POST /widget/session` with status **200**, not 401.

</Steps>

If `/widget/session` returns 401, the page's hostname isn't in your allowed domains. For other problems, see [Troubleshooting](/docs/guides/troubleshooting/).
