Skip to content

The chat widget

A round bubble in the bottom-right corner of the page, in your brand color. Clicking it opens and closes the chat panel.

The launcher can be moved: press and hold it for about half a second without moving, then drag it anywhere on the page. A drag that completes doesn’t open the panel, so moving the bubble never accidentally starts a chat. Its position is clamped to stay on screen, and it’s remembered for that site in the browser’s localStorage. When the panel is docked, it re-anchors itself just above wherever the launcher now sits.

The header shows your header title (Settings → header title; it falls back to your workspace name) and two controls: a window menu and a × close button. Your own admins additionally get a 💡 feedback menu.

The menu has three items:

  • Detach window / Dock to corner — detached, the panel floats free and you drag it by its header; docked, it’s anchored to the bottom-right corner above the launcher.
  • Reset size & position — clears the remembered size, panel position, detached/docked mode, and launcher position all at once.
  • New conversation — starts a fresh conversation.

Resizing: drag the small grip in the panel’s top-left corner. Because the panel is anchored bottom-right, dragging up and to the left grows it. The panel won’t go below 320 × 400 pixels, and won’t exceed 90% of the window in either direction.

Mode, size, panel position, and launcher position are each remembered per site in localStorage, and everything is clamped on restore — a window that shrinks or a phone that rotates can’t strand the panel off screen.

Careful with the ×: if the visitor has sent at least one message, × ends the conversation (and offers the rating prompt). On an empty or already-ended conversation it just collapses the panel. Clicking the launcher always just collapses.

Type in the composer and press Enter to send; Shift+Enter inserts a newline. A message can be up to 4,000 characters.

If a reply takes unusually long the composer unlocks itself after 45 seconds with a note that the answer will appear when it’s ready — the visitor is never stuck.

Three ways to attach a file:

  • Click the 📎 button and pick one (this is the only way to attach a document — you can paste a screenshot, but not a PDF).
  • Paste from the clipboard into the composer.
  • Drag and drop onto the chat panel; the panel outlines itself when a droppable file is over it.

What’s accepted:

Kind Types Size cap
Images PNG, JPEG, WebP, GIF 15 MB
Documents PDF, TXT, CSV, Markdown, RTF, DOC/DOCX, XLS/XLSX, PPT/PPTX 25 MB

Two things worth knowing. First, the widget’s own pre-check only rejects files over 25 MB, so an image between 15 MB and 25 MB is accepted by the browser and then refused by the server — the visitor sees “Couldn’t upload <filename>”. Second, browsers report file types unreliably for anything but images, so when the type is missing or generic the file extension decides. An extension that isn’t on the list above is never accepted, whatever the file claims to be.

Uploads start the moment the file is attached, not when Send is pressed, and each one shows a progress bar. If the composer is empty when an upload finishes, the message posts itself — drop a screenshot and it just appears. If the visitor is mid-sentence, the file waits for Send so the caption and the file stay together. Sending waits for any upload still in flight and drops the ones that failed, so the text still goes through.

Images render as thumbnails in the transcript; documents render as a download chip with the extension and file size. Operators can attach files to their replies too, and they show the same way.

The widget renders a deliberately small markdown subset in assistant messages: headings, bullet and numbered lists, inline code, fenced code blocks, **bold**, *italic*, [links](https://example.com), and bare URLs turned into links. Underscores are not treated as emphasis on purpose — snake_case identifiers in a support answer would otherwise turn into italics. Links open in a new tab.

Type /help in the composer to list them.

  • /help — list the available commands.
  • /new — start a new conversation (/clear and /reset do the same).
  • /end — end this conversation.

Slash commands work even when the widget is waiting on a reply or the conversation has already ended, so they’re always an escape hatch.

New conversation, /new, or the “Start a new chat” button on an ended conversation. This does not delete the previous conversation — it stays in your workspace with its transcript intact. The widget simply forgets which conversation it was on, and the next message starts a fresh one.

After three minutes with no typing or activity, the widget shows a “Still there? Ending in 60s” banner with Keep chatting and End now. If the countdown runs out the conversation ends by itself. This is separate from the workspace-level auto-close described in How a conversation is handled.

When a conversation ends and the visitor sent at least one message, they’re offered Was this helpful? — a 0 to 5 star scale plus an optional comment, or Skip. Ratings and comments show up on your Chats page.

An operator can ask to see the visitor’s screen from the workspace. The visitor gets a prompt in the transcript — “…asks to see a screenshot of this page. Nothing is shared until you agree.” — with Share screenshot and Not now. Nothing is captured unless the visitor explicitly agrees, and the captured image arrives as a normal attachment.

  • Shadow DOM. All the widget’s markup and CSS live inside a shadow root, so your site’s styles and the widget’s can’t affect each other.
  • No third-party cookies. Identity is a 32-character visitor token in localStorage, sent as a request header. The widget works in browsers that block third-party cookies.
  • Resume. Conversations survive page reloads and revisits in the same browser. If localStorage is blocked or full (private-browsing modes), the widget falls back to an in-memory token: chat works for that page load but doesn’t survive a reload.
  • Live updates. Replies stream in over a WebSocket. If that connection is refused or blocked, the widget falls back to refreshing every 10 seconds so replies still arrive.