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

# Web Widgets

> Put a chat with one of your flows on your website, with a launcher in the corner of each page.

<Frame caption="The Web Widgets tab on the Points of Contact page">
  <img className="block dark:hidden" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-list-light.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=52f5c46e024220e6f884ba1d82af95bd" alt="The Web Widgets tab shows a list of widgets with their status, flow, visitors, allowed sites and update time (light)" width="1440" height="900" data-path="images/web-widgets-list-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-list-dark.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=dd470df8aa8ec14ebbdba9870d428864" alt="The Web Widgets tab shows a list of widgets with their status, flow, visitors, allowed sites and update time (dark)" width="1440" height="900" data-path="images/web-widgets-list-dark.png" />
</Frame>

A **web widget** puts a chat with one of your flows on your own website. The widget adds a launcher in a bottom corner of each page. A visitor clicks the launcher, and a chat panel opens on the same page.

Web Widgets are the new way to put chat on a website. They replace the legacy web chat (chat links on the **Web (Legacy)** tab, with the [iframe](/iframe-integration) or the [script tag](/script-tag-integration)). Use a web widget for each new site.

A widget has these parts:

* **A flow** — the flow that answers the visitors.
* **Allowed sites** — the sites that can show the widget. No other site can show it.
* **An appearance** — a preset and your changes to it. See [Widget appearance](/web-widget-appearance).
* **Sign-in** — optional. A portal that signs its customers in can tell the widget who the customer is. See [Signed-in visitors](/web-widget-sign-in).

## Find Web Widgets

Go to **Agent > Points of Contact** and select the **Web Widgets** tab.

The tab shows only when your role has the `web-widgets:list` permission. Other actions need other permissions:

| Permission | What it lets you do |
| - | - |
| `web-widgets:list` | See the **Web Widgets** tab and the list of widgets. |
| `web-widgets:read` | Open the page of a widget. |
| `web-widgets:create` | Create a widget with **Create Widget**. |
| `web-widgets:update` | Change a widget: its status, allowed sites, appearance and sign-in. |
| `web-widgets:simulate` | Use **Act as a customer** on the **Try it** card. |

The list has these columns: **Status**, **Widget**, **Visitors**, **Allowed sites** and **Updated**. Active widgets are at the top. Use the **Status** filter to show only **Active** or **Off** widgets. Click a row to open the page of that widget.

## Create a widget

<Steps>
  <Step title="Open the dialog">
    On the **Web Widgets** tab, click **Create Widget**.
  </Step>

  <Step title="Type a name">
    In **Name**, type a name for the site or the page that shows the widget. An example is "Billing help on the account page". Each widget in your tenant must have a different name.
  </Step>

  <Step title="Select the flow">
    In **Flow**, select the flow that answers the visitors.
  </Step>

  <Step title="Add the allowed sites">
    In **Allowed sites**, type the address of a site, such as `https://www.example.com`. Click **Add**. Do this again for each site that shows the widget.
  </Step>

  <Step title="Create the widget">
    Click **Create Widget**. The page of the new widget opens.
  </Step>
</Steps>

<Frame caption="The Create Widget dialog with a name, a flow and one allowed site">
  <img className="block dark:hidden" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-create-dialog-light.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=ae80c099eb4000ee65b0f3b60389dce3" alt="The Create Widget dialog. The Name, Flow and Allowed sites fields are filled in (light)" width="920" height="522" data-path="images/web-widgets-create-dialog-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-create-dialog-dark.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=76b9bed5cdf99a8c6a3177a06947e188" alt="The Create Widget dialog. The Name, Flow and Allowed sites fields are filled in (dark)" width="920" height="522" data-path="images/web-widgets-create-dialog-dark.png" />
</Frame>

A new widget is active. Each visitor is anonymous until you set up [sign-in](/web-widget-sign-in). The appearance is the **Classic** preset until you change it.

## Allowed sites

The allowed sites are a security control. A site that is not in the list cannot show the widget. On that site, the launcher does not show, and the browser blocks the chat panel. If the list is empty, no site can show the widget.

Each entry is an origin: a scheme, a host and an optional port. The widget ignores the path of an address. These forms are permitted:

| Form | Example | Notes |
| - | - | - |
| One site | `https://www.example.com` | The usual form. |
| All subdomains of a domain | `https://*.example.com` | Not permitted on a public suffix, such as `*.co.uk` or `*.github.io`. |
| A site with a port | `https://portal.example.com:8443` | The platform removes a default port (`:443` on https). |
| A local test site | `http://localhost:3000` | Only `localhost` and `127.0.0.1` can use `http`. |

A widget has a maximum of 50 allowed sites.

The list in the **Create Widget** dialog starts with the site of the Dial AI dashboard. This lets you try the widget on the **Try it** card at once. Keep this entry while you use **Try it**.

To change the list later, click the edit (pencil) icon beside **Allowed sites** on the page of the widget. Add or remove sites, then click **Save**.

