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,guestorunavailable(the check could not run).
| Word | Meaning |
|---|---|
| Visitor token | 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. |
| Sign-in source | How Gydr checks the token: WordPress, Your keys or Your backend. One per widget. |
| Token origin | The API your token belongs to, for example https://api.example.com. Only plugins that call that origin receive the token. |
| User ID | 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). |
| Visitor ID | 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. |
| Sign-in state | 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_…).
| You want | You do | Visitor is |
|---|---|---|
| A chatbot for everyone | Paste the script tag. Nothing else. | A guest (vis_…); history is this browser. |
| Tools that call your API as the visitor, no sign-in | Give the widget the token, set the plugin to Send the visitor’s token, leave the sign-in source on none. | A guest to Gydr. Tools act as the person; the chat is private to that token. |
| Recognise people AND call your API as them | Give the widget the token, pick a sign-in source, set the plugin to send the token. | Signed in (usr_…) with history on every device. |
| Recognise people only | Give the widget the token, pick a sign-in source. No plugin sends it. | 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:
{
visitorToken: string | Record<origin, string> | null,
expiresIn?: number // seconds
}nullmeans the visitor is not signed in.expiresInis optional. A JWT’s ownexpwins. The widget asks again at 80% of the lifetime, every 4 minutes for an opaque token with noexpiresIn, once after Gydr reports the token expired or rejected, and straight away when you callGydr.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>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:
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 (
subby default).
- Source
- Your backend
- 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.
| Source | The token | Gydr checks | User ID |
|---|---|---|---|
| WordPress | A token signed by your site's own key (plugin 1.5.0+). | The signature, with the public key registered when you pressed Connect. | The WordPress user id. |
| Your keys | A JWT from your identity provider, or one your own server signs. | The signature (JWKS URL or a pasted public key), the issuer, and the audience. | The claim you name (sub by default). |
| Your backend | Any token — an opaque API token is fine. | Gydr asks your server, with a signed request. | 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
azpor itsclient_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
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.
| Area | Behaviour |
|---|---|
| User ID | 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. |
| History | 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. |
| Memory | 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. |
| Details | 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. |
| Sign-in and sign-out | 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. |
| Outage | 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. |
| History opt-out | 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
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
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.
| Code | When | Fix |
|---|---|---|
no_token | The page gave no token. | Sign in, or check the endpoint answers a token. |
no_source | A token arrived but the widget has no sign-in source. | Pick a source, or ignore it: the visitor stays a guest and tools still act as them. |
rejected | Wrong signature, issuer or audience, or your backend answered 401. | Check the source settings. |
expired | The token is past its exp. | The SDK refreshes it; check your token lifetime. |
unmatched | The token map has no entry for the token origin. | Add the entry, or fix the token origin. |
check_unavailable | 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. | Gydr retries; check your service is up. A burst of new tokens waits out the minute. |
bad_signature | Your backend answered 403: it refused Gydr's signature. | Re-copy the secret or rotate it. Nobody is signed out for this. |
source_inactive | A backend source has not been activated. | Press Activate in the Console. |
source_not_ready | The WordPress plugin is older than 1.5.0, or its key is not registered. | Update the plugin or reconnect. |
misconfigured | Your backend answered something Gydr cannot use (wrong shape, or a cacheable response). | Fix the check endpoint — see the reference. |
Related: Sign-in source reference · Guests & data never to send · Plugins · Migrate to 4
