Банк принимает на сайте заявки на бизнес-счёт (банк, заявки и номера в уроке условные). Маркетолог попросил разработчиков «поставить конверсию на форму». Фронтенд отправил событие conversion по нажатию «Отправить», бэкенд отправил conversion, когда заявка сохранилась, а интеграция с CRM - когда счёт открыли. В event_id все трое положили номер заявки. Через месяц в GA4 три события сложились в одно число, а Meta, которая склеивает браузерное и серверное событие с одинаковыми именем и event_id, часть из них выбросила как повторы. Сколько счетов принесла реклама, не видно ни там, ни там.
Каждый понял задачу по-своему и по-своему был прав. Чтобы так не вышло, событие заказывают не одной строкой, а спецификацией: для каждого события записано, что оно означает, когда отправляется, с какими параметрами, куда уходит и где его увидеть. Разработчик пишет код по этому документу, вы принимаете работу по нему же, и спор «кто прав» заканчивается, как только документ открыли.
Что такое dataLayer и при чём тут спецификация
dataLayer - это массив на странице, куда код сайта складывает сообщения, а GTM их читает (руководство Google по dataLayer). Сообщение с ключом event запускает триггеры, остальные ключи становятся значениями для переменных. Имена чувствительны к регистру: переменная form_name не прочитает ключ Form_Name, поэтому в спецификации их пишут ровно так, как в коде.
Спецификация шире dataLayer. dataLayer только доставляет в GTM то, что случилось в браузере, а в спецификации есть и события, которых браузер не увидит. Счёт банк открывает позже, когда страница с формой давно закрыта, и об этом сообщает сервер. Такие события доходят до GA4 и рекламных кабинетов через серверный трекинг, а в спецификации у них те же поля, что и у браузерных.
Сначала факты, потом имена
Прежде чем придумывать названия событий, договоритесь, какие факты вы считаете и что их подтверждает. У банка их три:
- заявка принята: сервер сохранил её и выдал номер;
- телефон подтверждён: человек ввёл код из SMS, и сервер этот код проверил;
- продукт открыт: в системе банка бизнес-счёт по заявке получил статус «открыт».
Нажатие кнопки, введённый, но не проверенный код и экран «Спасибо» фактами не считаются. Кнопку нажимают и с пустым полем, код бывает неверным, а экран «Спасибо» открывают повторно из истории браузера. Если событие висит на одном из них, отчёт считает попытки, а не результат. Так считал тег, который прошлый подрядчик онлайн-школы повесил на кнопку в Google Tag Manager.
Два идентификатора: заявка и событие
Чтобы три факта одной заявки можно было связать, но не путать друг с другом, нужны два номера. lead_id - номер заявки, он одинаковый на всех её этапах. event_id - номер факта, у каждого этапа свой.

