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

Server-side GTM: как устроен серверный контейнер и как его настроить

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

Онлайн-школа в Алматы продаёт курс аналитики за 25 000 ₸, тот самый, для которого в уроке про GA4 настраивали generate_lead и purchase (цифры в уроке условные). Владелец хочет передавать оплаты в Meta и Google Ads с сервера, и разработчик спрашивает, что именно поднимать и куда пойдут данные. Начинать стоит не с выбора хостинга, а с того, как один запрос проходит через серверный контейнер. Проследим оплату заказа course_order_42, а потом соберём всю цепочку для GA4.

Путь запроса через серверный контейнер

  1. HTTP-запрос

    Приходит на адрес сервера

  2. Клиент

    Распознаёт формат и забирает запрос

    Создаёт данные события

  3. Триггер

    Решает, каким тегам срабатывать

  4. Преобразование

    Меняет данные для выбранных тегов

  5. Тег и получатель

    Тег переводит данные в формат получателя и отправляет запрос

Преобразование меняет данные, которые видит тег, а входящий запрос не трогает.

Запрос распознаёт клиент, из данных события триггер выбирает теги, преобразование меняет их данные, а тег отправляет запрос получателю.

Как запрос проходит через контейнер

Серверный контейнер GTM работает не в браузере посетителя, а на сервере со своим адресом. Сайт отправляет на этот адрес HTTP-запросы, а внутри контейнера с ними работают клиенты, триггеры и теги.

Клиент (client) переводит запрос с протокола отправителя на язык контейнера. Каждый входящий запрос по очереди получают все клиенты, начиная с того, у кого приоритет выше. Первый, кто узнал формат, забирает запрос себе, и остальные клиенты его уже не видят. Не узнал - пропускает дальше (как работают клиенты). В новом контейнере уже есть клиент GA4, который понимает запросы тега Google.

Забрав запрос, клиент собирает из него одно или несколько событий. Наша оплата превращается в событие purchase, а в его данных (event data) лежат value 25000, currency KZT, transaction_id course_order_42 и служебные поля вроде идентификатора посетителя. Триггеры смотрят на каждое событие и решают, каким тегам срабатывать. Тег берёт данные события, переводит их в формат своего получателя и отправляет исходящий запрос: тег GA4 - в Google Analytics, тег Conversions API - в Meta.

Теперь о том, чего контейнер не видит. Страницы у него нет, а значит, нет DOM, кликов, прокрутки и dataLayer сайта. Есть только то, что пришло в запросе: адрес, параметры, заголовки и cookies своего домена. Если сайт отправляет purchase при открытии страницы «Спасибо», а не после подтверждения оплаты, сервер разошлёт эту ошибку всем получателям. Исправляют её там, где рождается событие: на сайте или в веб-контейнере GTM.

Веб-GTM - только один из отправителей

Привычная схема выглядит так: на сайте стоит веб-контейнер, его тег Google отправляет события на сервер, а серверный контейнер раздаёт их получателям. Но веб-контейнер для этого не обязателен. Отправлять можно прямо из gtag.js, а из мобильного приложения или с бэкенда - запросами в формате Measurement Protocol, которые забирает клиент Measurement Protocol (способы отправки данных).

Школе это пригодится. Подтверждение оплаты приходит от платёжной системы на бэкенд, а человек может так и не вернуться на страницу «Спасибо». Если бэкенд сам отправит purchase на сервер, оплата дойдёт до получателей без участия браузера: так работает серверный трекинг S2S, когда вкладка давно закрыта, а платёж прошёл.

Произвольный JSON из CRM событием не станет, пока его не заберёт клиент, который понимает именно этот формат: встроенный, из галереи шаблонов или написанный под вашу систему. Без такого клиента ни один тег не сработает.

Где будет работать сервер

Серверный контейнер создают в GTM так же, как веб-контейнер, только в поле «Целевая платформа» выбирают «Сервер». Затем GTM предлагает настроить сервер тегов. Вариантов два, а ручной можно отдать провайдеру (обзор настройки):

  • «Добавить сервер тегов автоматически». GTM создаёт проект в Google Cloud и сервер на Cloud Run, для этого нужен платёжный аккаунт Google Cloud.
  • «Добавить сервер тегов вручную». Сервер тегов - это Docker-образ, его запускают на своей инфраструктуре. GTM показывает строку конфигурации контейнера (Container Config), её передают серверу (ручная настройка). Так же подключаются провайдеры вроде Stape: строку вставляют в их панели, а сервер они поднимают и обслуживают сами. Владелец среды, где работает сервер, может иметь доступ к вашим данным, поэтому условия провайдера читают до того, как пойдут данные заказчика.

