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

# Connect the Chat Widget to Your Desk

> Install the hosted ResponseCX widget, find its conversation in Chat Desk, and verify human takeover, replies, and internal notes.

**Outcome:** a visitor sends a message on your website, your team finds the same conversation
in [Chat Desk](https://response.stateset.com/chat-desk), and an operator reply appears in the widget.

This guide uses the hosted **Widget Builder v2 loader** in `response-one-prod`. The
[standalone widget integration](/stateset-response/response-chat-widget-quickstart) has a different
mounting API and configurable backend endpoints. Mounting that standalone component does not
by itself connect its backend to ResponseCX Chat Desk.

## 1. Configure your hosted widget

Open [Widget Builder](https://response.stateset.com/widget-builder) in the intended organization.
Select the support agent, configure the greeting and appearance, and add your allowed website
origins. The builder requires valid exact origins, such as `https://shop.example.com`; confirm
the actual scheme and host used by your test page.

Save the widget and use the builder's publication controls when you are ready for customer
traffic. A saved inactive widget is not a live deployment. An agent preview alone does not test
the permanent widget ID, origin checks, or installed loader.

## 2. Install the generated snippet

Prefer the snippet generated for your widget. Its basic form is:

```html theme={null}
<script
  src="https://response.stateset.com/widget/v2/loader.js"
  data-widget-id="YOUR_WIDGET_ID"
  data-api="https://response.stateset.com"
  async>
</script>
```

Replace `YOUR_WIDGET_ID` with the permanent widget ID from the builder and place the script
before the closing body tag. The hosted loader initializes the widget; this path does not
require the separate React/UMD mounting example. Do not put a private service API key in the
script. If your site uses a content security policy, allow the loader origin in `script-src`
and the API origin in `connect-src`.

Test the actual published page on an allowed origin. If using a tag manager or cached site,
confirm the snippet reached the live page and was not inserted twice.

## 3. Follow a message into the desk

<div className="ss-operation-map" role="group" aria-label="Website conversation path">
  <div><span className="ss-eyebrow">VISITOR</span><strong>Hosted widget</strong><p>Sends a message with its session and thread context.</p></div>
  <div><span className="ss-eyebrow">RESPONSECX</span><strong>Agent and transcript</strong><p>Handles the message and persists the conversation for the organization.</p></div>
  <div><span className="ss-eyebrow">OPERATOR</span><strong>Chat Desk</strong><p>Reads the thread and saves a reply for the same visitor conversation.</p></div>
</div>

Send a unique test message, such as “Widget handoff test: shipping policy.” In the desk's
**Chat** view, find that text and compare the thread identity and agent. The widget runtime
persists chat threads and messages and also records response evidence. The desk combines native
chat threads with eligible response-backed records; a response row alone is not proof that
an editable native thread exists.

The visitor's open widget receives thread updates through streaming with polling fallback.
An operator reply must be saved to the same thread and retrieved by that visitor session to
appear. Desk event updates and widget updates are separate connections.

## 4. Verify a human handoff

1. In Chat Desk, **Claim** the test conversation and choose **Pause AI / take over**.
2. Send another message from the same visitor widget. When the widget backend detects human
   takeover, it saves the customer's message and returns a handoff acknowledgement instead
   of generating a new AI answer.
3. Use **Send reply** in the desk. Confirm the result says the transcript was saved, then
   watch the reply appear in the visitor widget.
4. Add a clearly marked test **internal note** in the desk. Confirm the team can see it and
   the visitor cannot. Public widget transcript reads filter internal-note messages.
5. If returning the conversation to automation, clear the relevant takeover state and verify
   the next test message. Releasing assignment alone does not clear every takeover signal.

<Note>
  Takeover is checked before generation using thread and latest-response state. The current
  public chat handler continues with AI if that state lookup fails. Treat the desk pause as
  conversation coordination, not a fail-closed emergency stop for the whole deployment.
</Note>

## Completion checklist

* The installed widget uses the intended widget ID, agent, organization, and allowed origin.
* A real visitor message is visible in the desk under the matching conversation.
* Human takeover is observed on a subsequent visitor message.
* An operator reply appears in that same visitor session.
* An internal note remains absent from the public transcript.

Keep the thread ID and the observed results in your
[onboarding record](/guides/platform-onboarding#keep-a-record-you-can-resume).

## Troubleshooting

| Symptom                                 | Check                                                                                                                           |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Builder preview works, website does not | Widget publication, exact allowed origin, installed script, permanent widget ID, and browser network errors                     |
| AI responds but desk lacks messages     | Transcript persistence and organization/thread mapping; inspect server errors rather than assuming every AI response was stored |
| Reply saved but visitor sees nothing    | Same thread/session, open widget, blocked streaming/polling, and reply versus note audience                                     |
| AI responds during a handoff            | Actual takeover state and backend lookup failures; assignment alone is not enough                                               |
| History or updates are rejected         | Origin/session/thread authorization; keep the loader's returned thread context intact                                           |

Continue with [desk operations](/stateset-response/chat-desk) or
[channel coverage](/stateset-response/chat-desk-channels).

Implementation checked against `response-one-prod` on 2026-09-20: `pages/widget-builder.js`,
`public/widget/v2/loader.js`, `pages/api/public/widget/chat.js`, public widget v2 thread routes,
`lib/widget/publicChatThreads.ts`, and `lib/chat-desk/thread-state.ts`.
