К содержанию
ActionPulse

Диагностика отправки

Инструменты для проверки отправки событий — сетевая панель браузера, вопросы к трекеру из консоли, безопасное логирование на бэкенде и разбор трёх состояний доставки.

Кому
Разработчику, у которого отправка ведёт себя не так
Проверено
На этой странице

Эта страница — про инструменты: что открыть, что спросить, что записать в журнал. Если вы уже знаете симптом и ищете причину, начинайте с решения проблем — там дерево «симптом → причина → проверка → исправление».

Порядок диагностики всегда один: сначала убедиться, что запрос вообще ушёл, потом прочитать ответ, и только потом искать событие в отчётах.

Сетевая панель браузера

Откройте инструменты разработчика, вкладку «Сеть», и включите сохранение журнала при переходах (в Chrome — «Preserve log», в Firefox — «Постоянные журналы»). Без этого запросы, которые уходят при закрытии страницы, исчезнут из списка вместе со страницей.

Смотреть нужно три разных запроса:

Фильтр Что это Ожидаемый код
tracker.js или t.js сам файл трекера 200
cfg запрос настроек сбора 200 или 304
track отправка событий 202

Если нет первого — не загрузился скрипт. Если есть первый, но нет третьего — трекер не инициализировался или сбор ещё не разрешён. Запрос настроек уходит только после разрешения сбора, поэтому его отсутствие — тот же признак.

Что смотреть в запросе

Где Что проверить
Адрес путь /v1/track и правильный хост приёма
Метод POST; отдельная строка OPTIONS перед ним — это предпроверка
Authorization Bearer и токен, начинающийся на pp_bt_
Content-Type text/plain — это норма, а не ошибка
Origin ровно тот адрес, который вы указали при выпуске токена
X-PP-Tracker версия трекера; расхождение с ожидаемой означает кэш
Тело объект с массивом batch; имена событий и event_id видны здесь

Content-Type: text/plain трекер ставит намеренно, чтобы не плодить лишние предпроверки. Приём не проверяет этот заголовок, поэтому «неправильный тип содержимого» никогда не бывает причиной отказа.

Что смотреть в ответе

Где Что означает
Код 202 батч принят целиком или частично — читайте тело
Тело {accepted, n, rejected} rejected с непустым списком = часть событий отклонена
Код 4xx или 5xx тело {"error":{"code","message","details"}}
Заголовок Retry-After приходит при 429 rate_limited, значение в секундах
Заголовок Deprecation: true ключ передан устаревшим способом — через адрес запроса

Заголовок Deprecation появляется, только если ключ уехал в параметре адреса. Это работает лишь для совместимых ключей pp_wk_…; новым токенам такой способ передачи запрещён.

Вопросы к трекеру из консоли

В режиме подключения скриптом трекер доступен как глобальный объект pp:

typeof window.pp;      // 'object' — скрипт загрузился и выполнился
pp.trackerVersion;     // версия загруженного трекера
pp.getConsent();       // 'pending' | 'granted' | 'denied' | 'revoked'
pp.getSessionId();     // строка, либо undefined пока сбор не разрешён

Что означают ответы:

Ответ Вывод
typeof window.pp === 'undefined' скрипт не загрузился или не выполнился
pp.getConsent() вернул 'pending' сбор выключен, запросов не будет — это правильно
pp.getConsent() вернул 'denied' или 'revoked' сбор отключён и очередь очищена
pp.getSessionId() вернул undefined сбор ещё не разрешён
pp.trackerVersion не тот, что вы ждёте отдаётся закэшированная версия файла

Дальше — принудительная отправка. Она даёт гарантированно наблюдаемый запрос в сетевой панели, не дожидаясь таймера:

pp.track('debug_probe', { source: 'devtools' });
await pp.flush();

Имя события должно проходить маску ^[a-z0-9_.]{1,128}$ и быть разрешено для браузерного токена, иначе вы увидите 202 с отказом credential_event_forbidden — что само по себе полезный результат: значит транспорт, ключ и origin в порядке, а дело в правах на имя события.

Состояние очереди видно в хранилище браузера:

JSON.parse(localStorage.getItem('pp_buffer_v2') ?? '[]').length;
localStorage.getItem('pp_anon_id');
localStorage.getItem('pp_session');

Непустой буфер, который не уменьшается, означает, что отправка не удаётся и события ждут следующей попытки. Пустой буфер при отсутствии запросов означает, что события вообще не создавались.

При подключении из бандла глобального pp нет — те же вызовы делаются на вашем экземпляре клиента.

Проверки без кабинета