Если отправка E2 сорвалась из-за сети и сервер повторил её, повтор идёт с тем же E2: факт-то тот же. Если тот же человек через месяц подаёт вторую заявку, у неё новый lead_id и новые event_id. Номер клиента, номер заявки, номер заказа и номер события - четыре разных поля, и склеивать их в одно нельзя.
Вернёмся к началу урока. Там все три этапа ушли под именем conversion с номером заявки в event_id. GA4 сложил их в одно число, а для Meta одинаковые имя и event_id означают копию, поэтому часть событий она выбросила. Исправление простое: L42 остаётся общим lead_id, этапы получают свои имена и номера E1, E2 и E3.
Как именно получатель узнаёт повтор, у каждого своё. GA4 убирает дубли purchase с одинаковым transaction_id, причём только в веб-потоке (как GA4 убирает дубли покупок). Meta склеивает браузерное и серверное событие, когда у них совпадают имя и event_id, а второе пришло в течение 48 часов после первого (дедупликация в Conversions API). Настраивают эту склейку вместе с Conversions API. Поэтому в спецификации для каждого получателя записано, по какому полю он отличает повтор от нового события.
Как выглядит событие в dataLayer
Вот первое событие банка. Сайт отправляет его, когда сервер ответил, что заявка сохранена. Имена полей придумала команда, это не готовый формат рекламной платформы.
event- имя, которого ждёт триггер в GTM.schema_version- версия описания события. Когда смысл какого-то поля меняется, версию поднимают, и в данных видно, с какого дня считают по-новому.event_idиlead_id- номер факта и номер заявки. E1 и L42 тестовые. На рабочем сайте номера выдаёт сервер, а код страницы берёт их из ответа: константа в коде дала бы всем заявкам один и тот же номер.product_id- что оформляют, здесь бизнес-счёт.occurred_at- когда факт произошёл, с часовым поясом. Время доставки хранят отдельно: при повторе после сбоя эти два времени разойдутся.
Телефона, ИИН и кода из SMS в событии нет, и почему их там быть не должно, сказано ниже.
Шаблон карточки события
Каждое событие в спецификации описывается карточкой с одними и теми же полями. Вот карточка для application_accepted, у двух других событий банка поля те же.
| Поле | application_accepted |
|---|---|
| Что означает | Банк сохранил заявку на бизнес-счёт и выдал ей номер |
| Когда срабатывает | Сервер ответил, что заявка сохранена |
| Когда не срабатывает | Ошибка в форме, отказ сервера, повторное открытие страницы «Спасибо» |
| Параметры | schema_version, event_id, lead_id, product_id, occurred_at |
| Повтор | Повтор того же факта уходит с тем же event_id, новая заявка получает новые lead_id и event_id |
| Получатели | Для каждого: имя события, набор полей и поле, по которому он отсеивает повторы |
| Где проверить | Предварительный просмотр GTM, DebugView, заявка с тем же lead_id в CRM |
| Кто отвечает | Смысл - продукт, код - разработчик, проверка - аналитик |
Самая полезная строка - «Когда не срабатывает». Без неё у разработчика нет причины отказываться от события на кнопке: так быстрее, и в предварительном просмотре всё сработает. А строка «Где проверить» говорит, когда работа закончена: пока событие не найдено там, задача не сдана.
Строки про value в карточке нет, и это решение, а не пропуск: у заявки на счёт нет суммы. Если команда захочет передавать прогноз дохода от клиента, у прогноза должна быть версия, а в отчёте его нельзя называть выручкой. Ставить value = 1, чтобы поле не пустовало, нельзя по той же причине, что и в GA4: в отчётах появится цена, которой нет.
Покупка: что спросит разработчик
Если клиент продаёт онлайн, разработчик первым делом спросит, когда отправлять purchase. Возьмём онлайн-школу из урока про GA4: курс за 25 000 ₸ оплачивают на сайте. В карточке purchase должны быть четыре вещи.
- Момент покупки. Платёжная система подтвердила оплату. Не открытие страницы «Спасибо» и не нажатие «Оплатить»: на «Спасибо» попадают и после отказа банка, и из истории браузера.
- Параметры.
value- сумма товаров, здесь 25 000.currency-KZT, Google просит передавать её вместе сvalue.items- что купили (схема ecommerce в GA4). - Номер заказа.
transaction_id- номер из системы школы, свой у каждого заказа, напримерcourse_order_42. GA4 считает покупки с одинаковым номером дублями, поэтому пустая строка или один номер на все заказы превратят разные покупки в одну. - Повтор. Если отправка сорвалась и уходит снова, номер тот же, и покупка посчитается один раз. Возврат передают отдельным событием
refundс тем жеtransaction_id.
С этими четырьмя пунктами тот, кто пишет код, и тот, кто его проверяет, работают по одному договору, а риск двойного учёта виден ещё в ТЗ, а не в отчёте через месяц. Скриншот отчёта, который хочет увидеть клиент, их не заменит: на нём результат, но не написано, откуда берутся цифры и когда срабатывает событие.
Чего в dataLayer быть не должно
Имя, телефон, email, ИИН, номер счёта и код из SMS в браузерный слой аналитики не кладут. Google запрещает передавать в Analytics данные, по которым можно узнать человека, в том числе в адресе страницы и его параметрах (правила Google Analytics о персональных данных). GTM отправит любое поле, которое подставят в тег, так что надёжнее, когда такого поля в dataLayer просто нет.
У банка список длиннее. Meta запрещает передавать через свои инструменты финансовые сведения о человеке: номера счетов и карт, одноразовые коды, кредитный лимит, остаток на счёте, одобрение или отказ по кредиту. Запрет касается и параметров URL, и названий собственных событий (о запрещённой информации). Какие события и поля банка уходят в рекламные кабинеты, решают вместе с юристом банка до разработки, и это решение записывают в строку «Получатели».
Ключ consent в обычном push режим согласия не включает: его настраивают командами gtag('consent', ...) или шаблоном платформы управления согласием в GTM (руководство по режиму согласия). В спецификации записывают, какие получатели ждут согласия на cookies и кто это настраивает.
Прогон одной заявки
Когда разработчик говорит «готово», пройдите заявку L42 от начала до конца и найдите её на каждом этапе из спецификации: событие в предварительном просмотре GTM, запись в CRM, события E1, E2 и E3 у получателей. Потом сломайте её четырьмя способами:
- отправьте форму с ошибкой:
application_acceptedне должно появиться; - обновите страницу после отправки: нового события быть не должно;
- попросите разработчика повторить отправку подтверждения телефона: повтор должен прийти с тем же E2;
- подайте вторую заявку: у неё должны быть новые
lead_idиevent_id.
Имя события, параметры и отсутствие дублей смотрят вместе: событие с правильным именем и пустым lead_id бесполезно так же, как дубль. Если позже смысл поля меняется, поднимите schema_version и запишите дату перехода. Иначе старый отчёт продолжит работать, только считать начнёт уже другое, и заметят это нескоро.
Упражнение: ТЗ на три события своего сайта
Возьмите тестовый сайт из недели 1 трека «Старт», где уже есть форма, GA4 и пиксель Meta.
Шаг трека засчитан, когда у каждого из трёх событий есть условие срабатывания, параметры и место проверки. Так могла бы выглядеть страница онлайн-школы из уроков про GTM и GA4, если добавить на её сайт кнопку WhatsApp:
| Поле | form_start | generate_lead | whatsapp_click |
|---|---|---|---|
| Что означает | Человек начал заполнять форму | Сервер принял заявку на курс | Человек нажал кнопку WhatsApp. Это клик, а не заявка |
| Когда срабатывает | GA4 отправляет сам при первом взаимодействии с формой | Сайт отправляет lead_submit_success после ответа сервера, тег GTM превращает его в generate_lead | Тег GTM по клику на ссылку WhatsApp |
| Когда не срабатывает | Повторное взаимодействие в том же сеансе | Ошибка в форме, обновление страницы | Человек написал в WhatsApp, не заходя на сайт |
| Параметры | form_id, form_name, form_destination GA4 берёт из HTML формы | form_name = course_signup; value = 5000: курс 25 000 ₸, оплачивает каждая пятая заявка, как в настройке GA4; currency = KZT | link_url, адрес ссылки |
| Повтор | В новом сеансе придёт снова | Двойной клик даёт одну заявку и одно событие | Каждый клик - отдельное событие |
| Получатели | GA4 | GA4 (generate_lead), пиксель Meta (Lead) | GA4 (whatsapp_click) |
| Где проверить | DebugView | Tag Assistant, DebugView, «Тестирование событий» в Events Manager | DebugView |
| Кто отвечает | Вы: включить улучшенную статистику | Разработчик - push, вы - тег и проверка | Вы: триггер и тег в GTM |
Карточка form_start не для галочки. GA4 собирает это событие сам (какие события даёт улучшенная статистика), и разработчику по нему ничего делать не надо. Но форму во встроенном виджете (iframe) GA4 со страницы не видит, и это тоже стоит записать в карточку. А если не написать, что событие уже собирается, кто-нибудь добавит в GTM свой тег form_start, и начатые формы в отчёте задвоятся.
Мини-тест: Веб-аналитика и GTM
Закрепление модуля
Проверьте, как применить идеи модуля в рабочей ситуации. Сначала ответьте самостоятельно, затем прочитайте разбор.
3 вопроса. После проверки - объяснение каждого варианта и ссылки на уроки. В вопросах с несколькими ответами нужен полный набор: частичный ответ не засчитывается. Ограничения по времени нет.
Прогресс сохраняется только в этом браузере. Очистка данных сайта удалит его; на другое устройство он не переносится.