User Identification
Identifying users connects anonymous chat sessions with real user profiles.
How it works
When you call Respondo.identify(), the provided fields are attached to the conversation. All fields are optional — pass only the ones you have. For example, you can send just userId without email or name. Support agents see this data in the conversation details panel.
Parameters#
| Property | Type | Required | Description |
|---|---|---|---|
| string | optional | User's email address | |
| name | string | optional | Display name |
| userId | string | optional | Your internal user or display ID — shown as-is in dashboard |
| userHash | string | optional | HMAC-SHA256 signature for identity verification |
| metadata | object | optional | Key-value pairs of custom fields (plan, company, etc.) |
| properties | object | optional | Custom contact properties defined in Agent Settings. Keys must match property definitions. Values are stored with cp_ prefix and are filterable in the Inbox. |
// After successful login
async function onLogin(user) {
await authenticateUser(user);
Respondo.identify({
email: user.email,
name: user.fullName,
userId: user.id,
metadata: {
plan: user.subscription.plan,
company: user.company.name,
role: user.role,
signedUp: user.createdAt
},
properties: { // custom contact properties
account_type: user.accountType, // must match keys from Agent Settings
industry: user.industry,
contract_tier: user.tier
}
});
}identify() after init(). If you call it before the widget is initialized, identity data will be ignored.Anonymous Visitors#
If you don't call identify(), the widget automatically assigns a persistent visitor ID stored in localStorage. In the dashboard, the conversation appears as Visitor XXXXXXXX (first 8 chars of the UUID).
| Mode | Dashboard display | HMAC required |
|---|---|---|
No identify() | Visitor a1b2c3d4 | No |
identify({ email, name }) | Name + email shown | No (but anyone can spoof) |
identify({ userId }) | userId shown as-is | No (unspoofable only with HMAC) |
identify({ userId, userHash }) | Verified user identity | Yes — cryptographically verified |
userId-only Identification (no email or name)#
If your platform doesn't have user emails or names — for example, you only have an internal display ID — you can pass just userId. No other fields are needed. The dashboard will show the userId as-is in conversation details.
// Your platform only has a display ID — that's enough
Respondo.identify({
userId: user.displayId, // e.g. "USR-4821" — shown in dashboard
metadata: { // optional extra context
plan: 'premium',
region: 'eu-west'
}
});
// No email or name needed — the widget works with just userIduserHash (see Identity Verification below). Without HMAC, anyone can pass any userId from the browser console.Google Tag Manager / deferred identify()#
When embedding via GTM, user data may not be available at page load. Two approaches:
// If your platform already writes the user ID to localStorage:
Respondo.init({
agentId: 'YOUR_AGENT_ID',
localStorageKey: 'myapp_user_id' // reads localStorage.getItem('myapp_user_id') automatically
});
// No identify() call needed — the widget picks up the userId on its own// 1. Init widget immediately (GTM tag)
Respondo.init({ agentId: 'YOUR_AGENT_ID' });
// 2. Later, when user data appears (e.g. from dataLayer or your app):
var waitForUser = setInterval(function() {
var uid = localStorage.getItem('myapp_user_id');
if (uid && window.Respondo && typeof window.Respondo.identify === 'function') {
clearInterval(waitForUser);
Respondo.identify({ userId: uid });
}
}, 500);localStorageKey is only used if no userId is already set via identify(). Explicit identify() calls always take precedence.Identity Verification (HMAC)#
Without verification, anyone could impersonate a user by passing a fake userId or email. Identity Verification uses HMAC-SHA256 to cryptographically prove the user's identity was set by your server, not by client-side code.
How it works#
- Enable Identity Verification in your channel settings — you'll get a secret key.
- On your server, compute
HMAC-SHA256(userId, secret)and send the result to the frontend. - Pass the hash as
userHashinRespondo.identify(). - Respondo verifies the hash server-side. If invalid, identity is stripped and the user is treated as anonymous.
Server-side examples#
const crypto = require('crypto');
const SECRET = process.env.RESPONDO_IDENTITY_SECRET;
function generateUserHash(userId) {
return crypto
.createHmac('sha256', SECRET)
.update(userId)
.digest('hex');
}
// In your API endpoint:
app.get('/api/respondo-hash', (req, res) => {
const hash = generateUserHash(req.user.id);
res.json({ userHash: hash });
});import hmac, hashlib, os
SECRET = os.environ['RESPONDO_IDENTITY_SECRET']
def generate_user_hash(user_id: str) -> str:
return hmac.new(
SECRET.encode(),
user_id.encode(),
hashlib.sha256
).hexdigest()
# In your view / endpoint:
user_hash = generate_user_hash(request.user.id)import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func GenerateUserHash(userID, secret string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(userID))
return hex.EncodeToString(mac.Sum(nil))
}Frontend usage#
// Fetch the hash from YOUR server
const { userHash } = await fetch('/api/respondo-hash').then(r => r.json());
Respondo.identify({
email: user.email,
name: user.name,
userId: user.id,
userHash: userHash // HMAC-SHA256 signature
});