Перейти к содержимому
Назад в Академию

Server-side трекинг: как передать оплату, которая пришла после заявки

10.11Веб-аналитика и GTM
Содержание статьи

Центр подготовки к IELTS в Алматы рекламирует в Instagram бесплатный пробный урок. В понедельник человек кликнул по объявлению и оставил заявку на сайте, пиксель Meta записал Lead. В субботу, после пробного урока, он оплатил через Kaspi первый месяц трёхмесячного курса, 45 000 ₸, и менеджер отметил сделку в CRM как «Оплачено» (цифры в уроке условные). Страницу с формой закрыли ещё в понедельник, в CRM пикселя нет, так что об оплате Meta узнает, только если ей сообщит сервер.

Заявка и оплата - разные события

  1. Понедельник: сайт

    lead_42

    Заявка сохранена; события отправляет браузер

  2. Суббота: CRM

    payment_42

    45 000 ₸ за первый месяц

    Менеджер подтверждает поступление денег

  3. Серверная отправка

    Скрипт реагирует на статус «Оплачено»

    При повторе ID тот же: payment_42

lead_42 и payment_42 связаны в CRM, но их не склеивают как дубли.

lead_42 создан в понедельник, payment_42 - после субботней оплаты; при повторе отправки ID оплаты тот же.

Server-side и S2S: два разных маршрута

Server-side называют две разные схемы, и на первом созвоне с клиентом стоит сразу выяснить, о какой из них речь.

В первой браузер по-прежнему отправляет события, только не прямо в Google и Meta, а на ваш сервер, например в серверный контейнер GTM на поддомене data.example.com. Сервер решает, что и кому переслать. Google описывает такой контейнер как дополнение к веб-контейнеру: он забирает часть работы у страницы и, если его настроить, даёт полный контроль над тем, какие данные уходят третьим сторонам. Но в этой схеме контейнер получает только то, что прислала страница. Субботней оплаты на странице не было, значит, не будет её и на этом сервере.

Во второй событие создаёт ваш backend или CRM, браузер в этом не участвует. Сделка перешла в «Оплачено», скрипт на сервере отправляет Purchase в Meta через Conversions API и purchase в GA4 через Measurement Protocol. Это S2S, server-to-server: запрос идёт с вашего сервера на сервер платформы. Оплату после заявки передают именно так.

Пиксель при этом остаётся на сайте. Meta советует подключать Conversions API вместе с пикселем, а Google пишет, что Measurement Protocol дополняет обычный сбор и работает только при теге на сайте. Страница сообщает о том, что случилось на странице, сервер - о том, что случилось потом. В тесте недели 2 кабинет видел 11 заявок, а о троих, кто дошёл до пробного урока, знал только менеджер. Как раз такие факты и передаёт сервер.

Что сохранить в момент заявки

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

Делается это скрытыми полями формы, которые скрипт заполняет из cookies, адреса страницы и заголовков запроса. Телефон Meta тоже использует для сопоставления, но только в виде хеша SHA-256 и после нормализации: с кодом страны, без плюса, пробелов и скобок. Номер, записанный как 8 701 123 45 67, превращается в 77011234567: восьмёрка в начале - не код страны. Если ничего этого не сохранить, оплату всё равно можно отправить, но рекламной системе будет почти не за что её зацепить.

С GA4 есть оговорка. Событие из Measurement Protocol получит географию и устройство этого визита, только если в нём есть session_id и оно пришло в течение 24 часов после начала сессии. События, которые должны склеиться с браузерными, Google просит доставить в течение 48 часов и предупреждает, что более поздние могут обработаться не так, как ожидается, особенно при атрибуции конверсий. Оплата через пять дней в эти сроки не укладывается, и источник рекламного визита в GA4 ей, скорее всего, не достанется. Канал для такой оплаты надёжнее брать из CRM: UTM-метки лежат в заявке, а заявка связана со сделкой.

Описание события

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

ПолеЗаявкаОплата
ID событияlead_42, создаётся, когда сайт сохранил заявкуpayment_42, создаётся, когда сделка перешла в «Оплачено»
Время событияпонедельник, момент сохранения заявкисуббота, момент подтверждения оплаты, а не момент отправки
Где случилось (action_source)websiteother: оплата прошла переводом, не на сайте
Источник фактаответ сервера сайта, что заявка записанастатус сделки в CRM, который менеджер ставит только после того, как деньги пришли на счёт
Кто отправляетпиксель Meta и тег GA4 в браузерескрипт на сервере по смене статуса сделки
Повторыодно событие на сохранённую заявкупри тайм-ауте или временной ошибке, с тем же payment_42, до пяти попыток
Суммане передаётся45 000 ₸ за первый месяц, валюта KZT
Связь с рекламойcookies и метки из браузеразначения, которые форма сохранила в заявке lead_42

action_source Meta требует в каждом серверном событии и даёт список значений: для перевода через Kaspi там нет отдельного варианта, и подходит other. Статус от менеджера годится как источник, пока его ставят по факту поступления денег, а не по обещанию клиента. В интернет-магазине с онлайн-оплатой источником служит подтверждение платёжного сервиса, как в S2S-трекинге оплаты.