## The page of a widget

The page has these cards: **Try it**, **Appearance**, **Embed code** and **Sign-in**. The side panel shows the **Status**, **Flow**, **Visitors**, **Allowed sites**, **Look**, **Limits** and **Created** date.

### Status

The **Status** switch turns the widget on or off for all sites at the same time.

* **Active: sites show the widget** — each allowed site shows the launcher.
* **Off: no site shows it** — the launcher goes away, and the widget starts no new session.

Use **Off** to stop a widget. The page has no delete action.

### Limits

**Limits** shows the maximum number of conversations that the widget starts in one day (UTC), or **No daily limit**. You cannot change the limit on this page.

## Try it

The **Try it** card shows a sample website with the widget on it. Click the launcher in its bottom corner and chat as a visitor does. A chat on the sample site is a real conversation with the flow of the widget.

<Frame caption="The page of a widget. The Try it card shows a chat on the sample site.">
  <img className="block dark:hidden" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-try-it-light.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=f84695de11fab1f13355979fc5709948" alt="The page of a widget. The chat panel is open on the sample site, with a question and the answer of the flow (light)" width="1440" height="900" data-path="images/web-widgets-try-it-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-try-it-dark.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=12acaefbda54518f6c423f65fefe9158" alt="The page of a widget. The chat panel is open on the sample site, with a question and the answer of the flow (dark)" width="1440" height="900" data-path="images/web-widgets-try-it-dark.png" />
</Frame>

* **Start again** loads the sample site again.
* The **Open the sample site in a new tab** icon button opens the sample site in a new browser tab. In the tab, the widget has the full window, so it shows its desktop layout.

<Frame caption="The sample site in a new tab. The widget has the full window.">
  <img className="block dark:hidden" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-sample-tab-light.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=5837754f8807bbe313c6ac69948e4f2f" alt="The sample site in a full browser tab, with the chat panel open in the bottom right corner (light)" width="1440" height="900" data-path="images/web-widgets-sample-tab-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-sample-tab-dark.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=4421a0dd98c74ca5ed089382e55585a7" alt="The sample site in a full browser tab, with the chat panel open in the bottom right corner (dark)" width="1440" height="900" data-path="images/web-widgets-sample-tab-dark.png" />
</Frame>

The new tab reads the widget again each 3 seconds. When somebody saves a change, a bar shows **The theme has changed.** or **The widget has changed.** Click **Reload** to show the change.

The sample site cannot show the widget in these conditions. The card then shows the reason.

| Message | What to do |
| - | - |
| This page (…) is not one of the widget's allowed sites, so the widget cannot show here. | Add the site of the dashboard to **Allowed sites**. |
| The widget is off, so no site shows it. | Set **Status** to **Active**. |
| The chat widget is not available on this deployment… | Contact your account representative. |

