Серверний трекінг і Measurement Protocol: коли він потрібен
Що таке серверний трекінг, чим відрізняються server-side GTM і GA4 Measurement Protocol, які події варто слати з бекенду (оплати, повернення, офлайн-продажі), як не порушити згоду користувача і не задвоїти дані.

Клієнтський трекінг (теги в браузері) втрачає частину подій: блокувальники, закриті вкладки, оплата на сторонніх сторінках. Серверний трекінг — це відправка подій з вашого сервера, де вони надійно відомі. Але це не «чарівна кнопка», яка повертає всіх користувачів, і не спосіб обійти відмову від cookies.
Два різні підходи
| Server-side GTM | Measurement Protocol (GA4) | |
|---|---|---|
| Що це | сервер-посередник: браузер шле події на ваш домен, сервер передає далі | прямий HTTP-запит до GA4 з бекенду |
| Для чого | керування потоком даних, власний домен, фільтрація полів | події, які знає лише бекенд |
| Складність | хостинг контейнера, налаштування | кілька рядків коду |
| Вартість | хостинг сервера | безкоштовно |
Ці підходи не взаємовиключні. Для малого й середнього бізнесу я найчастіше починаю з Measurement Protocol для ключових бекенд-подій.
Які події слати з сервера
- Підтвердження оплати після callback від LiqPay, monobank, Stripe — навіть якщо клієнт не повернувся на сайт.
- Повернення (
refund) — коли менеджер оформлює їх у CRM. - Зміни статусу ліда: кваліфікований, угода, оплачено — для оптимізації реклами на якісні ліди.
- Офлайн-продажі клієнтів, які прийшли з сайту (з відомим
client_id). - Продовження підписок у SaaS.
Measurement Protocol: як працює
Документація Google описує запит: POST з measurement_id, api_secret і тілом з client_id та подіями.
import os, requests
def ga4_purchase(client_id: str, order: dict) -> None:
url = "https://www.google-analytics.com/mp/collect"
params = {"measurement_id": os.environ["GA4_MEASUREMENT_ID"], "api_secret": os.environ["GA4_API_SECRET"]}
body = {
"client_id": client_id, # з cookie _ga, збережений із замовленням
"events": [{
"name": "purchase",
"params": {
"transaction_id": order["id"],
"value": order["total"],
"currency": "UAH",
"items": order["items"],
},
}],
}
requests.post(url, params=params, json=body, timeout=10).raise_for_status()
Ключові умови:
client_idтреба зберегти заздалегідь — під час оформлення замовлення фронтенд передає значення з cookie_gaразом із замовленням;transaction_idтой самий, що й у клієнтській події, — тоді дублікати відсіюються;api_secret— лише на сервері;- для перевірки є окремий debug-ендпоінт, що повертає помилки валідації.
Згода користувача
Серверний трекінг не скасовує вимог щодо згоди. Якщо користувач відмовився від аналітичних cookies, передавати його ідентифікатор і поведінкові дані в GA4 з сервера — це те саме порушення, лише з іншого місця. Практичний підхід:
- зберігати разом із замовленням стан згоди;
- слати серверні події з
client_idлише для користувачів зі згодою; - для решти — враховувати продажі в CRM і аналітиці на агрегованому рівні (consent mode).
Політика конфіденційності має описувати, які дані передаються третім сторонам.
Як не задвоїти дані
| Ризик | Рішення |
|---|---|
purchase і з браузера, і з сервера | однаковий transaction_id; або лише сервер для оплачених онлайн |
| Повторний callback від платіжки | ідемпотентність: зберігати, що подію вже відправлено |
| Події з тестового середовища | окремий ресурс GA4 або фільтр |
Неправильний client_id | валідувати формат, не генерувати випадковий |
Що змінюється в звітах
- покриття замовлень у GA4 зростає, особливо для оплат на сторонніх сторінках (розбіжності GA4 і CRM);
- серверні події не мають даних про сесію браузера (сторінка, пристрій) — GA4 прив'язує їх до користувача за
client_id; - у BigQuery серверні події видно так само, як клієнтські (експорт GA4).
Чекліст
- Визначено бекенд-події: оплата, повернення, статуси ліда
client_idзберігається із замовленням/лідом- Стан згоди зберігається і враховується
api_secretі ID — у змінних середовища- Ідемпотентність відправки
- Перевірка через debug-ендпоінт
- Звірка покриття до і після
Покроково: додаємо серверну подію покупки
Повне впровадження з низьким ризиком для магазину, де оплата завершується на зовнішній сторінці:
- Зберігайте
client_idіsession_idпід час оформлення. Прочитайте cookie_ga(client ID — дві останні частини через крапку) і ID сесії з сесійного cookie GA4 або черезgtag('get', ...)і передайте обидва разом із замовленням на бекенд. Збережіть їх у замовленні разом зі станом згоди. - Вирішіть, хто надсилає
purchase. Найпростіше безпечне рішення: сервер надсилаєpurchaseдля кожного оплаченого онлайн-замовлення зі згодою на аналітику, а браузер більше не надсилає. Ризик дублів зникає повністю. - Надсилайте на вебхук оплати — після перевірки його підпису і того, що замовлення ще не позначене як відправлене.
- Додайте
session_idу параметри події, щоб покупка прив'язалася до правильної сесії і зберегла джерело трафіку у звітах GA4. - Перевіряйте кожне повідомлення через debug-ендпоінт під час розробки, потім два тижні порівнюйте покриття до і після.
def on_payment_confirmed(order):
if order.ga_sent or not order.analytics_consent or not order.ga_client_id:
return
payload = {
"client_id": order.ga_client_id,
"timestamp_micros": int(order.paid_at.timestamp() * 1e6),
"events": [{
"name": "purchase",
"params": {
"session_id": order.ga_session_id,
"transaction_id": str(order.id),
"value": float(order.total_net),
"currency": order.currency,
"items": [{"item_id": li.sku, "price": float(li.price), "quantity": li.qty}
for li in order.lines],
},
}],
}
send_mp(payload) # POST /mp/collect, як вище
order.mark_ga_sent() # ідемпотентність
timestamp_micros дозволяє надіслати подію з фактичним часом оплати. Документація Google обмежує, наскільки далеко в минулому він може бути, тож надсилайте одразу, а не нічним пакетом.
Приклад: покриття до і після
Ілюстративне порівняння за два тижні для магазину, де близько третини оплат проходить через зовнішню сторінку оплати:
| До (лише браузер) | Після (серверний purchase) | |
|---|---|---|
| Оплачені онлайн-замовлення (бекенд) | 1 000 | 1 000 |
| Замовлення зі згодою на аналітику | 780 | 780 |
Події purchase у GA4 | 640 | 772 |
| Покриття замовлень зі згодою | 82% | 99% |
Залишок розриву — замовлення без збереженого client ID (наприклад, створені застосунком чи менеджером). Розрив для замовлень без згоди очікуваний і правильний — не намагайтеся його закрити.
Повернення з сервера
Повернення майже завжди оформлюються в бекенді, тож саме звідти їх природно надсилати:
{ "client_id": "1234567890.1700000000",
"events": [{ "name": "refund",
"params": { "transaction_id": "100245", "value": 875.00, "currency": "UAH",
"items": [{ "item_id": "SKU-118", "quantity": 1 }] } }] }
Для повного повернення items можна не передавати; для часткового — перелічіть повернені товари. Без повернень виручка в GA4 назавжди лишається вищою за ту, що ви реально отримали, — див. розбіжності GA4 і CRM.
Типові помилки
| Помилка | Наслідок | Як виправити |
|---|---|---|
| Генерувати новий client_id на сервері | покупка виглядає як новий користувач без джерела | завжди брати збережений ID браузера; немає — пропустити |
| Без session_id | покупка потрапляє в «(not set)» чи direct | передавати збережений ID сесії |
| Надсилати на кожен повтор вебхука | дублі | прапорець ідемпотентності в замовленні |
| Надсилати без згоди | ризик порушення вимог | зберігати згоду із замовленням і перевіряти перед відправкою |
| api_secret у коді фронтенду | будь-хто може слати фейкові події | тримати лише на сервері |
Коли server-side GTM вартий додаткової роботи
Server-side GTM окуповує хостинг, коли виконується одна чи кілька умов:
- Багато тегів вендорів. Замість п'яти маркетингових скриптів у браузері сторінка надсилає один потік у ваш серверний контейнер, а той пересилає кожному вендору. Сторінки легшають, і ви точно контролюєте, які поля отримує кожен вендор.
- Вимоги мінімізації даних. Можна прибрати IP-адреси, хешувати чи відкинути ідентифікатори, відфільтрувати параметри URL ще до того, як щось залишить вашу інфраструктуру.
- Власний ендпоінт. Контейнер на піддомені вашого сайту (наприклад,
metrics.example.com) робить запити «своїми» для браузера. Це підвищує надійність, але не змінює ваших зобов'язань щодо згоди.
Операційні нотатки, якщо обираєте цей шлях: плануйте щонайменше два інстанси для доступності, моніторте частку помилок і затримку, тримайте контейнер під контролем версій із журналом змін і закладайте бюджет на хостинг, що зростає разом із трафіком. Варіанти розгортання описано в документації Google щодо серверного тегування.
Для більшості малих і середніх бізнесів правильна послідовність така: спершу серверні події з бекенду через Measurement Protocol для оплат і повернень, а server-side GTM — пізніше, коли кількість тегів і вимоги до даних справді цього потребують.
Часті запитання
Чи потрібен server-side GTM малому бізнесу?
Не завжди. Якщо головна проблема — втрачені оплати й повернення, Measurement Protocol з бекенду вирішує її дешевше. Server-side GTM має сенс при багатьох тегах і вимогах до контролю даних.
Чи обходить серверний трекінг блокувальники реклами?
Частково — події з бекенду не залежать від браузера. Але це не привід ігнорувати вибір користувача щодо згоди.
Чи можна слати події в Meta з сервера?
Так, у Meta є Conversions API. Для дедуплікації з піксельними подіями використовується спільний ідентифікатор події.
Скільки часу займає впровадження?
Для 2–3 бекенд-подій з Measurement Protocol — зазвичай кілька днів разом з тестуванням, якщо є доступ до коду бекенду.


