- Guías
- Identificar al usuario
Identificar al usuario
Adjuntá un id opaco (nunca PII) a grabaciones y votos para ver feedback y replays por usuario, desde el script o en runtime. Verlo es Pro. Para tickets, firmá el correo del visitante con el secreto de identidad.
Por defecto cada voto y cada grabación quedan Anonymous, y todo funciona. Identify te deja adjuntar tu id para un usuario, así un voto o un replay se pueden rastrear hasta la persona que lo hizo — y así podés saltar de un puntaje de satisfacción directo a las grabaciones de ese usuario.
Es del todo opcional. Sin esto no se rompe nada; simplemente ves “Anonymous”.
La regla de oro
Sección titulada «La regla de oro»user-ref es un id opaco — el id que tu propia base ya tiene para ese usuario
(user-123, a1b2c3). Nunca un email, nunca un nombre, nunca PII.
El motivo es físico: el id viaja dentro del bundle, a la vista en el navegador. Cualquier cosa que pongas ahí es visible para quien abra las dev tools. Si querés nombres o emails reales en el dashboard, eso es un v2 server-side y no va por acá.
Dos formas de fijarlo
Sección titulada «Dos formas de fijarlo»Las dos son opcionales; usá la que te sirva. Elegí una.
En el script, cuando el id se conoce al renderizar la página:
<script src="https://app.espejo.dev/sdk/espejo.dom.js" data-key="pk_live_..." data-user-ref="user-123"></script>En runtime, en el momento en que tu usuario loguea (ideal para SPAs, donde la página nunca se recarga):
window.espejo.identify("user-123");
// Al desloguear, limpialo — los votos y grabaciones que siguen vuelven a Anonymous:window.espejo.identify(null);Dónde se ve
Sección titulada «Dónde se ve»En la consola, Satisfaction → Recent votes muestra el user_ref al lado de cada
voto. Desde ahí podés filtrar por usuario, y saltar de un usuario directo a sus
grabaciones. Un id opaco ata las dos vistas.
Identidad verificada para tickets
Sección titulada «Identidad verificada para tickets»La sección Tickets del widget de chat y las
tools de tickets del agente le muestran a un visitante sus tickets. Para eso
no alcanza un id opaco: Espejo tiene que saber el correo de la persona, y tiene
que estar seguro de que es suyo. Es algo distinto de user-ref, y los dos
conviven.
Tu backend prueba el correo firmándolo con el secreto de identidad del proyecto. El widget manda el correo y la firma en cada pedido de tickets y en cada mensaje del chat. Sin un par que verifique no hay tickets: el widget oculta la sección y el agente nunca recibe las tools de tickets. Un correo solo no se acepta nunca.
Conseguí el secreto de identidad
Sección titulada «Conseguí el secreto de identidad»En la consola, abrí Integraciones. Con Soporte conectado, la tarjeta
Tickets tiene el bloque Identidad del visitante. Generar secreto lo
muestra una sola vez: copialo al entorno de tu servidor (por ejemplo
ESPEJO_IDENTITY_SECRET). Después la consola sólo muestra sus últimos cuatro
caracteres.
Rotar lo reemplaza. Las firmas hechas con el secreto viejo dejan de valer en el pedido siguiente, así que los visitantes pierden sus tickets hasta que tu backend firme con el nuevo.
Prendé Tickets en el widget
Sección titulada «Prendé Tickets en el widget»En la consola, abrí la pestaña Widget y prendé Tickets en el bloque
Menú. Se puede prender cuando Soporte está conectado con Mostrar tickets
en el widget prendido. Sin eso, el widget no muestra la sección Tickets,
GET /v1/tickets contesta 404 y el agente no recibe lookup_tickets.
Mientras no haya secreto de identidad, la fila avisa que nadie va a ver
Tickets.
Firmá el correo en tu servidor
Sección titulada «Firmá el correo en tu servidor»La firma es hex(HMAC-SHA256(secreto, correo)), con el correo recortado y en
minúsculas. El resultado son 64 caracteres hexadecimales.
- Firmá sólo un correo que tu sitio verificó (una dirección confirmada, o una que viene de tu proveedor de identidad). La firma le dice a Espejo que el correo es de esa persona: una dirección firmada que nadie confirmó abre los tickets de quien sea su dueño.
- Sólo se pueden firmar correos ASCII. Sacá sólo los blancos ASCII de las
puntas (espacio, tab,
\n,\v,\f,\r), comprobá que lo que queda es ASCII visible y sin espacios, y recién ahí pasalo a minúsculas. Un correo con cualquier otra cosa no tiene identidad: el widget lo ignora yGET /v1/ticketscontesta401. - Un dominio con acentos o de otro alfabeto (IDN) se firma en punycode, la
forma
xn--:ana@münchen.examplese firma como[email protected]. Pasale esa misma forma al widget.
Los tres ejemplos de abajo hacen exactamente eso, así que dan la misma firma que comprueba Espejo.
Node
import { createHmac } from "node:crypto";
const trimmed = user.email.replace(/^[\t\n\v\f\r ]+|[\t\n\v\f\r ]+$/g, "");// Si no es ASCII: sin identidad.const email = /^[\x21-\x7e]+$/.test(trimmed) ? trimmed.toLowerCase() : null;const hash = email && createHmac("sha256", process.env.ESPEJO_IDENTITY_SECRET).update(email).digest("hex");Python
import hashlib, hmac, os, re
trimmed = user.email.strip(" \t\n\v\f\r")# Si no es ASCII: sin identidad.email = trimmed.lower() if re.fullmatch(r"[\x21-\x7e]+", trimmed) else Nonehash = email and hmac.new(os.environ["ESPEJO_IDENTITY_SECRET"].encode(), email.encode(), hashlib.sha256).hexdigest()PHP
$trimmed = trim($user->email, " \t\n\v\f\r");// Si no es ASCII: sin identidad. strtr baja sólo ASCII, con cualquier locale.$email = preg_match('/^[\x21-\x7e]+$/', $trimmed) ? strtr($trimmed, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : null;$hash = $email ? hash_hmac('sha256', $email, getenv('ESPEJO_IDENTITY_SECRET')) : null;Pasáselo al widget
Sección titulada «Pasáselo al widget»En el script, cuando la página se arma para un usuario logueado:
<script src="https://app.espejo.dev/sdk/espejo.chat.js" data-key="pk_live_..." data-user-hash="3f5c...e91a" data-user-name="Ana" defer></script>Escapá el correo al escribirlo en el atributo, como cualquier valor que ponés
en HTML (&, <, >, " y '). La mayoría de los motores de plantillas lo
hacen solos; si armás la etiqueta concatenando texto, hacelo vos. Lo mismo vale
para el nombre.
data-user-name es opcional y solo sirve para saludar al visitante en Inicio
(“Hola, Ana.”). Se usa solo mientras el correo y el hash son válidos, se corta
en 40 caracteres y nunca viaja a la API ni se guarda. No se firma: no cambia
lo que el visitante puede ver.
En una SPA, después del login y al cerrar sesión. El tercer argumento, el nombre, es opcional:
// Al cerrar sesión: Tickets desaparece y el chat arranca una conversación nueva.EspejoChat.identify(null);El widget los manda en los headers x-espejo-user-email y x-espejo-user-hash.
GET /v1/tickets contesta 401 si faltan o no verifican, y 404 si la sección
Tickets no está prendida en el proyecto.
Por qué el secreto nunca va al navegador
Sección titulada «Por qué el secreto nunca va al navegador»Quien tenga el secreto puede firmar cualquier correo y leer los tickets de esa persona. La firma se calcula donde vive el secreto, en tu servidor, y sólo para el usuario que está logueado. Nunca pongas el secreto en la página, en un bundle ni en una app móvil. Si se filtra, rotalo.
El correo y su firma sí llegan al navegador, y está bien: sólo abren los tickets de esa persona, la misma que ya está logueada. No se adjuntan a grabaciones ni a votos, y Espejo no guarda el correo.
Una identidad por conversación
Sección titulada «Una identidad por conversación»El primer mensaje del chat que llega con un par válido deja esa identidad pegada
a la conversación. Un pedido posterior en la misma conversación con otra
identidad, o sin ninguna, recibe 409 con el código identity_changed, y nada
de esa conversación: el widget arranca una nueva y manda el mensaje otra vez,
una sola vez.
El widget arranca una conversación nueva cuando identify cambia de usuario, y
también cuando la página carga con otra persona. Junto al id de la conversación
guarda, en sessionStorage, una huella de quién la abrió (nunca el correo ni el
hash). Si la página carga con otra identidad, o sin ninguna después de una
conversación que tenía, descarta la conversación guardada y la tarjeta
Continuar de Home.