For the complete documentation index, see llms.txt. Any page on this site can be fetched as Markdown by appending .md to its URL.

Chat Widget

Installing

Add the chat widget to your website and allow the origins it runs on.

1. Create the widget

In Tandem, go to Web Chat → Widgets and choose Add Widget. You need a name — which visitors see as the bot name in the chat header — and the agent it should talk to. Everything else is set on the page you land in.

2. Add your allowed origins

Under Allowed Origins, add every website origin the widget should work on:

https://www.example.com
https://shop.example.com

An origin is the scheme, host, and optional port — no path and no trailing slash. There is no wildcard: if you serve the chat from three subdomains, list three origins.

A widget with no allowed origins does not load anywhere, including the site you are testing from. This is deliberate — see Why the origin list matters.

While you are developing, add your local origin too. http:// is accepted only for localhost, 127.0.0.1, and [::1]; every other origin must be https://.

http://localhost:5173

3. Paste the snippet

Copy the snippet from the Install section and paste it into your site, just before the closing </body> tag on every page that should show the chat:

<script
    src="https://chat.tandemcx.ai/v1/spark-chat.js"
    data-spark-chat-key="spk_YOUR_PUBLIC_KEY"
    async
></script>

A snippet copied from the dashboard before it moved to app.tandemcx.ai loads the script from chat.spark.sharpencx.com instead. Both hosts serve the same script, and either works.

That is the whole integration. The script adds one element to your page and renders inside a shadow root, so your site's CSS cannot affect the chat and the chat's CSS cannot affect your site.

Optional attributes

The launcher's corner is not one of these. It is a widget setting, so it moves from the Tandem dashboard without editing the snippet on every page. See Position.

AttributeDefaultWhat it does
data-spark-chat-z-index2147483000Raise or lower if the launcher collides with another fixed element.
data-spark-chat-autotrueSet to false to stop the widget mounting itself, and call SparkChat.mount({ publicKey: 'spk_…' }) yourself — for example after cookie consent.

Controlling it from your own code

window.SparkChat is available as soon as the script has run:

SparkChat.open();
SparkChat.close();
SparkChat.toggle();
SparkChat.reset(); // discard the conversation and start over
SparkChat.destroy(); // remove the widget from the page

Why the origin list matters

The public key in your snippet is not a secret. Anyone who views your page source can read it, and there is no way around that — the snippet has to work in a browser with no login.

So the key is not what authorizes a request. The allowed-origins list is. Your visitor's browser sends an Origin header that page JavaScript cannot forge, and Tandem checks it against your list on every request. Someone who copies your snippet onto their own site gets nothing.

Keep the list to the sites that should have the chat, and it does its job.

What the widget does to your page

  • Adds one <spark-chat> element to <body>, rendered in a shadow root.
  • While the chat is open on a phone-sized screen, sets overflow: hidden on <html> so the page behind the full-screen panel does not scroll, and restores your previous value exactly when it closes.
  • Stores two small values in the visitor's browser, and no message text: a visitor id and the id of the conversation they were in, in localStorage under one key. The messages themselves stay on our servers and are fetched when the panel opens. No cookie is set — the widget is on your domain calling ours, so a cookie would be a third-party cookie, which several browsers block.
  • Also uses one sessionStorage key, to remember that this tab has already been greeted.
  • Defines window.SparkChat.

It sets no other global listeners, and never touches your page's history, title, or focus outside its own panel.

Content Security Policy

If your site sends a CSP, the widget needs:

script-src  https://chat.spark.sharpencx.com https://chat.tandemcx.ai
connect-src https://api.spark.sharpencx.com https://api.tandemcx.ai

List both script-src hosts so the policy holds whichever snippet your site uses. The widget calls api.spark.sharpencx.com today. List api.tandemcx.ai in connect-src as well, so your policy keeps working when the widget moves to that host.

Add img-src for whatever host your avatar image is on. The widget loads no fonts, no stylesheets, and no other scripts.

On this page