When the widget has a sign-in provider, you can also chat as a signed-in customer. See [Act as a customer](/web-widget-sign-in#test-the-paths-with-act-as-a-customer).

## Put the widget on your site

<Steps>
  <Step title="Copy the embed code">
    On the **Embed code** card, click **Copy**.
  </Step>

  <Step title="Paste it into each page">
    Paste the code immediately before the `</body>` tag of each page that shows the widget.
  </Step>

  <Step title="Check the allowed sites">
    Make sure that the site of each page is in **Allowed sites**.
  </Step>
</Steps>

<Frame caption="The Embed code card">
  <img className="block dark:hidden" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-embed-code-light.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=a2dd3f5bcf6e44cb5a706cad7a9a7e55" alt="The Embed code card with the script tag and the Copy button (light)" width="790" height="188" data-path="images/web-widgets-embed-code-light.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/dialai/H76LnNRjy-o0z9Jm/images/web-widgets-embed-code-dark.png?fit=max&auto=format&n=H76LnNRjy-o0z9Jm&q=85&s=2a211cd4e29320df0b3c181b0ff9bd02" alt="The Embed code card with the script tag and the Copy button (dark)" width="790" height="188" data-path="images/web-widgets-embed-code-dark.png" />
</Frame>

The embed code has this shape:

```html theme={null}
<script async src="https://<api host>/widget/loader.js"
  data-tenant="<tenant>"
  data-widget-id="<widget id>"
  data-host="https://<api host>"></script>
```

<Note>Always copy the embed code from the page of the widget. The page writes the correct API host, tenant and widget ID for your deployment. Do not type the code yourself.</Note>

The script adds the launcher to the page. The chat panel loads only when a visitor opens it.

### What visitors see

* The launcher shows in the corner that you set in the appearance.
* On a screen of 480 px or less, the open chat panel covers the full page.
* The **Escape** key closes the panel.
* If the chat cannot load in 15 seconds, the panel shows "The chat could not load." and a **Try again** button.

A page that a visitor opens after a change shows the change. A page that stays open reads the launcher again each 30 minutes.

## Control the widget from your page

The embed code also makes a JavaScript function, `DialAI`, on your page. Your page can use it to open the chat, to listen to events, and to give the widget a sign-in token.

### Call `DialAI` before the script loads

To call `DialAI` before the script loads, add a small queue function first. Then call `init` yourself, and remove the `data-tenant`, `data-widget-id` and `data-host` attributes from the script tag:

```html theme={null}
<script>
  window.DialAI = window.DialAI || function () { (DialAI.q = DialAI.q || []).push(arguments) };
  DialAI("init", { tenant: "<tenant>", widgetId: "<widget id>", host: "https://<api host>" });
</script>
<script async src="https://<api host>/widget/loader.js"></script>
```

Copy the values of `tenant`, `widgetId` and `host` from the embed code of the widget.

<Warning>Only the first `init` has an effect. The `data-tenant` attribute on the script tag is also an `init`, and it runs first. If you keep the attributes and also call `init`, the widget ignores your `init` and its options, such as `identity`.</Warning>

### Commands

| Command | What it does |
| - | - |
| `DialAI("init", { tenant, widgetId, host, identity })` | Adds the launcher. `host` and `identity` are optional. |
| `DialAI("open")` | Opens the chat panel. |
| `DialAI("close")` | Closes the chat panel. |
| `DialAI("toggle")` | Opens the panel when it is closed, and closes it when it is open. |
| `DialAI("logout")` | Ends the session of the visitor in the widget. |
| `DialAI("on", event, handler)` | Calls `handler(payload)` for each event of that type. |
| `DialAI("emit", "navigated", { url, title })` | Tells the widget that the page went to a different address. The widget accepts this event but does not use it yet. |

Call `DialAI("logout")` when a person signs out of your site. Then the next person on the same browser does not see the conversation of the previous person. The logout works also when the chat panel did not open yet.

To tell the widget who a signed-in customer is, give `init` an `identity` function. See [Signed-in visitors](/web-widget-sign-in#give-the-widget-a-token).

### Events

| Event | Payload | When |
| - | - | - |
| `state` | `{ open }` | Each time the panel opens or closes. |
| `conversation` | `{ event }`, with `event` one of `"started"`, `"ended"` or `"handoff-started"` | When a conversation starts, ends, or goes to a human agent. |
| `message` | `{ direction, text, at }`, with `direction` one of `"received"` or `"sent"` | For each new message. |

The `text` of a `sent` message is the text that the platform stored. The platform masks sensitive data, such as a card number, before it stores the text. Your page never gets the text that the visitor typed.

This example opens the chat from a "Chat with us" link, and records each handoff:

```html theme={null}
<a href="#" id="chat-link">Chat with us</a>
<script>
  document.getElementById("chat-link").addEventListener("click", function (event) {
    event.preventDefault();
    DialAI("open");
  });
  DialAI("on", "conversation", function (payload) {
    if (payload.event === "handoff-started") {
      console.log("The conversation went to a human agent.");
    }
  });
</script>
```

Put this code after the queue function, so that `DialAI` exists when it runs.

### Style the launcher

Your page can change the launcher with CSS `::part()` rules. Your page cannot change the chat panel or the theme. See [Widget appearance](/web-widget-appearance#style-the-launcher-from-your-page).

## Web Widgets and the legacy web chat

| | Web Widgets | Web (Legacy) |
| - | - | - |
| Where | **Points of Contact > Web Widgets** | **Points of Contact > Web (Legacy)** |
| On your site | One script tag. It adds a launcher and a chat panel. | An iframe or the `dial-ai.js` script with `renderModal`. |
| Which sites | Only the allowed sites. | Any site that has the chat link. |
| Look | Presets and overrides, set on the dashboard. | The tenant theme, or `brandVariants` on the page. |
| Customer identity | Tokens from your portal, checked by the platform. See [Signed-in visitors](/web-widget-sign-in). | Chat links with baked-in context. See [Passing context securely](/integration-context). |
| Status | Current. | Deprecated. Chat links still work for now. |

## Best practices

| Practice | Reason |
| - | - |
| Make one widget for each site or each part of a site. | Each widget has its own allowed sites, look and flow. The name shows in the list. |
| Add only the sites that you own to **Allowed sites**. | Any allowed site can show your flow to its visitors. |
| Test on the **Try it** card before you paste the embed code. | You see the same widget that your visitors see. |
| Set **Status** to **Off** to stop a widget at once. | All sites stop it. You do not have to change each page. |

## Related

<CardGroup>
  <Card title="Widget appearance" icon="palette" href="/web-widget-appearance">Presets, colours, fonts and the launcher.</Card>
  <Card title="Signed-in visitors" icon="user-check" href="/web-widget-sign-in">Tell the widget who your customer is.</Card>
  <Card title="Points of Contact" icon="address-book" href="/points-of-contact">All the channels that connect a flow to customers.</Card>
  <Card title="Flows" icon="diagram-project" href="/flows">Build the flow that answers your visitors.</Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.