Co-browse: live screen assistance
Co-browse is the real-time counterpart to session replay: instead of playing back what a visitor did, an agent joins the visitor’s live page as it happens. When a customer is stuck on your checkout, sign-up, or account settings, live assistance resolves it in the conversation instead of over a back-and-forth of screenshots. This page covers the order of operations from widget install to first session — the consent model, the privacy policy you set before going live, the agent join/end lifecycle, and guided-control packets. For the full request/response schema, see the Co-browse API reference.When to co-browse
Reach for co-browse when the session’s value depends on what the visitor sees right now — a checkout field that won’t validate, a multi-step form abandoned midway, an agent who can’t reproduce what the visitor describes. It runs inside a conversation the visitor already has open in the chat widget, so the agent joins the page without asking for a share link. Two consent postures, chosen by the visitor when they start the session:- Observe (
control: false) — the agent watches the live page only. The page DOM is mirrored; nothing the agent types or clicks reaches the visitor. - Guided control (
control: true) — in addition to observing, the agent can highlight elements, scroll, and fill form fields on the visitor’s page. The consent ceiling is set by the visitor; an agent can request control on join, but an observe-only session can never be escalated to control. The visitor can re-confirm or revoke the grant at any time by re-POSTing their start call.
Prerequisites
Before a session can start, you need the native chat widget installed and the operator’s role set. Co-browse is not available on SMS, WhatsApp, voice, or email threads — only on web-chat conversations.- Widget installed. Install the native chat widget on the pages your visitors use — the
./widgetexport of@devotel-orbit/web, or the hostedorbit-chat.jsbootstrap. See the widget install guide for the embed steps; a page without the widget script can never carry a session. - Operator role. The agent joining from the inbox needs the
conversations:writescope plus anowner,admin, ordeveloperrole on their API key or dashboard session. Agents with onlyconversations:readcan see the “Co-browse available” affordance but can’t join.
End-to-end flow
A session moves through four steps, visitor-side then agent-side:- Visitor starts. The visitor starts co-browsing from the widget — usually when they answer the agent’s question “can I see what you’re looking at?” The widget calls
POST /widget/conversations/{id}/cobrowsewith the visitor’s session token; the session is stamped on the conversation’s metadata and fans out to the inbox in real time. The body is optional;controldefaults tofalse. - Inbox shows the session. The dashboard Inbox polls the session state on open web-chat conversations. When the visitor has initiated, the conversation panel shows a “Co-browse available” affordance; once an agent joins, it flips to “Co-browse live” with a per-session consent indicator.
- Agent joins. Call
POST /api/v1/cobrowse/{conversationId}/joinwith the visitor’s conversation id. The endpoint mints a data-channel join token and a scopedroom_namebound to , flips the session toactive, and stamps the agent and start time. Passcontrol: truein the body to request guided control; the response’scontrolfield is the effective grant after the visitor’s consent cap. - Agent’s client connects. Use the returned
tokenandws_urlto attach an agent-side viewer to the room so the agent’s browser can render the page mirror. The token expires afterexpires_in(30 minutes); re-mint by re-calling join, which is idempotent on an already-active session.
Guided control
Once the visitor grantedcontrol: true, an agent that joined with control: true in their request can send highlight, scroll, and form_fill packets on the session. Each one travels as a broadcast into the data room; the visitor’s browser rerenders the hint — a pulsing box around a selector, a scroll, or the value you wrote into a form field.
The packet is checked against the privacy policy before it leaves the platform — a selector or input type inside any blocked region or always-blocked hard floor is rejected with 403 COBROWSE_CONTROL_BLOCKED, and form_fill attempts are audit-logged. A session where the visitor joined observe-only rejects control with 403 COBROWSE_CONTROL_NOT_GRANTED.
The sequence as calls:
POST .../control returns 204 No Content — the packet was broadcast into the room. Keep control packets small: each request travels as a dispatch payload, and a packet that exceeds the 1 MB dispatch ceiling returns 502 COBROWSE_CONTROL_FAILED.
Set the capture-time privacy policy first
Co-browse mirrors the visitor’s live DOM. The privacy policy decides what the capture client masks in the visitor’s page before it publishes a DOM packet — masking happens in the visitor’s browser, and masked content never leaves the page. It also doubles as the server-side guard on the control endpoint: a selector or input type the policy blocks can never be captured or remotely controlled. The default posture is fail-closed — with nothing configured, every input is masked andtel, email, and cc input types are blocked. Password fields and a small set of built-in payment/card selectors are always blocked and cannot be relaxed by this endpoint.
Set the policy before your first live session, and cover your checkout, payment, and account-settings pages explicitly:
The same toggle set is backed by the Settings → Channels → Native chat dashboard panel, so operators can adjust masking without an API client. The change takes effect on the next co-browse session bootstrap for both the visitor and the joining agent — it doesn’t retroactively change a session already in progress.
Because off-screen DOM is never transmitted, co-browse isn’t a screen share: the capture client only sends the DOM tree the visitor’s page exposes, minus whatever your policy masks, over a scoped data channel. Choosing selectors to block — and documenting that decision with your DPO — is the tenant-owned control that keeps co-browse aligned with your compliance posture. Password fields,
X-Frame-Options-protected iframes, and your own block_selectors are all excluded at capture time.
Ending a session
Either side can end the session; both stop the data room:- Agent ends.
POST /api/v1/cobrowse/{conversationId}/endstampsstatus: ended,ended_at, andended_by: "agent". The inbox panel’s End session button calls this endpoint. Ending an already-ended session is an idempotent no-op. - Visitor ends. The widget calls
POST /widget/conversations/{id}/cobrowse/endwith the visitor token;ended_bybecomes"visitor". Either a visitor closing the widget or a system cleanup stampsended_by: "system".
- End sessions on resolution, not just on conversation close. An ended session can never be joined again; the visitor re-initiates from the widget so consent is re-confirmed.
- Re-initiation re-confirms consent — don’t reuse an ended room. The re-join endpoint is idempotent on a live session and never revives an ended one.
- The visitor can revoke at any time. If an agent requests control on a session the visitor opened observe-only, the
403rejection is the consent model working, not an error. - Sessions on closed/archived threads can’t be joined — the affordance hides once the thread is terminal.
- Tokens expire after 30 minutes. Re-mint via join rather than holding a long-lived token; the process re-stamps the agent without advancing
started_at.
Failure ladder
When a session won’t start, stalls, or refuses control, work the ladder in the Troubleshooting: co-browse session stuck page. The common classes:COBROWSE_NOT_ACTIVEon join — the visitor hasn’t started co-browsing, or the previous session ended. Ask the visitor to re-initiate from the widget.- A frame blocked by the customer site’s
X-Frame-Optionsor CSPframe-ancestors— the embedded viewer can’t render the page. - A session that joins and then freezes — an edge point-of-presence dropped the data-channel socket; reconnect with the client SDK and re-mint the token.
- A control or custom-tool packet refused with
502— the dispatch payload exceeded the 1 MB ceiling; trim the selector andvalue.
Minimal HTML that starts a session
The hosted widget bootstrap is anorbit-chat custom element on your page; the visitor opens chat, and starts co-browsing from the widget UI — no integration code is required on your end. The element below is the least the page needs:
Endpoint summary
See also
- Co-browse API reference — the full session, privacy, and control record shapes and error codes
- Session replay — the asynchronous counterpart to live co-browse
- Troubleshooting: co-browse session stuck — the failure ladder for each stuck-session class
- Inbox setup — widget install and agent roles