- события
- backend
- frontend
Серверные и клиентские события: что отправлять откуда
Клиентские события описывают взаимодействие с интерфейсом, серверные — подтверждённые операции системы. Ошибка выбора источника превращает намерение в результат: клик по кнопке начинает считаться оплатой, хотя сервер отклонил операцию.
У одного события должен быть основной источник истины. Если один факт отправляют и браузер, и бэкенд, нужен явный ключ дедупликации и причина для двух источников.
Что удобно фиксировать в браузере
Клиент подходит для событий, существующих только в интерфейсе:
- показ важного элемента;
- начало заполнения формы;
- выбор варианта;
- переход между шагами;
- открытие подсказки;
- клиентская ошибка валидации;
- взаимодействие с функцией до отправки запроса.
Браузер знает визуальный контекст, но может закрыться, потерять сеть или быть заблокирован.
Что подтверждать на сервере
Сервер нужен для бизнес-фактов:
- аккаунт создан;
- доступ выдан;
- интеграция подключена;
- операция завершена;
- данные приняты и обработаны;
- платёж подтверждён;
- подписка продлена или отменена;
- приглашение принято.
Событие следует отправлять после фиксации результата, а не перед попыткой.
Начало, успех и ошибка
Один сценарий полезно разделить:
- integration_started — пользователь начал;
- integration_succeeded — сервер подтвердил;
- integration_failed — операция завершилась ошибкой.
Это позволяет отличить проблему точки входа от технической ошибки и узнать, сколько начатых действий зависло без результата.
Два источника одного сценария
Интерфейс и сервер могут описывать разные факты:
| Источник | Событие | Смысл |
|---|---|---|
| браузер | payment_form_opened | пользователь увидел форму |
| браузер | payment_submitted | отправил данные |
| сервер | payment_succeeded | платёж подтверждён |
| сервер | payment_failed | получен итоговый отказ |
Это не дубли, потому что события отвечают на разные вопросы.
Повторная доставка
Сеть ненадёжна, поэтому отправитель может повторить запрос. Для критичных фактов используйте:
- event_id;
- id операции;
- id платежа;
- idempotency key;
- уникальное сочетание сущности и версии.
Приёмник должен отличать повторную доставку от повторного реального действия. Два платежа одного клиента — не обязательно дубль.
Время
Храните:
- время события на источнике;
- время приёма;
- при необходимости время обработки.
Клиентские часы могут быть неверными. Серверное время надёжнее, но офлайн-событие приходит позже реального действия. Для путей используйте правила сортировки и контролируйте аномальную разницу.
Идентификаторы
Браузер до входа знает анонимный id, после входа — user_id. Сервер может знать user_id, account_id и id бизнес-объекта.
Не пытайтесь соединять события только по email. Используйте внутренние псевдонимные ключи и явное правило связи. Подробности — в статье идентификация пользователей.
Свойства
Клиент может передать:
- вариант интерфейса;
- место входа;
- локальную версию;
- тип устройства.
Сервер лучше подтверждает:
- итоговый статус;
- тип операции;
- тариф на момент факта;
- роль и доступ;
- id сущности;
- код ошибки.
Не доверяйте клиенту свойства, влияющие на финансовый или административный вывод, если сервер может определить их сам.
Единый контракт
Оба источника должны использовать общий словарь:
- правила имён;
- типы;
- обязательные поля;
- версию схемы;
- формат времени;
- правила идентификации;
- список запрещённых данных;
- владельца.
Пример словаря приведён в статье как разметить события B2B SaaS.
Ошибки интеграции
Отправлять успех до ответа
Воронка показывает высокую конверсию, хотя операция падает позже.
Дублировать факт из двух источников
Оплаты и регистрации удваиваются.
Терять контекст
Серверное событие не содержит account_id или способ запуска, поэтому его нельзя связать с клиентским шагом.
Передавать лишние данные
В свойства попадают текст формы, токен или адрес без необходимости.
Не различать retry
Повтор запроса считается новым действием.
Тестирование
Проверьте минимум четыре сценария:
- успешное действие;
- ожидаемая ошибка;
- повторная доставка;
- потеря сети или закрытие вкладки.
Сверьте последовательность в истории пользователя и независимый факт на сервере.
Итог
Браузер описывает интерфейсный путь, сервер подтверждает бизнес-результат. Разделите начало, успех и ошибку, задайте основной источник и дедупликацию. Тогда события образуют проверяемую последовательность вместо набора несогласованных кликов.