У заявки и оплаты разные ID, потому что это два факта. Связь между ними хранится в CRM: в сделке записан номер заявки. ID принадлежит факту, а не человеку. Когда тот же ученик заплатит за второй месяц, это будет новое событие с новым номером. Дайте всем событиям клиента один ID, и вторую оплату будет не отличить от повтора первой ни в вашем журнале, ни у получателя, который склеивает дубли по ID.

Время события - момент оплаты, и его передают отдельно от момента отправки, потому что у получателей есть предел давности. Meta принимает event_time не старше семи дней на момент отправки, а если в запросе есть хоть одно более старое событие, отклоняет весь запрос. GA4 разрешает сдвинуть время не больше чем на 72 часа назад; более старое событие он по умолчанию примет, но запишет его на отметку 72 часа назад. Если скрипт упал в субботу и его подняли только в среду, оплата попадёт в GA4 с неверным временем, а ещё через несколько дней её не примет и Meta. Следить за очередью неотправленных событий должен назначенный человек.

Есть и правила атрибуции. По умолчанию Meta засчитывает объявлению события в течение семи дней после клика по ссылке и одного дня после просмотра, а окно по кликам можно сократить до одного дня. Клик был в понедельник, оплата в субботу, через пять дней: в окно по умолчанию она попадает, в однодневное нет. А если бы ученик думал две недели, никакая серверная интеграция не приписала бы эту оплату объявлению. И деталь, на которой спотыкаются при сверке: Ads Manager показывает конверсию в дне показа объявления, то есть понедельником, а в CRM оплата стоит субботой.

Повтор не должен удваивать выручку

Допустим, в субботу скрипт отправил оплату, не дождался ответа и отправил её ещё раз, уже с новым ID. В кабинете окажутся две покупки на 90 000 ₸. Посчитаем на месяце: на кампанию потратили 60 000 ₸, первых оплат было три, по 45 000 ₸ каждая. Настоящий ROAS 135 000 / 60 000 = 2,25. Один такой дубль, и кабинет покажет 180 000 ₸ и ROAS 3, а вы предложите клиенту поднять бюджет по деньгам, которых нет.

Повтор поэтому всегда уходит с тем же payment_42: Meta убирает повторные серверные события с одинаковыми event_name и event_id. Как устроить очередь, повторы и разбор ошибок, подробно разобрано в S2S-трекинге оплаты.

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

Что проверить до запуска

Ответ «200 OK» от получателя значит только, что запрос принят. Measurement Protocol GA4 не возвращает ошибку даже на неправильно собранное событие, и новые события сначала гоняют через его сервер проверки /debug/mp/collect. В Meta отдельные события видно только в «Тестировании событий»: там же отмечено, какие из них отброшены как дубли. Общие счётчики Events Manager дубли не убирают, а сработала ли склейка на живом трафике, показывают вкладка «Дедупликация событий» и Ads Manager.

Возьмите одну тестовую сделку и проведите через неё пять ситуаций:

  1. Обычная оплата. Уходит одно событие с правильной суммой, валютой и временем. Тестовые события отправляйте с test_event_code из «Тестирования событий»: Meta их не выбрасывает, поэтому сумму ставьте маленькую, а перед запуском код уберите.
  2. Менеджер ошибся, вернул сделку из «Оплачено» назад и снова перевёл. Событие всё равно одно.
  3. Сервер получателя недоступен. Скрипт повторяет с тем же ID, а после последней попытки событие оказывается в очереди разбора.
  4. Возврат. Повторный Purchase не уходит. Как отражать возвраты, решите заранее вместе с бухгалтерией: в GA4 для этого есть событие refund.
  5. Человек отказался от рекламных cookies. Серверный маршрут выполняет его выбор так же, как браузер.

Пятый пункт легко пропустить: баннер cookies стоит на сайте, а скрипт оплат живёт в CRM и о баннере ничего не знает. Выбор человека сохраняют вместе с заявкой и смотрят на него перед каждой отправкой. Где ещё здесь ломается, разобрано в статье про согласия и серверный GTM, а что вообще можно передавать, в уроке про privacy и cookieless.

Упражнение: описание события для своего проекта

Возьмите тестовый сайт или проект клиента:

Выполнено 0 из 4

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

Теперь вопрос, который вам зададут. Через месяц клиент видит оплаты в Ads Manager и спрашивает: «Теперь реклама оптимизируется на оплаты?» Что вы ответите?

Нет. Событие оптимизации выбирают в группе объявлений, и появление Purchase в наборе данных его не меняет. Даже если переключить группу на оплаты, при трёх оплатах в месяц она застрянет в обучении. Meta считает группу ограниченной в обучении, если та вряд ли наберёт около 50 событий оптимизации за неделю, и сама советует в таком случае выбрать событие, которое случается чаще. Клиент получил другое: отчёт показывает, какие объявления привели к оплатам в пределах окна атрибуции, и ROAS считается по деньгам, а не по заявкам. К оптимизации на оплаты можно возвращаться, когда их станут десятки в неделю.

Видео: общая схема server-side tracking

Server-side tracking explained in 100 seconds

Видео на английском и про первую схему, серверный GTM. Как он устроен, показано на примере серверного GTM.

Нужна помощь с аналитикой вашего проекта?