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
- •Only when signed, per detail, in your agent's Dynamic Instructions tab: the detail counts only when it was signed, and as missing otherwise, both for the avatar and in data handoffs. You can mark details the avatar never uses too, like an ID that only travels back to your systems.
- •Require a verified visitor, in the agent's Embed settings under Dynamic variables: a call starts only with signed details, and anyone else sees “Please sign in to talk to this assistant.”
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 settings, then Dynamic variables → 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: { name: "John", customer_id: "c_123", 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": {"name": "John", "customer_id": "c_123", "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' => ['name' => 'John', 'customer_id' => 'c_123', '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.
- •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.