Skip to content
Widget SDK

Signed-in Visitors

Give the widget your visitor's token; Gydr checks it through a sign-in source so history, memory and tools follow the person.

On this page

Signed-in Visitors#

A guest needs nothing but the script tag. When a shopper or member is signed in to your site, the page gives the widget one thing: the visitor’s token. Gydr checks it on its own servers, works out who the person is, and from then on their history, memory and Console record follow them across devices and the Conversation API. Plugins that act as the visitor (your REST API, an MCP server, Shopify, WooCommerce) are sent that same token.

Gydr always makes the visitor id. No page, link, storage edit or API call can choose one, so nobody can claim another person’s conversations by guessing a label.

Six words#

These words mean the same thing in the Console, the SDK and these docs.

Word
Visitor token
Meaning
A token your site issues for this visitor — your API token, your identity provider's token, or a token your server signs with its own key. It is never a Gydr-specific token and never a Gydr secret. Gydr checks it and forwards it to your API.
Word
Sign-in source
Meaning
How Gydr checks the token: WordPress, Your keys or Your backend. One per widget.
Word
Token origin
Meaning
The API your token belongs to, for example https://api.example.com. Only plugins that call that origin receive the token.
Word
User ID
Meaning
Your own id for the person, taken from the check (the WordPress user id, the token's sub claim, or the userId your backend answers).
Word
Visitor ID
Meaning
Gydr’s id for a visitor on any channel: vis_… for a guest, usr_… for a signed-in visitor. Gydr makes it; you never choose one.
Word
Sign-in state
Meaning
verified, guest or unavailable (the check could not run).

Which setup do you need?#

You want
A chatbot for everyone
You do
Paste the script tag. Nothing else.
Visitor is
A guest (vis_…); history is this browser.
You want
Tools that call your API as the visitor, no sign-in
You do
Give the widget the token, set the plugin to Send the visitor’s token, leave the sign-in source on none.
Visitor is
A guest to Gydr. Tools act as the person; the chat is private to that token.
You want
Recognise people AND call your API as them
You do
Give the widget the token, pick a sign-in source, set the plugin to send the token.
Visitor is
Signed in (usr_…) with history on every device.
You want
Recognise people only
You do
Give the widget the token, pick a sign-in source. No plugin sends it.
Visitor is
Signed in (usr_…).

A WordPress or WooCommerce site needs no code at all: install the Gydr plugin and press Connect WordPress. See WordPress & WooCommerce setup.

Step 1 — give the widget the visitor’s token#

Either a same-origin endpoint or a JavaScript provider. Both return the same shape:

The answer
{
  visitorToken: string | Record<origin, string> | null,
  expiresIn?: number // seconds
}
  • null means the visitor is not signed in.
  • expiresIn is optional. A JWT’s own exp wins. The widget asks again at 80% of the lifetime, every 4 minutes for an opaque token with no expiresIn, once after Gydr reports the token expired or rejected, and straight away when you call Gydr.refreshVisitorToken().
  • If you set both an endpoint and a provider, the provider wins (one console line says so).
<script
  src="https://cdn.infinichat.dev/widget.js"
  data-api-key="pk_live_YOUR_KEY"
  data-visitor-token-endpoint="/gydr/visitor-token"
  async
></script>
Never print the token into the page. There is no data-visitor-token attribute on purpose. Serve the token from an endpoint with Cache-Control: no-store, so no page cache or CDN can hand one customer’s token to the next visitor.

Several backends#

If different plugins call different APIs, key each token by the origin it was issued for:

One token per origin
Gydr.setVisitorTokenProvider(async () => ({
  visitorToken: {
    'https://shop.example.com': shopToken,
    'https://api.example.com': apiToken,
  },
}))

Each plugin receives only the token filed under its own origin. A plugin whose origin has no entry gets nothing and the miss is logged as unmatched.

Step 2 — pick a sign-in source#

In the Console open Settings → Visitor sign-in and press Add sign-in source. Then, in the widget’s settings, choose it as the widget’s sign-in source. A console with exactly one source preselects it on widgets that have none. Skip this step to keep visitors as guests while plugins still act as them.

Source
WordPress
The token
A token signed by your site's own key (plugin 1.5.0+).
Gydr checks
The signature, with the public key registered when you pressed Connect.
User ID
The WordPress user id.
Source
Your keys
The token
A JWT from your identity provider, or one your own server signs.
Gydr checks
The signature (JWKS URL or a pasted public key), the issuer, and the audience.
User ID
The claim you name (sub by default).
The token
Any token — an opaque API token is fine.
Gydr checks
Gydr asks your server, with a signed request.
User ID
The userId your server answers.

WordPress#

Install the Gydr WordPress plugin (1.5.0 or later) and press Connect WordPress. The plugin creates its own signing key on your site, registers only the public half with Gydr, and serves the visitor token from your site for any signed-in user. Gydr never calls back into WordPress to sign anyone in, so a firewall in front of your site does not matter for sign-in. Until a site has plugin 1.5.0 and a registered key, its visitors are guests and the Console shows a warning.

Your keys#

For an identity provider (Auth0, Clerk, Cognito, Firebase, Supabase, or any provider that publishes a JWKS), or for a site that signs its own tokens. Give the widget the provider’s token as shown above, then in the Console add a source with:

  • the issuer (the token’s iss);
  • either a JWKS URL or a pasted public key;
  • the audience — your API’s audience, the token’s azp or its client_id. It is required for a JWKS URL, so a token the same provider issued to a different app is rejected;
  • optionally the claim that holds the user’s id (default sub).

A site with cookie sessions and no identity provider can sign its own token and paste the public key — see the sign-in source reference for the key-pair command, the claims and a signing snippet. Gydr does not accept alg: none or HS256 for a visitor token.

Your backend#

For an opaque API token Gydr cannot read, Gydr asks your server who the token belongs to. In the Console add the source with your check URL (for example https://api.example.com/gydr/check), copy the secret (shown once) into your server, and press Activate. Your endpoint receives a signed request, answers { userId, name?, email? } when the token is valid and 401 when it is not. The full contract, with Node, PHP and Python verification snippets, is in the sign-in source reference.

Why Gydr signs every check

The check URL is on your server, so anyone could call it. The signature proves a request comes from Gydr’s servers, and the secret is never stored by Gydr after it is shown. An edit of the URL deactivates the source until a new activation succeeds.

Step 3 — set the token origin#

Each widget has one token origin, shown next to its sign-in source. It is prefilled from the plugin that sends the token (the plugin’s own origin) and otherwise from the source (the WordPress site, or your check URL). A Your keys widget that forwards the token must set it, because the identity provider’s issuer is usually not your API’s address.

  • A single token is treated as one filed under the token origin, and the sign-in source always checks the entry at that origin.
  • Every entry reaches only plugins whose target origin equals its key. A plugin on a different origin never sees it.
  • The token also never reaches a write endpoint unless the operator allowed that action to act as the visitor.

What signed-in visitors get#

Area
User ID
Behaviour
Shown on the visitor's Console row beside the sign-in source, in webhooks, the Conversation API, Custom Desk and exports. Two sources that return the same id (say 42) are still two different people.
Area
History
Behaviour
A signed-in visitor sees every conversation bound to them on this widget — from any device and from the Conversation API. A guest sees only this browser's own conversations. A conversation never crosses from guest to signed-in: signing in always starts a new visitor, and signing back in brings that person's history back.
Area
Memory
Behaviour
On for signed-in visitors, unless the widget has history opt-out (memory then needs the visitor-memory setting). Turns holding personal data are skipped.
Area
Details
Behaviour
Name, email and phone from the check fill the visitor's details where they are empty. A check-filled email does not create a CRM lead.
Area
Sign-in and sign-out
Behaviour
Signing out or switching to another person makes the widget a fresh visitor: the list empties at once, and the next person sees nothing of the last. Call Gydr.refreshVisitorToken() right after your own sign-in or sign-out in a single-page app.
Area
Outage
Behaviour
If your JWKS or backend is down, a signed-in visitor stays signed in on the same conversation and the composer shows a retry banner; nobody is signed out because a check could not run. A guest stays a guest.
Area
History opt-out
Behaviour
With history off there is no Past conversations list. User ID and details are masked in the Console and exports, and left out of webhooks and the Custom Desk payload.

No source, but a token

With a token and no sign-in source, the visitor stays a guest. The session is bound to that token and always treated as private: it is not listed in history and not resumed after a reload. If the page switches to another person, the chat starts fresh. An opaque token that changes every few minutes therefore starts a new conversation each time — use a JWT or a sign-in source when you need continuity.

Limiting a team to signed-in visitors#

A human-handoff team can be limited to signed-in visitors. In the Console, open the team’s Visitor experience tab and turn on Signed-in visitors only. Guests are then never offered that team. The option needs a sign-in source on every widget the team is attached to, and saving it asks you to confirm what it limits.

Where it applies

Only visitors signed in through your website chat widget, and Conversation API sessions whose creating request identifies the user (set by the user:assert request that creates the session), can reach a signed-in-only team. Visitors on WhatsApp, Messenger, Instagram and Telegram never can, because a messaging platform gives Gydr no verified identity.

A team that needs visitor details (Zanroo Desk needs name and email) also needs the widget to ask for them as required. The widget’s Integrations tab shows a notice on that team until it does, and the visitor is asked for anything missing before the chat is handed over.

Reason codes#

When a visitor is not recognised, the SDK console line and the Console’s token tester (Settings → Visitor sign-in → Test a token) name one of these.

Code
no_token
When
The page gave no token.
Fix
Sign in, or check the endpoint answers a token.
Code
no_source
When
A token arrived but the widget has no sign-in source.
Fix
Pick a source, or ignore it: the visitor stays a guest and tools still act as them.
Code
rejected
When
Wrong signature, issuer or audience, or your backend answered 401.
Fix
Check the source settings.
Code
expired
When
The token is past its exp.
Fix
The SDK refreshes it; check your token lifetime.
Code
unmatched
When
The token map has no entry for the token origin.
Fix
Add the entry, or fix the token origin.
Code
check_unavailable
When
Your backend timed out or answered 5xx, the JWKS could not be fetched, or too many new tokens were checked from one browser in a minute.
Fix
Gydr retries; check your service is up. A burst of new tokens waits out the minute.
Code
bad_signature
When
Your backend answered 403: it refused Gydr's signature.
Fix
Re-copy the secret or rotate it. Nobody is signed out for this.
Code
source_inactive
When
A backend source has not been activated.
Fix
Press Activate in the Console.
Code
source_not_ready
When
The WordPress plugin is older than 1.5.0, or its key is not registered.
Fix
Update the plugin or reconnect.
Code
misconfigured
When
Your backend answered something Gydr cannot use (wrong shape, or a cacheable response).
Fix
Fix the check endpoint — see the reference.

Related: Sign-in source reference · Guests & data never to send · Plugins · Migrate to 4

Ready to get started?

Create a free account and deploy your first chatbot in minutes.