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

# Add the chat widget to your website

> Put a chat bubble on your own site, style it to match your brand, and answer it from the same inbox as every other channel.

Every other channel belongs to someone else — Meta, Telegram, a phone network. This one is
yours: a chat bubble on your own website, with conversations landing in the same inbox,
routed by the same rules, answered by the same agents.

Visitors install nothing and need no account. They click the bubble and type.

## Turn it on

<Steps>
  <Step title="Create the channel">
    **Settings → Channels → Website chat**. Type the domain the widget will run on —
    `acme.com` — and press **Create**.

    The domain is asked for first because a channel with no domain serves nobody: the
    widget refuses to load anywhere it hasn't been allowed. That is the safe default, and
    also the most common reason a freshly-pasted snippet shows nothing.
  </Step>

  <Step title="Save the identity secret">
    It is shown **once**, on creation, and starts with `wc_sec_`. You only need it if your
    visitors sign in — see [If your visitors are signed in](#if-your-visitors-are-signed-in) —
    but there is no way to read it later, so store it now or rotate it when you need it.
  </Step>

  <Step title="Copy the snippet into your site">
    One line, just before the closing `</body>` tag, on every page you want the bubble on.
    The **Install** tab has yours with the key already in it:

    ```html theme={null}
    <script
      src="https://social.linkiasoft.com/widget/v1/loader.js"
      data-website-id="wc_pub_7c8d9e0f1a2b"
      async
    ></script>
    ```
  </Step>

  <Step title="Grant the channel to a role">
    **Roles → the role → Channels**. A channel nobody is granted delivers to nobody. This
    is the step people miss on every channel, and this one is no different.
  </Step>

  <Step title="Load your site and send yourself a message">
    The bubble appears bottom-right. Send a test message and watch it arrive in the inbox.
  </Step>
</Steps>

<Note>
  Not comfortable editing your site's HTML? Most platforms have a place for this:

  * **WordPress** — Appearance → Theme File Editor → `footer.php`, or any "custom scripts"
    plugin.
  * **Shopify** — Online Store → Themes → Edit code → `theme.liquid`, before `</body>`.
  * **Webflow** — Project settings → Custom code → Footer code.
  * **Wix / Squarespace** — the site's custom-code or code-injection panel.

  Anything that asks for "footer code" or "code before the closing body tag" is the right
  box.
</Note>

## Which domains it runs on

**Website chat → Settings → Security.** The widget boots only on the domains listed there.

| Entry        | Matches                                                    |
| ------------ | ---------------------------------------------------------- |
| `acme.com`   | `acme.com` and `www.acme.com`                              |
| `*.acme.com` | `shop.acme.com`, `shop.eu.acme.com`, and `acme.com` itself |
| `localhost`  | any local dev server, on any port                          |
| `*`          | everywhere — for testing only                              |

The website id in your snippet is **public**: it sits in a page anyone can view the source
of. This list is what makes that safe. A key copied out of your site is useless on any
domain you haven't allowed.

<Warning>
  Add your staging domain too if you test there, and remove `*` before you launch. A widget
  that boots anywhere can be embedded on somebody else's page and used to send you messages
  that look like they came from your own site.
</Warning>

## Make it look like yours

**Website chat → Settings → Appearance.** Changes save straight to the widget — no code
change, no deploy. Reload the page and they're there, with a preview beside the form as
you edit.

| Setting                                           | What it changes                                                                  |
| ------------------------------------------------- | -------------------------------------------------------------------------------- |
| Brand colour                                      | The launcher bubble, the header, and the visitor's own message bubbles.          |
| Text on brand colour                              | Picked automatically for contrast. Override it if the automatic choice is wrong. |
| Light / dark / automatic                          | Automatic follows the visitor's own system setting.                              |
| Position, corner radius, distance from the bottom | Left or right, and how it sits against your layout.                              |
| Logo                                              | Shown in the header and beside replies that have no agent photo.                 |
| "We run on Linkiasoft"                            | A small credit at the bottom of the widget. Can be turned off.                   |

<Warning>
  A pale brand colour with white text on it is unreadable. The preview warns you when the
  contrast falls below the accessibility threshold — if it does, darken the colour or set
  the text colour yourself. If it looks washed out to you, it is worse for anyone with low
  vision.
</Warning>

Under **Messages** you set the team name, greeting, offline message and composer
placeholder, and choose the language — Arabic switches the whole widget to right-to-left.

Developers can override the colours, position and launcher **per page** from the snippet
itself — a docs site that wants the bubble on the left, a checkout page that wants it
hidden. See [the widget guide](/widget#overriding-settings-on-one-page).

## What a visitor gets

* **Their history.** A returning visitor sees their past conversations and can reopen one
  or start a new one.
* **Attachments.** Images, PDFs and files up to 25 MB, if you leave them on.
* **Typing indicators and read receipts**, in both directions.
* **Live replies**, even with the panel closed — the bubble shows an unread count.

You can ask for a name, email or phone number before the chat starts — **Settings →
Behaviour → Before the chat starts**. Keep it short. Every field you add is a reason to
close the widget instead of typing, and you can ask for the email later, when they already
want an answer from you.

## When nobody is available

Availability follows agent presence and your shifts, the same as everything else. See
[Presence](/help/routing/presence-ready-busy-off) and
[Shifts and rotas](/help/routing/shifts-and-rotas).

* **Someone is ready** — the widget says so, and shows your typical reply time if you set
  one.
* **Nobody is** — visitors see your offline message and can still write. The conversation
  waits in the inbox.

You can override this under **Settings → Behaviour → Availability**: always show as
available (sensible when an [AI agent](/help/ai/agents-overview) answers first), or always
show as away.

<Note>
  Don't advertise a reply time you can't hold on a Friday night. Leave the field empty and
  the widget promises nothing — an unanswered promise costs you more than no promise.
</Note>

## Who gets the chat

Exactly like every other channel: sticky owner first, then your distribution settings. See
[How assignment works](/help/routing/how-assignment-works).

Two things are specific to website chat:

* **A visitor is anonymous until they tell you who they are.** Until then there is no
  customer record to be sticky to, so the chat is distributed fresh — and **no lead is
  created**. A lead appears the moment they give a name, email or phone number, through the
  pre-chat form, in the conversation, or because your site identified them. This is
  deliberate: a lead per anonymous visitor would fill your pipeline with rows nobody can
  follow up, and count each one against your plan's active contacts.
* **An AI agent can take the first turn** and hand over when it can't answer — worth having
  on a channel where people expect an instant reply.

## If your visitors are signed in

If the widget sits behind a login — a dashboard, a customer portal — your site can tell us
who the visitor is, and the conversation attaches to that customer instead of an anonymous
one. Their history then follows them across devices.

<Warning>
  Do this with **identity verification**. Without a signature, the browser is simply claiming
  an identity, and anyone who can open developer tools can claim someone else's and read
  their conversations. Your server signs each user id with the channel's identity secret; we
  check it before trusting the claim.

  Turn on **Require a valid signature** under **Settings → Security** once your site is
  signing, and have your developers follow
  [Identity verification](/widget-api#identity-verification). It is a few lines of
  server-side code.
</Warning>

**Sign out all visitors** on the same page invalidates every stored session at once. Every
visitor's browser becomes a new, anonymous one; nothing is deleted, they simply can't see
their history any more. It exists for the day a secret leaks.

## Nothing appears on the site

<AccordionGroup>
  <Accordion title="The bubble doesn't show up at all">
    In order:

    1. Is the domain in the allowlist, exactly as it appears in the address bar?
       `acme.com` covers `www.acme.com`, but `shop.acme.com` needs `*.acme.com`.
    2. Is the channel **Connected**, not paused?
    3. Did the snippet land on the page? View source and search for `linkiasoft`.
    4. Open the browser console. The widget writes one line starting `[Linkia chat]` when
       it refuses to start, and it says why.
    5. Ad blockers and privacy extensions block chat widgets. Test in a clean browser
       profile before assuming it's broken.
  </Accordion>

  <Accordion title="Messages send but never reach the inbox">
    Almost always the role grant: **Roles → the role → Channels**. A connected channel
    that no role includes delivers to nobody, and the visitor sees no error.
  </Accordion>

  <Accordion title="Two bubbles">
    The snippet is on the page twice — often once in the theme footer and once in a tag
    manager. The widget only loads once per page no matter how many times you paste it, so
    a second bubble means a second, different snippet.
  </Accordion>

  <Accordion title="It says we're away while agents are working">
    Availability follows presence and shifts, not whether someone is logged in. An agent
    on **Busy** or outside a shift doesn't count as available. See
    [Presence](/help/routing/presence-ready-busy-off), or set availability to **Always show
    as available** if an AI agent answers first.
  </Accordion>

  <Accordion title="A returning visitor lost their history">
    The visitor's session lives in their own browser. Clearing site data, a private window,
    or a different device all start fresh — that is expected. To carry history across
    devices, identify signed-in visitors as described above.

    It also happens after **Sign out all visitors**, or after rotating the website id.
  </Accordion>

  <Accordion title="No lead appeared in the pipeline">
    Working as intended while the visitor is anonymous — see
    [Who gets the chat](#who-gets-the-chat). Turn on the pre-chat form, or ask for an email
    in the conversation, and the lead is created then.
  </Accordion>
</AccordionGroup>
