Identificación de usuarios
Identificar a los usuarios conecta las sesiones de chat anónimas con perfiles de usuario reales.
Cómo funciona
Cuando llamas a Respondo.identify(), los campos proporcionados se adjuntan a la conversación. Todos los campos son opcionales — pasa solo los que tengas. Por ejemplo, puedes enviar únicamente userId sin email ni nombre. Los agentes de soporte ven estos datos en el panel de detalles de la conversación.
Parámetros#
| Propiedad | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| string | opcional | Dirección de email del usuario | |
| name | string | opcional | Nombre para mostrar |
| userId | string | opcional | Tu ID interno de usuario o de visualización — se muestra tal cual en el panel |
| userHash | string | opcional | Firma HMAC-SHA256 para la verificación de identidad |
| metadata | object | opcional | Pares clave-valor de campos personalizados (plan, empresa, etc.) |
| properties | object | opcional | Propiedades de contacto personalizadas definidas en Agent Settings. Las claves deben coincidir con las definiciones de propiedades. Los valores se almacenan con el prefijo cp_ y se pueden filtrar en la Bandeja de entrada. |
// Tras un inicio de sesión correcto
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: { // propiedades de contacto personalizadas
account_type: user.accountType, // deben coincidir con las claves de Agent Settings
industry: user.industry,
contract_tier: user.tier
}
});
}identify() en cualquier momento — las llamadas realizadas antes de que widget.js termine de cargar se encolan en el fragmento y se reproducen automáticamente cuando el widget se inicializa. Los datos de identidad solo se descartan (con una advertencia en la consola) si cargas widget.js por tu cuenta y llamas a identify() antes de haber llamado nunca a init() — en configuraciones manuales, llama siempre primero a init().Visitantes anónimos#
Si no llamas a identify(), el widget asigna automáticamente un ID de visitante persistente almacenado en localStorage (clave respondoai_visitor_id). En el panel, la conversación aparece como Guest · Web widget.
| Modo | Visualización en el panel | HMAC requerido |
|---|---|---|
Sin identify() | Guest · Web widget | No |
identify({ email, name }) | Se muestran nombre + email | No — a menos que la Verificación de identidad esté activada; en ese caso, el email/nombre sin firmar se eliminan silenciosamente y la sesión permanece anónima |
identify({ userId }) | userId se muestra tal cual | No — a menos que la Verificación de identidad esté activada; entonces se requiere un userHash válido o la identidad se elimina |
identify({ userId, userHash }) | Identidad de usuario verificada | Sí — verificado criptográficamente |
Cuando la Verificación de identidad está activada para el canal, cualquier identify() que lleve email o userId sin un userHash válido se elimina en el servidor y el visitante permanece anónimo — consulta Verificación de identidad (HMAC) más abajo.
Identificación solo con userId (sin email ni nombre)#
Si tu plataforma no dispone de emails ni nombres de usuario — por ejemplo, solo tienes un ID de visualización interno — puedes pasar únicamente userId. No se necesita ningún otro campo. El panel mostrará el userId tal cual en los detalles de la conversación.
// Tu plataforma solo tiene un ID de visualización — con eso basta
Respondo.identify({
userId: user.displayId, // p. ej. "USR-4821" — se muestra en el panel
metadata: { // contexto adicional opcional
plan: 'premium',
region: 'eu-west'
}
});
// No se necesita email ni nombre — el widget funciona solo con userIduserHash (consulta Verificación de identidad más abajo). Sin HMAC, cualquiera puede pasar cualquier userId desde la consola del navegador.Google Tag Manager / identify() diferido#
Al integrar mediante GTM, es posible que los datos del usuario no estén disponibles cuando se carga la página. Dos enfoques:
// Si tu plataforma ya escribe el ID de usuario en localStorage:
Respondo.init({
agentId: 'YOUR_AGENT_ID',
localStorageKey: 'myapp_user_id' // lee localStorage.getItem('myapp_user_id') automáticamente
});
// No hace falta llamar a identify() — el widget toma el userId por su cuenta// 1. Inicializa el widget de inmediato (etiqueta de GTM)
Respondo.init({ agentId: 'YOUR_AGENT_ID' });
// 2. Más tarde, cuando aparezcan los datos del usuario (p. ej. desde dataLayer o tu 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 solo se usa si aún no se ha establecido ningún userId mediante identify(). Las llamadas explícitas a identify() siempre tienen prioridad.Verificación de identidad (HMAC)#
Sin verificación, cualquiera podría hacerse pasar por un usuario pasando un userId o un email falso. La verificación de identidad usa HMAC-SHA256 para demostrar criptográficamente que la identidad del usuario fue establecida por tu servidor, no por código del lado del cliente.
Cómo funciona#
- Activa la verificación de identidad en la configuración de tu canal — obtendrás una clave secreta.
- En tu servidor, calcula
HMAC-SHA256(secret, userId)— el secret es la clave y el userId es el mensaje — y envía el resultado al frontend. Si identificas a los usuarios solo por email (sin userId), firma el email en su lugar: la carga firmada es el userId cuando está definido, y si no, el email. Si pasas ambos, firma el userId; tiene prioridad. - Pasa el hash como
userHashenRespondo.identify(). - Respondo verifica el hash en el servidor. Si no es válido, se elimina la identidad y el usuario se trata como anónimo.
identify() que lleve userId o email debe incluir un userHash válido — de lo contrario, los campos de identidad se eliminan y el visitante se trata como anónimo.Ejemplos del lado del servidor#
const crypto = require('crypto');
const SECRET = process.env.RESPONDO_IDENTITY_SECRET;
function generateUserHash(userId) {
return crypto
.createHmac('sha256', SECRET)
.update(userId)
.digest('hex');
}
// En tu endpoint de API:
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()
# En tu vista / 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))
}Uso en el frontend#
// Obtén el hash desde TU servidor
const { userHash } = await fetch('/api/respondo-hash').then(r => r.json());
Respondo.identify({
email: user.email,
name: user.name,
userId: user.id,
userHash: userHash // firma HMAC-SHA256
});