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

Спецификация dataLayer: как написать разработчику ТЗ на события

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

Банк принимает на сайте заявки на бизнес-счёт (банк, заявки и номера в уроке условные). Маркетолог попросил разработчиков «поставить конверсию на форму». Фронтенд отправил событие 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 - номер факта, у каждого этапа свой.

Заявка L42 и три её события: «Заявка принята» с event_id E1, «Телефон подтверждён» с E2, «Продукт открыт» с E3. Повтор того же факта сохраняет его event_id.
Заявка L42 и три её события: «Заявка принята» с event_id E1, «Телефон подтверждён» с E2, «Продукт открыт» с E3. Повтор того же факта сохраняет его 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

Вот первое событие банка. Сайт отправляет его, когда сервер ответил, что заявка сохранена. Имена полей придумала команда, это не готовый формат рекламной платформы.

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "application_accepted",
schema_version: "1.0",
event_id: "E1",
lead_id: "L42",
product_id: "business_account",
occurred_at: "2026-09-08T10:00:00+05:00"
});
  • 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 должны быть четыре вещи.

  1. Момент покупки. Платёжная система подтвердила оплату. Не открытие страницы «Спасибо» и не нажатие «Оплатить»: на «Спасибо» попадают и после отказа банка, и из истории браузера.
  2. Параметры. value - сумма товаров, здесь 25 000. currency - KZT, Google просит передавать её вместе с value. items - что купили (схема ecommerce в GA4).
  3. Номер заказа. transaction_id - номер из системы школы, свой у каждого заказа, например course_order_42. GA4 считает покупки с одинаковым номером дублями, поэтому пустая строка или один номер на все заказы превратят разные покупки в одну.
  4. Повтор. Если отправка сорвалась и уходит снова, номер тот же, и покупка посчитается один раз. Возврат передают отдельным событием 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_startgenerate_leadwhatsapp_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 = KZTlink_url, адрес ссылки
ПовторВ новом сеансе придёт сноваДвойной клик даёт одну заявку и одно событиеКаждый клик - отдельное событие
ПолучателиGA4GA4 (generate_lead), пиксель Meta (Lead)GA4 (whatsapp_click)
Где проверитьDebugViewTag Assistant, DebugView, «Тестирование событий» в Events ManagerDebugView
Кто отвечаетВы: включить улучшенную статистикуРазработчик - push, вы - тег и проверкаВы: триггер и тег в GTM

Карточка form_start не для галочки. GA4 собирает это событие сам (какие события даёт улучшенная статистика), и разработчику по нему ничего делать не надо. Но форму во встроенном виджете (iframe) GA4 со страницы не видит, и это тоже стоит записать в карточку. А если не написать, что событие уже собирается, кто-нибудь добавит в GTM свой тег form_start, и начатые формы в отчёте задвоятся.

Мини-тест: Веб-аналитика и GTM

Закрепление модуля

Проверьте, как применить идеи модуля в рабочей ситуации. Сначала ответьте самостоятельно, затем прочитайте разбор.

3 вопроса. После проверки - объяснение каждого варианта и ссылки на уроки. В вопросах с несколькими ответами нужен полный набор: частичный ответ не засчитывается. Ограничения по времени нет.

Прогресс сохраняется только в этом браузере. Очистка данных сайта удалит его; на другое устройство он не переносится.

Нужна помощь с аналитикой вашего проекта? Обсудить задачу с Goodlabs →