Идентификация посетителей и передача контекста
Как сообщать о вошедших пользователях через ReactiveChat('identify'), подписывать userHash с HMAC-SHA256 на сервере, менять секрет и передавать ассистенту контекст страницы, например товар или корзину.
Если сайт знает, кто перед ним, сообщите чату. Тогда команда видит в панели имя вместо «Посетитель 4f2a», а функции вроде данных клиентов и клиентского портала вообще становятся возможны.
Принцип: браузер ничего не доказывает. Всё, что страница сообщает через identify, посетитель может подделать в консоли. Пользователь считается подтверждённым только с подписью, которую ваш сервер вычислил с секретом, никогда не попадающим в браузер.
Вызов в браузере
ReactiveChat('identify', {
userId: '4711',
email: 'kim@example.com',
name: 'Kim Berger',
userHash: '9c1f…',
exp: 1792503600
});
- userId (строка, рекомендуется) — ваш постоянный ID пользователя. Не электронная почта и не порядковый номер, который может измениться.
- email (строка, необязательно) — отображается в панели. Подтверждён, только если тоже подписан (ниже).
- name (строка, необязательно) — отображаемое имя в панели.
- userHash (строка, обязателен для подтверждения) — 64 шестнадцатеричных символа, вычисляется на сервере.
- exp (целое число, рекомендуется) — срок действия хеша во времени Unix в секундах, максимум 24 часа вперёд.
Другие поля отбрасываются. identify можно вызвать до загрузки виджета; вызов попадёт в очередь и не вызовет раннюю загрузку. Значения передаются при подключении, а если виджет уже подключён — немедленно.
Секрет
В аккаунте в Проект → Подтверждение личности создаётся секрет проекта (право: изменение проекта). Он состоит из 64 шестнадцатеричных символов и полностью показывается ровно один раз, затем только в скрытом виде. Поместите его в окружение сервера; никогда в браузерный скрипт, приложение или репозиторий.
Важно для вычисления: ключ HMAC — сама строка из 64 символов, точно как показана, а не декодированные из неё байты.
Вычисление подписи
userHash = hex( HMAC_SHA256( secret, userId + "." + exp ) )
Шестнадцатеричная запись строчными буквами, 64 символа. С подтверждённой электронной почтой:
userHash = hex( HMAC_SHA256( secret, userId + "." + exp + "." + email ) )
Только во втором варианте адрес считается подтверждённым. Для него нужен exp.
PHP:
<?php
$geheim = getenv('RC_IDENT_SECRET'); // 64 hex characters from the account
$userId = (string) $kunde->id;
$exp = time() + 3600; // at most 24 h
$userHash = hash_hmac('sha256', $userId . '.' . $exp, $geheim);
?>
<script nonce="<?= $cspNonce ?>">
ReactiveChat('identify', {
userId: <?= json_encode($userId) ?>,
userHash: <?= json_encode($userHash) ?>,
exp: <?= (int) $exp ?>
});
</script>
Node.js:
const crypto = require('crypto');
function rcIdentitaet(kunde) {
const userId = String(kunde.id);
const exp = Math.floor(Date.now() / 1000) + 3600;
const userHash = crypto.createHmac('sha256', process.env.RC_IDENT_SECRET)
.update(userId + '.' + exp)
.digest('hex');
return { userId, userHash, exp };
}
Python:
import hmac, hashlib, os, time
def rc_identitaet(kunde_id: str) -> dict:
exp = int(time.time()) + 3600
msg = f"{kunde_id}.{exp}".encode()
key = os.environ["RC_IDENT_SECRET"].encode() # the hex string as text
return {"userId": kunde_id, "exp": exp,
"userHash": hmac.new(key, msg, hashlib.sha256).hexdigest()}
С электронной почтой (PHP):
$userHash = hash_hmac('sha256', $userId . '.' . $exp . '.' . $email, $geheim);
Адрес нужно подписать ровно в том виде, в котором он передаётся в identify.
Без встроенного скрипта (строгая CSP)
Если Content Security Policy не разрешает встроенные скрипты, выведите значения как данные и вызовите identify из своего файла скрипта:
<meta name="rc-ident" content='{"userId":"4711","userHash":"9c1f…","exp":1792503600}'>
// /js/chat-ident.js
var m = document.querySelector('meta[name="rc-ident"]');
if (m) { ReactiveChat('identify', JSON.parse(m.content)); }
В одностраничных приложениях после входа получите три значения с сервера через fetch.
Что проверяет сервер
exp— целое число (время Unix в секундах), находится в будущем и не более чем на 24 часа вперёд (плюс допуск 5 минут).- Хеш соответствует
userId + "." + exp(или варианту с почтой). Прописные буквы в хеше допускаются. - Сравнение выполняется за постоянное время.
Пользователь подтверждён и актуален, если имеет действительный хеш и exp. Только тогда доступны данные клиентов и клиентский портал.
Старый вариант без exp: userHash = HMAC_SHA256(secret, userId) по-прежнему принимается как подтверждённый, но не как актуальный; достаточно для истории разговоров и отображения в панели, но не для данных клиентов. Переведите существующие интеграции на вариант с exp.
Если проверка не пройдена
Чат продолжает работать, но анонимно. Виджет получает ошибку auth_failed с причиной в detail.reason:
- no_hash — отсутствует
userHash. - no_secret — секрет для проекта не настроен.
- bad_exp —
expне является корректным целым числом в секундах (часто переданы миллисекунды). - expired —
expв прошлом (страница давно открыта, неверные часы сервера). - exp_too_far —
expболее чем на 24 часа вперёд. - bad_hash — хеш не совпадает: неверный секрет, порядок,
userIdподписан как число вместо строки, почта записана иначе.
Во вкладке сети инструментов разработчика причина находится в кадре error WebSocket-подключения; init_ok.identity показывает verified и reason.
Настройки «Разрешать только подтверждённых посетителей» нет: неподтверждённые всегда общаются анонимно.
Ротация секрета
- Создать новый секрет: предыдущий действует ещё 24 часа. За это время установите новый на серверах.
- Удалить: немедленно аннулирует оба. Все пользователи считаются неподтверждёнными до настройки нового секрета.
Смена пользователей и выход
- При вызове
identifyс другим пользователем (например, после смены аккаунта в SPA) виджет отделяет черновик ввода от предыдущего пользователя. - Отдельной команды выхода нет. Идентификация действует только для текущего просмотра страницы: после выхода предоставляйте страницы без
identify. Разговор и ID посетителя остаются в браузере; если на общем устройстве больше ничего не должно отображаться, посетитель может удалить данные в виджете.
Передача контекста
Кроме идентификации страница может сообщать ассистенту и команде, что происходит сейчас, например какой товар показан или что лежит в корзине. Для этого служит track:
ReactiveChat('track', 'warenkorb', {
page_type: 'cart',
cart_value: 129.80,
cart_items: 3,
currency: 'EUR'
});
Принимаются только следующие поля; всё остальное отбрасывается:
- Страница:
url,path,title,referrer,page_type,landing_path - Товар:
product_id,variant_id,category,price,currency,in_stock - Корзина:
cart_value,cart_items - Кампания:
utm_source,utm_medium,utm_campaign,gclid,msclkid,fbclid - Сигналы:
intent,intent_confidence,rage_score,scroll_pct,dwell_ms
Адрес, заголовок, источник перехода и параметры кампаний виджет и так фиксирует при каждом переходе. Контекст передаётся только с согласием (Интеграция конфиденциальности). Не записывайте в эти поля персональные данные; для этого есть identify.
Мобильные приложения
В приложении передавайте идентификационные данные через JavaScript после загрузки WebView, никогда через адрес. Здесь тоже хеш вычисляется на сервере, а не в приложении: Мобильные приложения.
Далее: Конечная точка данных клиентов · SPA и переходы между страницами
Обновлено: