Sessions & Prefill
The visitor session lifecycle, identify and shutdown, unverified prefill, and bot protection
This page covers what happens after a visitor loads the widget: how the session is established, how to switch or clear identity, the difference between prefill and identity, and Turnstile bot protection.
Session lifecycle
On mount the widget resolves any VisitorIdentity you passed, then performs a handshake:
- Identity present → an identified handshake. The proof is verified and a verified session is issued.
- No identity → an anonymous handshake. A session is still issued; the visitor can read content, react, and browse.
Every visitor — anonymous or identified — gets a chat at handshake. The session is a token the widget sends on every request, carrying the contact id, an opaque visitor id, and whether the visitor is verified.
Sticky visitor id
The widget mints a random visitor id and stores it in localStorage, keyed by your public key. It persists across reloads and even across logout, so a returning visitor on the same browser lands back in the same conversation — until they explicitly shutdown.
localStorage key | Purpose |
|---|---|
wexio:visitor-id:<pk> | The sticky visitor id. |
wexio:visitor-session:<pk> | The identified session blob (token + expiry). |
wexio:prechat-submitted:<pk> | Whether the prechat form was submitted. |
Silent renewal
Identified sessions renew automatically ~30 seconds before expiry, and on tab focus, reusing the same visitor id for continuity. You don't have to refresh tokens yourself — just keep handing the widget a valid proof when it asks (i.e. mint a fresh JWT on each page load).
Identify and shutdown
Switch identity at runtime, or clear it:
// React — change the user prop
<WexioWidget user={{ jwt: newJwt, name: "Grace" }} /> // log in / switch
<WexioWidget user={undefined} /> // log out// Web Component
el.identify({ jwt: newJwt, name: "Grace" }); // log in
el.identify(null); // log out
// Script loader
window.Wexio("identify", { jwt: newJwt, name: "Grace" });
window.Wexio("shutdown"); // log outCall shutdown (or identify(null)) when a user logs out of your app — especially on shared computers. It forgets the sticky visitor id, drops the session, and starts a fresh anonymous one, so the next user can't inherit the previous user's conversation.
Prefill is not identity
Prefill pre-populates the prechat form with name / email / phone. It's a convenience — it is never verified, never unlocks sensitive data, and never marks the visitor as identified.
| Embed | How to prefill |
|---|---|
| React | Pass a verified user instead; or use the Web Component / loader prefill paths. |
| Web Component | prefill-name, prefill-email, prefill-phone attributes. |
| Script loader | window.wexioSettings.prefill = {…}, or Wexio("prefill", {…}), or wx_name / wx_email / wx_phone URL params. |
URL params (?wx_email=…) leak via history, logs, and the Referer header. Prefer wexioSettings.prefill or props for anything containing PII.
Require auth
When Require auth is enabled, an anonymous visitor still gets a session and can browse Home, Help, and News — but the messenger is gated. Their outbound message is refused at the backend and the composer is replaced by a sign-in panel. Identify the visitor (or enable Google / passkey sign-in) to unlock messaging.
Bot protection (Turnstile)
Enable Cloudflare Turnstile under Setup → General and provide a site key. When on:
- The widget lazy-loads the Turnstile script and runs an interaction-only challenge anchored to the launcher corner.
- A token gates the handshake and prechat submission.
- On failure, a retry popup floats above the launcher.
The host does nothing — the site key is read from the backend config, not injected by the page. Turnstile is recommended for high-traffic public widgets.
Server-side trust
For anything sensitive — returning PII, calling billing APIs from a flow or the AI assistant — always hard-check verification server-side and key on the verified user id. The read-only web_verified system field reflects this and is safe for flows to branch on (it's set by the backend only on a real verification and can't be forged), but a tool that exposes sensitive data must still verify on the server, never trust the client or the model.