Обе проверки ниже не требуют авторизации в кабинете и делаются из терминала.

Отвечает ли приём. Проверка живости не требует ключа:

curl -i https://YOUR_ACTIONPULSE_HOST/healthz

Ответ 200 с телом {"status":"ok"} означает, что адрес правильный и сервис принимает запросы.

Какие виды сбора включены для ключа. Публичный запрос настроек принимает только безопасный префикс ключа — 8 символов после pp_bt_, без секретной части:

# Ровно 8 символов между вторым и третьим подчёркиванием токена pp_bt_…
PREFIX=<8-symbol-key-prefix>

curl -s "https://YOUR_ACTIONPULSE_HOST/v1/cfg?key=$PREFIX" | python3 -m json.tool

В ответе видно, включены ли автосбор кликов, разделов, прокрутки и форм, записи сессий и сбор клиентских ошибок. Это отвечает на вопрос «почему автосбор не работает, хотя события идут».

Что логировать на бэкенде

Отправка с сервера диагностируется только по вашим журналам — сетевой панели здесь нет. Минимальный набор, которого достаточно почти всегда:

Писать Зачем
event_id и имя события связать свою запись с событием в ActionPulse
Код ответа HTTP отличить отказ от ошибки транспорта
error.code из тела отличить rate_limited от quota_exceeded
Каждый элемент rejected: индекс и код найти, какое именно событие не прошло
Номер попытки увидеть, что повторы работают и не бесконечны
Длительность запроса заметить таймауты до того, как они станут отказами
const response = await fetch('https://YOUR_ACTIONPULSE_HOST/v1/track', requestInit);

if (response.status !== 202) {
  const body = await response.json().catch(() => ({}));
  logger.warn('actionpulse rejected request', {
    status: response.status,
    code: body?.error?.code,
    retryAfter: response.headers.get('retry-after'),
    eventIds,
  });
  return;
}

const result = await response.json();
for (const item of result.rejected) {
  logger.warn('actionpulse rejected event', {
    eventId: eventIds[item.i],
    code: item.code,
  });
}

Полезные счётчики, если у вас есть метрики: отправленные события, принятые, отклонённые по каждому коду, попытки повторов, текущая длина своей очереди. Рост отклонённых по одному коду сразу показывает, какая именно разметка сломалась после релиза.

Три состояния: не отправили, отказали, не видно

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

Состояние Признак Где проверять
Не отправили запроса на /v1/track нет вовсе сетевая панель, свой журнал попыток
Отправили и отказали запрос есть, код не 202 либо rejected непустой код ответа, error.code, rejected[].code
Приняли, но не видно код 202 и accepted больше нуля период отчёта, фильтры, проект, время события

Не отправили

Проверяйте в таком порядке: разрешён ли сбор (pp.getConsent()), существует ли трекер (typeof window.pp), доходит ли выполнение до вашего вызова, подставился ли токен в разметку. На бэкенде — считает ли ваш код попытки отправки вообще.

Отправили и отказали

Читайте error.code для отказа всего запроса и rejected[].code для отказов по элементам. Расшифровка всех кодов — в решении проблем. Обратите внимание, что 202 с accepted: 0 — это тоже отказ, просто по элементам.

Приняли, но не видно

Самое коварное состояние: транспорт исправен, а событий в отчёте нет. Проверяйте по этому списку:

  1. Тот ли проект. Проект определяется криптографически по ключу и не может быть переопределён заголовком. Ключ от другого проекта отправит события в другой проект и вернёт при этом честный 202.
  2. Тот ли период. Если time было вне окна ±48 ч, приём заменил его временем получения — событие лежит «сейчас», а вы ищете его в прошлом. Или наоборот. Сравните event_time и server_time.
  3. Не прошло ли достаточно времени. Между ответом и появлением события в отчётах проходит несколько секунд — накопленное пишется пакетами.
  4. Не отфильтровано ли. Активный сегмент, фильтр по свойству или выбранный тип устройства могут исключить именно ваше событие.
  5. То ли имя. Order_Paid и order_paid — разные строки, и первое имя приём вообще не примет.
  6. Не пустые ли свойства. Значения с признаками секрета или персональных данных заменяются на [redacted] на сервере. Событие есть, свойство пустое.

Подробнее про время, повторы и дубли — в доставке и повторах. Про границы и квоты — в лимитах.

Что собрать перед обращением в поддержку

  • код ответа и тело ответа на /v1/trackбез значения ключа;
  • префикс ключа: символы до второго подчёркивания;
  • event_id и имя события, которое не нашлось;
  • время попытки в UTC;
  • origin страницы, если отправка из браузера.