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

# Install the widget

> Add the TinyInbox widget script to a site.

Each TinyInbox site has its own widget snippet. Install that snippet on the
pages where visitors should be able to contact you.

## Copy the snippet

Open **Install widget** in the dashboard, choose the site, and copy its script
tag.

```html theme={null}
<script
  async
  src="https://api.tinyinbox.co/widget.js"
  data-tinyinbox-site="tin_your_site_key"
  data-tinyinbox-language="auto"
></script>
```

## Paste it into your site

Paste the script before the closing `</body>` tag. Most website builders and CMS
tools have a custom code area for this.

Use the exact snippet from your dashboard. Your site key is unique to that site.

## Recommended app pattern

The widget script is async. If your app needs to configure labels, set a
language, or identify a visitor, run those calls from client-only code after
TinyInbox is ready. In app frameworks, use a client-only route/component
boundary or framework loader that runs after hydration and auth state are known.

Do not call `window.TinyInbox` during server rendering or directly during a
component render. Those phases can run more than once, be replayed, or happen
before the async widget runtime is ready.

For logged-in app users with signed identity, keep using the dashboard script
and pass the signed `identityToken` through `TinyInbox.identify` once auth state
is known. Do not rebuild the widget URL or site key in application code.

## Set the visitor language

`data-tinyinbox-language` accepts `auto`, `en`, or `zh-tw`. Use `auto` to read
the page or browser language.

If your app has its own language picker, configure TinyInbox after the widget
loads. You can call this again whenever the visitor changes language.

```js theme={null}
const tinyInboxLanguage =
  (currentUser.language || "").replace(/_/g, "-").toLowerCase() === "zh-tw"
    ? "zh-tw"
    : "en"

function onTinyInboxReady(callback) {
  if (window.TinyInbox && window.TinyInbox.isReady) {
    callback(window.TinyInbox)
    return
  }

  window.addEventListener(
    "tinyinbox:ready",
    (event) => callback(event.detail),
    { once: true }
  )
}

onTinyInboxReady((TinyInbox) => {
  TinyInbox.configure({
    language: tinyInboxLanguage,
    welcomeMessage: translate("support.chatWelcome"),
    labels: {
      send: translate("support.send"),
      messagePlaceholder: translate("support.messagePlaceholder"),
    },
  })
})
```

## Origin checks

Widget session requests must come from one of the site's allowed origins.
TinyInbox checks the browser `Origin` or `Referer` before issuing a widget
session token.

## Add visitor details

If your site already knows the visitor's name or email, pass it to TinyInbox
after the widget loads.

Use this browser-provided identity pattern when you are not using signed
identity tokens. For logged-in product users, prefer the signed token flow and
do not also send a separate browser name/email identify call for the same
visitor.

```js theme={null}
function onTinyInboxReady(callback) {
  if (window.TinyInbox && window.TinyInbox.isReady) {
    callback(window.TinyInbox)
    return
  }

  window.addEventListener(
    "tinyinbox:ready",
    (event) => callback(event.detail),
    { once: true }
  )
}

onTinyInboxReady((TinyInbox) => {
  TinyInbox.identify({
    name: currentUser.name,
    email: currentUser.email,
  })
})
```

Use [identity verification](/en/guides/identity-verification) for logged-in
users when the visitor ID, name, or email must be trusted by your backend.
