Идентификация пользователей
Идентификация связывает анонимные сессии чата с реальными профилями пользователей.
Как это работает
Когда вы вызываете Respondo.identify(), переданные поля прикрепляются к диалогу. Все поля необязательны — передавайте только те, что у вас есть. Например, можно отправить только userId без email или имени. Операторы поддержки видят эти данные на панели деталей диалога.
Параметры#
| Свойство | Тип | Обязательное | Описание |
|---|---|---|---|
| string | необязательно | Email-адрес пользователя | |
| name | string | необязательно | Отображаемое имя |
| userId | string | необязательно | Ваш внутренний ID пользователя или отображаемый ID — показывается как есть в панели |
| userHash | string | необязательно | Подпись HMAC-SHA256 для проверки личности |
| metadata | object | необязательно | Пары «ключ-значение» с пользовательскими полями (plan, company и т. д.) |
| properties | object | необязательно | Пользовательские свойства контакта, заданные в настройках агента. Ключи должны совпадать с определениями свойств. Значения хранятся с префиксом cp_ и доступны для фильтрации в Инбоксе. |
// После успешного входа
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: { // пользовательские свойства контакта
account_type: user.accountType, // должны совпадать с ключами из настроек агента
industry: user.industry,
contract_tier: user.tier
}
});
}identify() можно вызывать в любой момент — вызовы, сделанные до окончания загрузки widget.js, ставятся фрагментом в очередь и автоматически воспроизводятся после инициализации виджета. Данные идентификации отбрасываются (с предупреждением в консоли) только если вы загружаете widget.js самостоятельно и вызываете identify() до первого вызова init() — при ручной установке всегда сначала вызывайте init().Анонимные посетители#
Если вы не вызываете identify(), виджет автоматически присваивает постоянный visitor ID, сохраняемый в localStorage (ключ respondoai_visitor_id). В панели диалог отображается как Guest · Web widget.
| Режим | Отображение в панели | Требуется HMAC |
|---|---|---|
Без identify() | Guest · Web widget | Нет |
identify({ email, name }) | Показываются имя + email | Нет — если не включена проверка личности; тогда неподписанные email/имя молча отбрасываются, и сессия остаётся анонимной |
identify({ userId }) | userId показывается как есть | Нет — если не включена проверка личности; тогда требуется валидный userHash, иначе личность отбрасывается |
identify({ userId, userHash }) | Проверенная личность пользователя | Да — криптографически проверено |
Когда для канала включена проверка личности, любой вызов identify() с email или userId без валидного userHash очищается на стороне сервера, и посетитель остаётся анонимным — см. «Проверка личности (HMAC)» ниже.
Идентификация только по userId (без email и имени)#
Если на вашей платформе нет email или имён пользователей — например, есть только внутренний отображаемый ID — можно передать только userId. Другие поля не нужны. В панели userId будет показан как есть в деталях диалога.
// У вашей платформы есть только отображаемый ID — этого достаточно
Respondo.identify({
userId: user.displayId, // например «USR-4821» — показывается в панели
metadata: { // необязательный дополнительный контекст
plan: 'premium',
region: 'eu-west'
}
});
// email и имя не нужны — виджет работает только с userIduserHash (см. «Проверку личности» ниже). Без HMAC кто угодно может передать любой userId из консоли браузера.Google Tag Manager / отложенный вызов identify()#
При встраивании через GTM данные пользователя могут быть недоступны в момент загрузки страницы. Два подхода:
// Если ваша платформа уже записывает ID пользователя в localStorage:
Respondo.init({
agentId: 'YOUR_AGENT_ID',
localStorageKey: 'myapp_user_id' // автоматически читает localStorage.getItem('myapp_user_id')
});
// вызов identify() не нужен — виджет сам подхватывает userId// 1. Немедленно инициализируем виджет (тег GTM)
Respondo.init({ agentId: 'YOUR_AGENT_ID' });
// 2. Позже, когда появятся данные пользователя (например, из dataLayer или вашего приложения):
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 используется только если userId ещё не задан через identify(). Явные вызовы identify() всегда имеют приоритет.Проверка личности (HMAC)#
Без проверки кто угодно мог бы выдать себя за пользователя, передав поддельный userId или email. Проверка личности использует HMAC-SHA256, чтобы криптографически доказать, что личность пользователя задана вашим сервером, а не клиентским кодом.
Как это работает#
- Включите проверку личности в настройках канала — вы получите секретный ключ.
- На вашем сервере вычислите
HMAC-SHA256(secret, userId)— секрет является ключом, userId — сообщением — и отправьте результат на фронтенд. Если вы идентифицируете пользователей только по email (без userId), подписывайте email: подписываемое значение — userId, если он задан, иначе email. Если переданы оба, подписывайте userId — он имеет приоритет. - Передайте хеш как
userHashвRespondo.identify(). - Respondo проверяет хеш на стороне сервера. Если он неверен, данные идентификации удаляются, и пользователь считается анонимным.
identify() с userId или email должен содержать валидный userHash — иначе поля идентификации отбрасываются, и посетитель считается анонимным.Примеры на стороне сервера#
const crypto = require('crypto');
const SECRET = process.env.RESPONDO_IDENTITY_SECRET;
function generateUserHash(userId) {
return crypto
.createHmac('sha256', SECRET)
.update(userId)
.digest('hex');
}
// В вашем 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()
# В вашем представлении / эндпоинте:
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))
}Использование на фронтенде#
// Получаем хеш с ВАШЕГО сервера
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
});