Перейти к основному содержимому

События

События — это основа аналитики в Metriox. Каждое действие пользователя в вашем Telegram-боте может быть записано как событие.

Что такое событие?

Событие — это любое действие или взаимодействие пользователя с вашим ботом:

  • Нажатие на кнопку
  • Отправка команды
  • Просмотр экрана
  • Завершение покупки
  • Любое кастомное действие

Структура события

События в Metriox платформо-агностичны и состоят из:

Таблица событий в Metriox: колонки Timestamp (UTC), Event, Text, User, Source, Origin, Type и Details, строки с событиями callback_query и message

Базовые поля

ПолеТипОписание
event_idUUIDУникальный идентификатор события
event_nameStringНазвание события (например, message)
platform_user_idStringID пользователя в Telegram
session_idUUIDID сессии пользователя
tenant_idUUIDID вашего бота в Metriox
received_atDateTimeВремя получения события сервером
created_atDateTimeВремя создания события

Дополнительные поля

  • body (String, nullable) — текстовое содержимое события
  • props (JSON) — произвольные свойства события в формате JSON

Единый формат независимо от источника

Данные в вашем боте могут собираться разными способами — через токен бота (опрос Telegram по MTProto), через серверный SDK поверх Bot API, через WebApp-SDK в браузере или напрямую по HTTP API. Независимо от источника Metriox приводит все события к одной канонической структуре на стороне сервера: одинаковые имена событий, одни и те же разделы $-свойств и одинаковые значения полей.

Это значит, что данные любого происхождения одинаково видны и доступны в дашборде, фильтрах и сегментах — вам не нужно знать, каким способом было собрано событие, чтобы построить по нему отчёт.

Как это устроено

Приведение к канону выполняется один раз, на входе (ingest). Чем меньше преобразований — тем предсказуемее данные, поэтому SDK и воркер отдают поля максимально близко к финальному виду, а сервер лишь достандартизирует их. Историческим данным это не мешает: старые события дочитываются в том же каноническом виде.

Канонические имена событий (Telegram)

События из Telegram получают каноническое имя по смыслу действия, а не по способу доставки. Ключевой принцип: одно действие — одно имя, а детали выражаются свойствами.

Например, любое сообщение — входящее или исходящее, текстовое или с вложением, новое или отредактированное — это одно событие message. Различить их можно по свойствам:

СвойствоЧто показывает
$tg.directionoutbound — ответ бота, inbound — сообщение пользователя
$tg.is_editedсообщение было отредактировано
$tg.content_typeчто было в сообщении (text, photo, voice, …) — одинаково на любом подключении
$tg.message_typeисходное поле Bot API SDK; для группировок используйте content_type
$tg.chat_typeтип чата (private, group, supergroup, channel)
$tg.entitiesформатирование текста (жирный, ссылки, код)

Основные канонические имена:

Имя событияКогда возникает
messageлюбое сообщение (см. свойства выше)
callback_queryнажата inline-кнопка
inline_queryinline-запрос к боту
chosen_inline_resultвыбран inline-результат
poll / poll_voteопрос / голос в опросе
reactionреакция на сообщение
pre_checkout_query, shipping_query, successful_paymentэтапы оплаты
my_chat_member, chat_member, chat_join_requestизменение участия в чате (в том числе блокировка бота)
message_deletedсообщения удалены
business_messageсообщение через Telegram Business
Направление в переписке

Metriox использует $tg.direction, чтобы показывать переписку двумя сторонами: сообщения пользователя — слева, ответы бота — справа.

Поле заполняется на любом источнике, но ответы бота нужно ещё уметь увидеть. Bot API принципиально не присылает боту его собственные отправленные сообщения, поэтому на Bot API их сообщает сам бот: оберните клиент через WithMetrioxCapture(...) в C#-SDK, и это произойдёт автоматически. Подключение по токену бота (MTProto) видит исходящие сообщения само, но не получает личные переписки — их приносит только SDK. Подробнее в SDK.

Идентификатор события и дедупликация

event_id вычисляется детерминированно из «естественных» координат Telegram — например, из идентификатора чата и идентификатора сообщения. Отсюда два практических следствия:

  • повторная доставка не удваивает данные. Если Telegram или ваш бот отправит одно и то же обновление дважды (перезапуск, повтор вебхука, переподключение), это останется одним событием;
  • двойное подключение не удваивает счёт. Если один и тот же бот подключён и по токену, и через SDK, оба способа вычислят для одного действия одинаковый event_id.