Сколько экземпляров держать, что делать с журналами запросов и во что обходится server-side GTM, решают при выборе инфраструктуры sGTM.

Когда сервер работает, GTM должен знать его адрес. При ручной настройке адрес добавляют в «Администрирование» → «Настройки контейнера» кнопкой «Добавить URL» в поле адресов серверного контейнера (Server container URL). Связь проверяют сразу: открывается предварительный просмотр, а адрес сервера с /healthy на конце отвечает ok (руководство по Cloud Run).

Адрес сервера: путь, поддомен или адрес провайдера

Новый сервер получает адрес на домене провайдера, у Cloud Run это run.app. Данные по такому адресу доходят, но работает он в стороннем контексте. Для сайта https://www.example.com у Google три варианта (свой домен для сервера):

ВариантПример адресаЧто настроитьCookies от сервера
Путь на основном доменеhttps://www.example.com/metricsCDN или балансировщик, который пересылает запросы с этого пути на сервер; иногда DNSДа
Поддоменhttps://metrics.example.comЗапись в DNSДа
Адрес провайдераhttps://metrics.run.appНичего, работает сразуНет, только cookies из JavaScript

Разница в cookies. На пути и на поддомене сервер может ставить свои cookies прямо в ответе на запрос, в том числе с флагом HttpOnly, которые скрипты на странице не видят, а на адресе провайдера остаются только cookies из JavaScript. Путь даёт тот же origin, что у сайта, и именно этот вариант Google называет лучшей практикой, но для него нужен CDN или балансировщик. Поддомен - другой origin того же сайта, зато хватает записи в DNS.

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

Настройка для GA4 по шагам

Порядок для тестового сайта или первого заказчика:

  1. Создайте серверный контейнер и сервер, как описано выше, и убедитесь, что адрес сервера есть в настройках контейнера.
  2. Привяжите к серверу поддомен или путь сайта и замените адрес в настройках контейнера на новый. На тестовом сайте этот шаг можно отложить.
  3. В серверном контейнере откройте «Клиенты» и посмотрите клиент GA4. Если других клиентов, претендующих на запросы GA4, нет, приоритет можно оставить 0. Пока сервер живёт на адресе провайдера, в настройке cookies клиента оставьте JavaScript Managed: до смены домена работает только этот вариант (настройка потока GA4).
  4. Создайте тег типа Google Analytics: GA4. Поля оставьте по умолчанию, идентификатор потока и параметры он возьмёт из данных события. Триггер нужен типа Custom с условием Some Events, в котором встроенная переменная Client Name равна имени клиента, например GA4. Именно имени, а не типу клиента, который называется Google Analytics: GA4.
  5. В веб-контейнере создайте переменную типа «Тег Google: Настройки конфигурации» с параметром server_container_url и адресом сервера в значении. Выберите её в разделе «Настройки конфигурации» тега Google и поставьте триггер «Инициализация - Все страницы». Если на сайте gtag.js без GTM, адрес передают в команде config:
gtag('config', 'G-XXXXXXXXXX', {
server_container_url: 'https://metrics.example.com'
});
  1. Откройте предварительный просмотр серверного контейнера, а в том же браузере - сайт. Слева появятся запросы collect?v=2 и события под ними. На вкладке «Запрос» видно, какой клиент забрал запрос, что пришло и какой исходящий запрос ушёл в GA4, вместе с кодом ответа (предварительный просмотр и отладка). Запросы из другого браузера в просмотр не попадают (проверка настройки).
  2. Опубликуйте серверный контейнер, затем веб-контейнер.

На проекте заказчика рабочий тег сразу не переключают. Для серверных данных заводят отдельный ресурс GA4 и какое-то время собирают данные в оба ресурса, пока цифры не сойдутся (параллельный сбор). Допустим, за неделю старый ресурс показал 15 покупок, а новый 14. По одному заказу причину не назвать. Выгрузите из CRM номера заказов за неделю, найдите тот, которого нет в новом ресурсе, и повторите такую покупку в предварительном просмотре: тот же способ оплаты, то же устройство. Переключать рабочий тег можно, когда расхождение объяснено.

