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

# Web widget

> Embed an agent as a chat widget on your portal or intranet.

# Web widget

The web widget is an embeddable chat experience you drop onto any page — a
floating bubble that opens a panel, or a full-screen page you link to directly.

## Embed it

Each web-widget channel has a public key. Add this snippet to your page, before
the closing `</body>` tag, with your channel's key:

```html theme={null}
<script>
  window.cobaltSettings = { channelKey: "wgt_pub_your_channel_key" };
  (function () {
    var s = document.createElement("script");
    s.async = true;
    s.src = "https://widget.cobalt.peoplereign.io/loader.js";
    document.head.appendChild(s);
  })();
</script>
```

The channel's **Install** tab has this snippet pre-filled with your key — copy
it from there. The loader fetches the channel's configuration — branding,
greeting, identity mode — so you can change those in the console without
touching the page.

## Allow your site's origin

Every page origin that embeds the widget must be listed in the channel's
**Allowed origins**. Requests from an unlisted origin are refused — the widget
simply won't load — so this is the first thing to check when an embed shows
nothing. Add each origin exactly (`https://intranet.example.com`), including any
staging hosts you test from. The admin console's own preview origin is handled
for you.

## Choose how users are identified

Set the channel's **identity mode** to match where you're embedding it:

| Mode                      | How identity arrives                                                                                                 | Use when                                                                                                            |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **Anonymous**             | None (a per-browser session)                                                                                         | Public or low-sensitivity help, no sign-in required.                                                                |
| **Embedded token**        | Your app's **server** mints a short-lived signed token and passes it to the widget                                   | Your app already authenticates the user and can sign a token server-side (intranet portal, ServiceNow app). Silent. |
| **Federated (IdP token)** | The host obtains an IdP token for the signed-in user **silently** and passes it; Cobalt verifies it against your IdP | The host can't safely hold a signing secret but can get an IdP token client-side (SharePoint / SPFx). Silent.       |
| **Hosted sign-in**        | Interactive sign-in on the standalone full-page surface                                                              | Only the standalone hosted page, where there's no host-app session to reuse.                                        |

If the agent acts on a user's behalf, use **Embedded token** or **Federated** so
requests are tied to a real identity — both sign the user in silently when the
widget is embedded in an app they're already logged into. Don't use interactive
hosted sign-in for an embedded widget. For the full picture — trust tiers, and
which modes can *act as* the user vs. only *attribute* — see
[End-user identity](/identity/end-user-identity#web-widget--no-second-sign-in).

## Brand it

Configure the widget's appearance on the channel's settings — no code:

* **Display name** and **role** shown in the header.
* **Avatar** image (falls back to a generated initial).
* **Primary color** for the launcher and the user's message bubbles, with an
  optional **header color** and a second color for a subtle gradient.
* **Corner radius** for the overall shape.
* **Greeting** and up to a handful of **suggested prompts** shown when the
  conversation is empty.
* **Preferred voice** for read-aloud.

<Tip>
  Pick a primary color with enough contrast against white text — the widget uses
  it behind message text and on the send button.
</Tip>

## What the conversation includes

The widget is a full conversational surface, not just a text box:

* **Rich answers** — markdown, tables, code, images and other media inline, with
  **citations** and source cards when the agent draws on indexed content, and
  live activity indicators while it works.
* **Attachments** — users can upload a file or screenshot for the agent to look
  at.
* **Voice** — three distinct things, all optional: **dictation** (speak instead
  of type), **voice mode** (a real-time spoken conversation), and **read-aloud**
  (the agent's answer spoken back, in the channel's preferred voice).
* **Feedback** — thumbs up/down with categories, feeding the agent's reporting.
* **Forms and confirmations** — structured forms for multi-field requests;
  confirmation prompts before actions; per-user sign-in consent cards when a
  tool acts as the user in another system.
* **Human handoff** — when a conversation is handed to a live agent, the
  transition and the human's replies render right in the thread.

## Anonymous channels and browser storage

Two things to know before a public, no-sign-in embed:

* **Rate limits.** Anonymous visitors get per-visitor limits on uploads,
  dictation, and voice, plus a per-tenant daily cap on anonymous voice minutes —
  so an abusive visitor can't run up your usage.
* **Browser storage.** An anonymous visitor is remembered with browser storage.
  When your page and the widget are on different sites, some browsers partition
  or block that storage (third-party cookie rules); the widget falls back to
  asking for storage access, and if the browser still refuses, the visitor gets
  a fresh session per visit. Signed-in identity modes (embedded token,
  federated) don't have this problem — prefer them wherever users are
  authenticated.

## Widget and full-screen share a conversation

The same channel can render as the compact widget or as a full-screen page. A
user can move between them and keep the same conversation, history, and unsent
draft — useful when a quick question turns into a longer session.

## On SharePoint Online

Modern SharePoint Online forbids pasting the `<script>` snippet on a page. To
put this widget on a SharePoint intranet — with single sign-on for logged-in
Microsoft 365 users — use the dedicated SharePoint package and guide:
[Deploy to SharePoint Online](/channels/sharepoint). You download the package
from this channel's **Install** tab (**Deploy to → SharePoint site**).

## Troubleshooting

<AccordionGroup>
  <Accordion title="The widget doesn't appear at all">
    Almost always an **allowed origins** problem: the page's origin isn't on the
    channel's list, so the config request is refused. Add the exact origin
    (scheme and host, e.g. `https://intranet.example.com`) and hard-refresh. The
    browser console shows the refused request.
  </Accordion>

  <Accordion title="Anonymous visitors have to start over every visit">
    On a cross-site anonymous embed, the browser is partitioning or blocking the
    widget's storage (third-party cookie rules). Use a signed-in identity mode
    (embedded token or federated) where visitors are authenticated; for a truly
    public embed this is expected behavior.
  </Accordion>

  <Accordion title="Branding changes aren't showing up">
    Branding is fetched by the loader at runtime, so changes apply without
    re-embedding — but a cached page may hold the old config. Hard-refresh. If
    you changed the channel key, update the snippet.
  </Accordion>

  <Accordion title="Voice mode never prompts for the microphone">
    The embedding page must permit microphone access. On SharePoint, see the
    [SharePoint guide's troubleshooting](/channels/sharepoint).
  </Accordion>
</AccordionGroup>