Что именно происходит при двойном подключении

Здесь легко ошибиться, поэтому точная формулировка:

Результат
event_id у обеих копийсовпадает
Строк в хранилищедве — они не схлопываются в одну
Списывается из квоты событийодна

Строки намеренно остаются раздельными: у них разные $source.channel, а также могут различаться session_id и platform_user_id, поэтому отчёт с привязкой к конкретному источнику продолжает находить свои данные. Вторая копия помечается свойством $meta.unbilled_duplicate и не расходует квоту.

Дедупликация счёта работает не для всех типов событий: она применяется там, где оба способа подключения сообщают одинаковые «естественные» координаты Telegram — обычные сообщения, правки (если Telegram прислал время правки), нажатия кнопок, инлайн-запросы, платёжные запросы и сообщения бизнес-аккаунта.

Пока считаются отдельно: реакции, голоса в опросах и выбранные инлайн-результаты. Для остальных типов вопрос не стоит — их физически видит только один способ подключения, поэтому дубликата не возникает.

Почему не update_id

Может показаться, что для этого подходит update_id из Bot API. Он не подходит: update_id существует только в потоке getUpdates/вебхука Bot API, а в MTProto его нет вообще — там обновления нумеруются курсорами сессии (pts/qts), которые различаются у каждого клиента и не являются свойством самого события. Поэтому идентификатор строится из координат, которые видны обоим способам подключения.

Ваши кастомные события используют любое имя, которое вы задаёте (purchase_completed, screen_view, …), и помечаются как $event.origin = custom.

Свойства события

Свойства — это дополнительная информация о событии, которая позволяет более детально анализировать поведение пользователей.

Свойства бывают двух видов: системные (собираются платформой автоматически, начинаются с $) и пользовательские (ваши произвольные поля). Подробнее — в разделе Свойства.

Примеры свойств

{
"button_name": "купить_подписку",
"plan": "premium",
"price": 299,
"currency": "RUB",
"screen_name": "pricing"
}

Типы свойств

Metriox поддерживает следующие терминальные типы данных:

  • String — текстовые значения
  • Number — числовые значения (integer, float)
  • DateTime — дата и время
  • Boolean — true/false
Совет

Используйте понятные названия для кастомных событий и свойств. Например, вместо btn_1_click используйте subscription_button_click.

Примеры событий

Простое кастомное событие

{
"event_name": "bot_started",
"platform_user_id": "123456789",
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Кастомное событие со свойствами

{
"event_name": "purchase_completed",
"platform_user_id": "123456789",
"props": {
"product_id": "premium_month",
"amount": 299,
"currency": "RUB",
"payment_method": "telegram_stars"
}
}

Автоматически собранное сообщение из Telegram

Так выглядит команда /start premium от пользователя после приведения к канону. Имя события — message, а Telegram-детали лежат в системных разделах $event и $tg (только для чтения):

{
"event_name": "message",
"platform_user_id": "123456789",
"body": "/start premium",
"props": {
"$event": { "origin": "telegram", "type": "message" },
"$tg": {
"is_outgoing": false,
"chat_type": "private",
"command": "/start",
"command_params": "premium"
}
}
}

Отправка событий

События можно отправлять несколькими способами:

  1. SDK — используйте официальные SDK для JavaScript/TypeScript или C#
  2. API — отправляйте события через REST API
  3. Автоматически — Telegram-события собираются автоматически при подключении токена бота

Лучшие практики

Рекомендуется

  • Используйте snake_case для названий кастомных событий: button_click, purchase_completed
  • Добавляйте контекстные свойства: screen_name, source, category
  • Группируйте похожие события через свойства, а не через десятки уникальных имён

Не рекомендуется

  • Слишком общие названия: click, action, event
  • Отправка персональных данных в открытом виде
  • Слишком много уникальных событий (лучше использовать свойства)

Что дальше?

  • Свойства — системные и пользовательские свойства
  • Типы данных — подробнее о поддерживаемых типах данных
  • Дашборд — как визуализировать события
  • Фильтры — как фильтровать события для анализа