Преобразования: Allow, Augment и Exclude

Между данными события и тегом можно поставить преобразование (transformation). Оно запускается после того, как клиент собрал данные события, и меняет то, что увидят выбранные теги. Входящий запрос оно не трогает. Типов три (преобразования):

  • Allow («Использовать параметры» в русской документации) оставляет тегам только перечисленные параметры, а остальные отбрасывает, включая те, без которых не работают теги Google.
  • Augment («Дополнить данные, относящиеся к событию») меняет значение параметра или добавляет новый.
  • Exclude («Исключение параметров») убирает указанные параметры.

По умолчанию они применяются в порядке Allow, Augment, Exclude. Порядок меняют приоритетом: чем больше число у преобразования, тем раньше оно сработает. У каждого есть «Затронутые теги» и «Условия совпадения», и без настройки преобразование действует на все теги и всегда.

Из-за этого умолчания слишком узкий Allow ломает поток данных незаметно. Допустим, для тега, который пишет события в BigQuery, разрешили event_name, page_path и client_id, а затронутые теги выбрать забыли. Allow отрежет поля у всех тегов, и те, кому нужно больше, включая GA4, перестанут срабатывать: преобразование, которое убрало нужные тегу поля, может его остановить. На сайте при этом ошибок нет, просто в отчётах становится меньше событий. Найти такую поломку можно, только если смотреть, какие данные получает каждый тег.

Теперь пример, ради которого преобразования и ставят. Админка сайта добавляет к заказу пометку о скидке, и разработчик школы передаёт её в purchase параметром internal_note: «скидка сотруднику 30%». Ни рекламным кабинетам, ни GA4 эта пометка не нужна. А некоторые серверные теги отправляют получателю дополнительные параметры без всякой настройки, и лишнее убирают как раз преобразованием (отправка данных на сервер). Делаем Exclude с internal_note и в затронутых тегах выбираем рекламные теги и GA4. Приёмка на примере тега Meta выглядит так:

  1. В предварительном просмотре выберите событие purchase и откройте вкладку «Теги».
  2. Нажмите на тег Meta. В сведениях о теге видно, какие преобразования сработали и в каком порядке.
  3. В блоке «Данные события» internal_note быть не должно. С отметкой «Показать исходные данные» он появится среди исходных параметров, так и задумано.
  4. На вкладке «Запрос» откройте исходящий запрос к Meta: internal_note нет и там. Те же два места смотрят у тегов Google Ads и GA4.

Во входящем запросе поле останется, потому что преобразование входящий запрос не переписывает. Раз пометка не нужна ни одному получателю, правильнее убрать её на сайте, а Exclude оставить страховкой, пока разработчик это делает. И помните о журналах: Cloud Run по умолчанию записывает путь и параметры каждого запроса, так что всё, что пришло на сервер, окажется и там.

Согласие

Согласие собирают в веб-контейнере. Баннер передаёт выбор тегу Google, тот добавляет параметры согласия к запросу на сервер, а теги Google в серверном контейнере сами подстраиваются под этот выбор, поэтому режим согласия настраивают только в веб-контейнере (consent mode на сервере). Но это правило про теги Google. Тег Meta, TikTok или собственный HTTP-запрос в серверном контейнере срабатывает по своему триггеру у любого посетителя, пока вы сами не добавите условие на согласие. Такое условие ставят на каждый сторонний тег отдельно и потом проверяют отказом, как в разборе Consent Mode v2 и server-side GTM.

Задание: серверный контейнер для тестового сайта

Возьмите тестовый сайт с формой из урока про GA4 или любой свой.

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

Если предварительный просмотр пуст, первым делом смотрят адрес в server_container_url и браузер: сайт и просмотр должны быть открыты в одном браузере. Запрос виден, а тег GA4 не сработал - откройте условие триггера, там должно стоять имя клиента, а не его тип. Тег сработал, но у исходящего запроса код ошибки - значит, получатель что-то не принял, и разбираться надо с данными события. Если заявка с ошибкой всё же дошла до сервера, тег на сайте срабатывает по клику, а не по ответу сервера, и чинить это надо в веб-контейнере. В итоге у вас скриншот, по которому другой человек поймёт, что поток работает.

Видео: настройка GA4 через sGTM

Google Tag Manager Server-side tagging tutorial with Google Analytics 4 - Analytics Mania

Видео на английском.

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