Appearance
Identity verification
If your site has accounts, the chat can know who it is talking to. Your page passes the user's id, name and email, plus a hash your server computes with a secret only it and the chat server know. With a valid hash the visitor is verified: the agent and your team can trust the details, and the user's conversations follow them from device to device.
1. Get the identity secret
In the admin panel, open the bot's Security tab and create an identity secret. It starts with wfs_ and is shown once: store it on your server (an environment variable such as WIREFACE_IDENTITY_SECRET), never in a page. Making a new one replaces the old one, and hashes made with the old one stop working. (The REST API's POST /api/v1/bots/{id}/identity-secret does the same.)
Then choose the identity mode (security.identity.mode):
| Mode | What happens |
|---|---|
off (default) | The page's user is ignored. |
optional | Visitors may be anonymous. A user with a valid hash is verified; one without a hash is kept but marked unverified; one with a wrong hash is ignored (identity_invalid). |
required | Every visitor needs a valid hash. With no user the chat refuses to connect (identity_required); with a hash that doesn't match, too (identity_invalid). Make sure the bot has a secret first. |
Publish the bot after changing either.
2. Compute the hash on your server
The hash is HMAC-SHA256(identity secret, user id), written as lowercase hex. The user id is whatever string you pass as user.id (up to 200 characters).
js
import { createHmac } from 'node:crypto';
export function wirefaceHash(userId) {
return createHmac('sha256', process.env.WIREFACE_IDENTITY_SECRET).update(String(userId)).digest('hex');
}python
import hashlib
import hmac
import os
def wireface_hash(user_id):
secret = os.environ["WIREFACE_IDENTITY_SECRET"].encode()
return hmac.new(secret, str(user_id).encode(), hashlib.sha256).hexdigest()php
<?php
function wireface_hash($userId) {
return hash_hmac('sha256', (string) $userId, getenv('WIREFACE_IDENTITY_SECRET'));
}go
package chat
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"os"
)
func WirefaceHash(userID string) string {
mac := hmac.New(sha256.New, []byte(os.Getenv("WIREFACE_IDENTITY_SECRET")))
mac.Write([]byte(userID))
return hex.EncodeToString(mac.Sum(nil))
}3. Pass it to the chat
Render the user into the page with the hash. With the script tag, set window.wirefaceChatSettings before widget.js loads:
html
<script>
window.wirefaceChatSettings = {
bot: 'pk_your_bot_id',
user: {
id: '42',
hash: 'the hex your server computed for 42',
name: 'Ana Silva',
email: 'ana@example.com',
},
};
</script>
<script src="https://chat.example.com/widget.js" async></script>With JavaScript or the npm package, pass user to boot(), bootWirefaceChat() or the React component. Escape the values properly when you write them into HTML (a JSON encoder that escapes < does it).
attributes takes more facts to keep with the visitor (plan, company and so on). The full shape is in the JavaScript API.
examples/identity-node/ in the repo is a small Node server that signs a user in and renders the page with the hash (run it with WIREFACE_HOST, WIREFACE_BOT and IDENTITY_SECRET set).
Signing in and out
- Signing in on a page that already has the chat: call
identify({ id, hash, name, email }). The details apply straight away. The rest of the user's history (below) joins the chat when it next connects, for example on the next page. - Signing out: call
WirefaceChat.shutdown({ forget: true }). It removes the chat and deletes the visitor token and conversation it kept in your site's storage, so the next person on that browser starts fresh. Boot it again afterwards if the chat should stay on the page for anonymous visitors (the React component starts a new chat by itself the next time it mounts).
The server protects signed-in users even if a page gets this wrong:
- A visitor token that belongs to a verified user only carries on for that same user, with a valid hash. After sign-out (no
user), or when a different user signs in on the same browser, the server starts a fresh visitor, so nobody sees the previous user's conversations. - Signing a different user in with
identify()while a verified user has the chat is refused withidentity_invalid. Callshutdown({ forget: true })on sign-out, then boot again.
What verification gets you
- Conversations follow the user. When a verified user connects, the server picks up their earlier visitor record: their conversations carry on across devices and sign-outs. Anything they did anonymously in that browser before signing in moves into their history.
- The agent knows who it is talking to. It is told the visitor's name and email, marked as verified or not. In the bot's instructions and guardrails,
{{visitor.name}}and{{visitor.email}}are filled in for verified visitors only (otherwise they are empty), alongside{{page.url}}(origin and path, no query string),{{page.title}},{{agent.name}},{{agent.role}}and{{business.name}}. - Your team sees the user in the admin panel, and you can find their data by your own id for data requests (
GET /api/v1/visitors?userId=42, see Privacy). - HTTP tools can use it:
{{visitor.userId}}and{{visitor.email}}(filled in for verified visitors only) and{{visitor.verified}}in a tool's request. See Tools and MCP.
Unverified identities
In optional mode a user without a hash is accepted as given, so a visitor can claim any id or name. The agent is told the details are unverified, and HTTP tools only get {{visitor.userId}} and {{visitor.email}} for verified visitors ({{visitor.verified}} says which). Don't let the agent act on an account based on what an unverified visitor says.
Problems
identity_required: the bot requires identity and the page sent nouserat all.identity_invalid: the hash doesn't match (inrequiredmode the chat then refuses to connect; inoptionalmode it carries on anonymously), or a different user tried to take over a signed-in chat.
Check that you hash exactly the string you pass as id (42 and "42 " differ) and that you use the current secret. Upper- and lowercase hex both work. See Errors.