Installation & configuration
Embed the widget, set your origin allow-list and branding, and understand what rotating each key breaks.
The widget is a drop-in product, not an API. You embed a snippet, configure it in the dashboard, and you have chat on your site — with visitor identity, file attachments, and handoff to a human all handled for you.
The only code you might write is optional: signing an identity token so your logged-in users are recognized. Everything else on this page is configuration.
Same engine as the Public API
A conversation started in the widget and one started through the Public API are the same object. They land in the same agent inbox and run the same routing rules. Installing the widget doesn't put you on a separate, lesser track — it's the same helpdesk, reached a different way.
1. Embed the snippet
The widget is a single <script> tag — a self-contained bundle, with no npm package and
nothing to install. Put it just before the closing </body> tag, on every page the
widget should appear on.
<script
src="https://ws.asssistive.com/widget.js"
data-public-key="wpk_example_M4tQ8vC2xR7d"
async
></script>Yes, the host really has three s's
ws.asssistive.com — asssistive, not assistive. It is not a typo in these docs, and
it must not be "corrected" when you paste it.
widget.useassistive.com does not resolve. If you tidy the spelling, the bundle 404s and
the widget never loads.
The snippet carries your widget public key (wpk_…), which identifies your
organization. It ships inside a page anyone can view-source, so it is not a secret —
what protects you is the origin allow-list, not the key.
The attribute must be spelled data-public-key exactly
The bundle boots only if the script tag carries data-public-key. Under any other
name — data-publickey, data-key, publicKey — the check simply never fires.
And it fails completely silently: no error, no console warning, no widget. There is nothing in your console to tell you why the page looks unchanged. If the widget isn't appearing at all, check this attribute's spelling before anything else.
2. Set your allowed origins
The widget only works on origins you've explicitly allowed. In the dashboard, list every exact origin — scheme, host, and port — that the widget will run on:
https://acme.test
https://www.acme.test
https://staging.acme.test
http://localhost:3000A page served from an origin that isn't on the list cannot use the widget at all. This is the real security boundary: someone who copies your snippet — public key and all — onto their own site gets nothing, because their origin isn't allowed.
An incomplete allow-list is the #1 cause of “the widget doesn’t load”
Origins are matched exactly, and the traps are the ones that look like the same site to a human but aren't to a browser:
- Apex and
wwware different origins.https://acme.testdoes not coverhttps://www.acme.test. - Staging and preview domains are different origins. Vercel/Netlify preview URLs especially — each deployment can get its own hostname.
httpandhttpsare different origins, and so is a non-default port.
If the widget works locally and vanishes in production, check this list first. It's almost always this.
Add your localhost origins while developing, and take them out before you ship.
3. Configure it
Widget settings live at agent.useassistive.com/settings/widget, and you need to be an
Owner or Admin.
| Field | What it does |
|---|---|
| Widget enabled | The master switch (under Status). A disabled widget doesn't load. |
| Human handoff | Whether visitors may ask to talk to a person (under Status). See Attachments & handoff. |
| Brand name | The name in the chat header, e.g. "Acme Support". |
| Brand color | The accent color. |
| Greeting | The opening message visitors see. |
| Logo URL | Optional logo in the chat header. |
| Launcher text | The text on the launcher button. |
| Allowed origins | The origins permitted to embed the widget — use Add for each one. See above. |
Edits are staged as you make them and only take effect when you press Save changes. Discard throws them away.
Visitors only ever see your branding
When the widget loads, the only configuration it receives is the branding above — never your keys, never your origin allow-list, never any other setting. There's nothing sensitive in a widget's bootstrap for someone to dig out of your page.
4. Your two keys
Both live in the Keys card on the same widget settings page.
| Key | Lives | Purpose |
|---|---|---|
Public key (wpk_…) | In your web page, inside the snippet | Identifies your organization. Not a secret. |
Secret key (wsk_…) | On your server only | Signs identity tokens. A real secret. |
You need the secret key only if you're identifying logged-in users. If you're running the widget anonymously, you'll never touch it.
Unlike a publishable API key, the widget secret key is not shown-once. It's masked in the dashboard behind an eye toggle, and you can reveal and copy it again whenever you need to — losing your copy is not a crisis, and doesn't require a rotation.
The secret key never goes in a browser
wsk_ is what lets your server vouch for who a visitor is. Anyone holding it can mint a
token claiming to be any of your users and read that person's support history.
It belongs in your secrets manager and nowhere else. If it ever appears in your frontend bundle, in your page source, or in a client-side environment variable, rotate it immediately.
Rotating keys
Both keys rotate from the Keys card, using the circular-arrows button next to each one. It's icon-only — there's no button text — and its accessible name is Rotate Public key or Rotate Secret key.
Rotation takes effect immediately — there is no grace period and no overlap window, so what breaks depends on which key you rotate. The dashboard warns you in the confirm dialog; believe it.
Rotating the public key invalidates the key in your snippet. Until you deploy the new one, the widget stops working for every visitor. Update your page in the same deploy as the rotation.
Rotating the secret key invalidates every identity token at once
The secret key signs identity tokens. The moment you rotate it, every token ever signed with the old key stops verifying — including ones your server minted seconds ago that browsers are still holding.
Your server has to switch to signing with the new key at the same moment. Practically: put the new secret in your secrets manager and deploy the server change together with the rotation.
Visitors holding a stale token don't lose any data — they simply fall back to being anonymous until they reload with a freshly signed token.
Rotate on a schedule, when someone with access leaves, and immediately on any suspicion that the secret key has leaked.
Before you ship
- Every production origin on the allow-list — apex,
www, and any preview domains. localhostorigins removed.- Widget enabled.
- Secret key on your server only. Grep your built bundle to be sure.
- Branding set: name, color, greeting.
- Handoff enabled matches whether you actually have people to answer.
- Send a test message from the widget and answer it from the inbox.