Dynamic variables
Signed values
Visitor details your avatar can trust, because your server vouches for them.
When you need them
Anything in a web page can be changed by the visitor in their browser. For a name that doesn't matter. For a detail that unlocks something, it does: a visitor could type “Platinum” to get Platinum terms. Signed values stop that. Your server signs the details, and anything a visitor changes no longer checks out.
| Detail | Sign it? |
|---|---|
| Name, preferred language | Not needed |
| Membership plan, discount level, account status | Yes |
| An ID your systems act on (order, draft, customer) | Yes, or use an ID nobody can guess |
What you decide in the console
Require a verified visitor, in the agent's Embed dialog under Pass data from your app or website: a call starts only with details your server signed, and anyone else sees “Please sign in to talk to this assistant.” Put every detail you rely on in the token: a signed value always wins over an unsigned one with the same name.
Set it up
This part is for your developer, on your server.
1. Get the agent's signing secret
In the console, open the agent's Embed dialog, then Pass data from your app or website → Create a signing secret. Store it on your server, never in a web page. Each agent has its own secret.
Think it leaked? Choose Replace secret, then put the new one on your server. Tokens signed with the old secret stop counting as verified at once. If Require a verified visitor is on, visitors can't start a call until your server uses the new secret, so update it straight away.
2. Sign the details on your server
The token is a standard JWT signed with HS256, carrying the details in a vars claim and an expiry in exp (required). Make a fresh token for each page view, valid for an hour or less.
Node.js
// npm install jsonwebtoken
const jwt = require("jsonwebtoken");
const token = jwt.sign(
{ vars: { client_name: "John", customer_id: "c_123", subscription_plan: "Gold" } },
process.env.SIGNING_SECRET, // vsk_… from the console. Server only.
{ algorithm: "HS256", expiresIn: "1h" }
);Python
# pip install pyjwt
import os, time, jwt
token = jwt.encode(
{"vars": {"client_name": "John", "customer_id": "c_123", "subscription_plan": "Gold"},
"exp": int(time.time()) + 3600},
os.environ["SIGNING_SECRET"], # vsk_… from the console. Server only.
algorithm="HS256",
)PHP
// composer require firebase/php-jwt
use Firebase\JWT\JWT;
$token = JWT::encode(
['vars' => ['client_name' => 'John', 'customer_id' => 'c_123', 'subscription_plan' => 'Gold'],
'exp' => time() + 3600],
getenv('SIGNING_SECRET'), // vsk_… from the console. Server only.
'HS256'
);3. Pass the token instead of the details
SelviaAI.identify({ token: "<the token your server made>" });
<!-- or on the widget snippet -->
data-vars-token="<the token your server made>"
<!-- or in an iframe address or link -->
https://talk.selviaai.com/embed/emb_…#token=<the token your server made>- •Signed details count as verified, and win over unsigned details with the same name.
- •A token that has expired or doesn't check out is ignored; the call starts with any unsigned details only.
- •You can pass signed and unsigned details together, e.g. a signed plan and an unsigned name.
Security checklist
- •Keep the signing secret on your server. Anyone who has it can make tokens.
- •Treat unsigned details as something the visitor could have typed.
- •Put every detail you rely on in the token, and turn on Require a verified visitor, so a call can't start without one.
- •If a detail points at a record in your systems, use an ID nobody can guess, or sign it.
- •Keep token lifetimes short. A few minutes is enough if the page starts calls right away.