Чистий серверний трекінг: екскурсія по сетапу

Я обійшовся без web GTM, переніс збирання пейлоуду в Cloudflare Worker і зробив GA4 споживачем своїх даних, а не їх джерелом.
Якби ж то мені сказали 7 років тому, в яких хащах трекінгу я буду вовтузитися, я б собі не повірив. От знав я ще з початку своєї карʼєри - хочеш, щоб Universal Analytics збирала дані на сайті? Встанови скрипт. Скрипт… Тоді в мене в голові ще не існувало категорій client-side / server-side, а принцип роботи аналітики був чимось дійсно магічним. Та тепер я тут, на крайньому (на даний момент) етапі еволюції трекінгу, і буду розказувати вам про нюанси і підходи, для котрих поставити скрипт на сайт буде явно недостатньо.
Хоч тему статті я вже визначив, оскільки це перша стаття на блозі, мені не відпетляти від короткого інтро про себе. Я працюю технічним маркетологом вже понад сім років і на власні очі спостерігав етапи розвитку веб-аналітики і трекінгу: перші спроби працювати з сирими даними в Analytics 360 (для особливо багатих), перші дзвіночки про серверний трекінг, повальне захоплення аналізом сирих даних GA4 в силу доступності експорту до BigQuery… На той час все, що відмінне від клієнтського трекінгу, виглядало для мене дійсно, як рокетсаєнс. Зараз, у 2026 році, серверний трекінг вже не виглядає якоюсь непосильною задачою. Великий і щирий шаут-аут за це команді Стейпу, як головним євангелістам сервер-сайд трекінгу.
Так ось. На етапі першого релізу Гуглами серверного ГТМу я думав, що це – безпосередньо заміна звичайному веб-контейнеру. Ба більше, я певен, що багато маркетологів досі так і вважають. Інтуітивно відчувається, що серверний трекінг – це обмін даними між сервером нашого сайту і вендорами, чи то Гугл аналітика або Google Ads. Але реальність трохи складніша і, щоб дані зʼявилися у нас на сервері, вони мають «відбутися», «народитися» в браузері користувача . Лише потім вони опиняються у нас на сервері.
Нам продають покращення швидкості завантаження сторінок при використанні сервер-сайд ГТМу шляхом мінімізації кількості трекінгового js-коду в браузері користувача. Однак, делікатно не уточнюють, що на 100% позбутися браузерного трекінгу навряд вдасться – нам треба щось, що буде збирати всяку телеметрію користувача. Без цього, деяких даних в вашій аналітиці просто не зʼявиться.

І мені останні пару років моєї щільної роботи з сервер-сайдом, аж свербіло в голові, як хотілося не зупинятися на чомусь «гібридному» серверному відстеженні і протоптати стежинку далі, випередивши самих Гуглів, Майкрософтів або, на крайняк, Stape. І я почав брейнштормити «А що, якщо?»
А що там в Смарагдовому місті?
Смарагдове місто за моїм сетінгом – то мій блог, якщо що. Так ось, цей сайт – моя лабораторія, місце, де я можу дозволити собі будь-які експерименти. Місце, де я абсолютно безпечно можу шукати способи втілення усіх моїх найбезумніших фантазій. Які фантазії, ви спитаєте?
- Наприклад, збір даних і формування пейлоуду не в браузері користувача, а на сервері;
- Альтернативний стрімінг сирих даних замість нативного експорту GA4 в BigQuery;
- Логічний наступний крок – альтернативний постпроцесінг даних (підходи до атрибуції, до прикладу);
- Відмінні від стандартних експортів BigQuery підходи на дата-інженерному поприщі;
- Свої спроби боротьби з ботами;
- GA4, як користувач, а не власник даних;
- Грамотна візуалізація контент-проекту, котрим я бачу цей блог в майбутньому (відкладемо на момент, коли буде хоч якийсь трафік);
Швиденько пробіжимося по всіх пунктах, але не сумнівайтесь, що більш детально про кожен з них я буду писати в майбутньому, як окремі статті.
Етап 1: формування хітів і їх відправка в sGTM на базі Stape
Скажу максимально приземлено і в контексті веб-трекінгу, що хіт – це мінімальна одиниця, зерно, grain, кожна окрема подія-івент, що виникає під час взаємодії окремого користувача з сайтом. При суто клієнтському трекінгу або «серверному» (в лапках, бо говорю про гібридний), ці хіти збираються в браузері за допомогою gtagʼу і звідти відправляються на сторону вендора (або опціонально на серверний контейнер таг менеджеру).
В моєму рішенні пейлоуд збирається воркером на стороні Cloudflare, він же відповідає за ідентифікацію користувачів та їх сесій (грубо кажучи, проставляє куки з відповідними айдішками від імені серверу). Цей пейлоуд виходить майже 1в1 з тим, що відправляє ГА4 з браузера, таким чином, ідеально сприймається нативним клієнтом GA4 на стороні sGTM’у.


Справжній пейлоуд page_view – рівно такий, яким його склав воркер.


І той самий пейлоуд уже в sGTM: нативний клієнт GA4 забирає його як свій, а collected_by: worker показує, де він зібраний.
Махінації в межах серверного контейнера – то окрема тема, котрої точно буде вдосталь на цьому блозі. Але в контексті моїх вологих веб-аналітичних фантазій, там не те, щоб щось дуже цікаве є розповідати на даному етапі. Все стандартно:
- Клейм вхідного реквесту GA4
- Парсинг даних на івентДату
- Спред і ворвард даних на потрібних нам вендорів
Етап 2: Альтернативний стрімінг сирих даних замість коробочного рішення GA4 ↔ BigQuery
На межі двох епох, між UA і GA4, всі дуже плювалися на нову аналітику (здебільшого, за урізання вже звичного функціоналу і дуже незвичного веб-інтерфейсу), але беззаперечною кіллер-фічею була нативна інтеграція і експорт сирих даних в Google BigQuery. На мою думку це саме той момент, коли маркетологи всього світу щільно насіли на вивчення SQL. І від того моменту я почав забувати, що таке GA4 web-UI (ненавиджу його).
Так склалося, що продукти (в плані бізнеси), з якими я працюю, мають дуже великі обʼєми трафіку і це унеможливлює аналіз на агрегованих даних у вебі. Тож єдиним для нас виходом було переорієнтування на аналіз на основі сирих даних. Та є речі в нативному експорті, котрі мені взагалі не до вподоби:
- Daily експорт має обмеження в 1 мільйон івентів на добу для одного проперті аналітики;
- Інтрадей обмежень не має, але там вручну треба процесити дані (теж багато нюансів є);
- Працюючи виключно на інтрадей експорті, якщо з боку Гугла відбуваються збої в роботі, дані втрачаються назавжди;
- Процесінг даних на етапі «дані долетіли до ендпоінту ГА4» – «дані поклалися в таблицю», це блекбокс і те ще дно.
Отже, і тут буде своє рішення, з блекджеком і слухами. А для порівняння,
забігаючи трохи наперед, на кожному івенті буде передаватись свій event_key,
котрий потенційно буде використаний як місток між власним стрімінгом і нативним
(на випадок, якщо захочу порівняти власні правила процесингу і повноту даних).
Етап 3: Постпроцесінг (постобробка) даних
Сусідні етапи межують по змісту, тож вже похаяти рідний гугловський процесінг я вже встиг. Не, ну серйозно, я памʼятаю навіть в мережі гуляв спредшит-файл у вигляді таблички, де комʼюніті однодумців збирали баги, повʼязані з сирими даними GA4 при експорті в BigQuery (upd: знайшов).
- Параметр
page_locationмаєgclid, але в окреме поле його чомусь не винесло. google / organicтам, де мав би бутиgoogle / cpc(то взагалі класика).- та інші досадні баги (детальний список за посиланням вище).
Ну, погодьтеся, несолідно червоніти перед менеджером, відповідаючи «то все процесінг» на питання просадки трафіку по платній рекламі. Ні. Я хочу контролювати кожен крок і впливати на дані на кожному з етапів. Отже, правила обробки даних також лягають на мої плечі і логічно діляться на наступні категорії:
- Атрибуція і все, що з нею повʼязано (
source,medium, клік айдішки, групи каналів тощо – все рахується і виводиться на основіpage_location&page_referrer) - Тачпоінти – логічна сутність між івентом і сесією. Простими словами –
доторк ззовні до сайту від користувача. Прийшов з органіки на сайт, повернувся
назад у видачу і перейшов вже по рекламі – зробив два тачпоінти: по
google / organicі другий – поgoogle / cpc. - Пристрій (девайс, браузер, ОС) – парсинг юзер-агента і робота з так званими підказками браузера.
- Робота з ГЕО полями і консентом
- Все, що повʼязано з ботами (результатом виноситься вердикт, бот-не-бот)
- Решта дрібʼязку по типу локального часу користувача і спільного слагу укр і eng сторінки
Після цього етапу маю плоску таблицю на 112 поля. Оскільки трафіку поки нема (ми тільки розганяємося), я дозволив собі розгулятися. Хоча до цього варіантів було в районі 140 полів (але за відчуттями, то вже занадто)
Етап 4: Заглиблення в дата-інженерію
Раніше робота веб-аналітика на тривіальному рівні виглядала так: ставиш ГТМ, запускаєш аналітику, вмикаєш експорт у БігКвері з адмінки ГА4 і все, далі просто нюхаєш квіточки. Зараз до всього цього я пробую себе в якості дата-інженера: будую таке собі ДВХ за всіма канонами, рухаючись порівнево, від сирих даних до вітрин, котрі відповідатимуть на конкретно поставлені мною бізнес-питання:
- Layer 0 – джерела даних: браузер, кукі, хедери реквестів
- Layer 1 – raw, складування R2 файлів в Cloudflare (1 файл = 1 хіт, івент) з подальшою склейкою по закриттю повних 24 годин доби до одного файлу
- Layer 2 – staging, трансформація результату Layer 1 до табличного вигляду в паркет файл з відповідністю 1до1 попереднього етапу.
- Layer 3 – enriched, місце, де відбувається пост-процесінг, частково описаний в етапі 3. Поки що дійшов лише сюди
- Layer 4 – models, тут плануються таблиці в розрізі скоупів вище івенту:
touchpoints, sessions, pseudo-ids, users,
identity_map(словник айдішок, за допомогою котрого будуть відбуватись джойни) - Layer 5 – marts, вітрини агрегованих даних, котрі мають відповідати на конкретно поставлені питання, наприклад, про популярність статей
Про існування подібних підходів я десь шось чув, десь шось читав, але ніколи не займався проектуванням леєрів і не проходив степ-бай-степ власноруч. Зізнаюсь, що таски по блогу, повʼязані з дата-інженерією – одні з найулюбленіших на даний момент. Поки сумно, що реальних даних (виключаючи ботів) нема, тож дещо доводиться робити «всліпу» і наперед. Прекрасне ось що: кожен Layer має свої фіксовані правила того, що можна робити, а чого – в жодному разі (наприклад, в жодному випадку не можна змінювати сирі дані, і кожен наступний крок вираховується на основі даних з попереднього кроку).
Етап 5: Вилов / фільтрація ботів і різних краулерів
Якщо ви уважно вдивитесь поміж рядків цієї статті, ви зрозумієте, що я будую самодостатню від GA4 систему аналітики. Так, деякі речі у неї запозичені, по типу параметрів хітів. І, по суті, ніщо не заважає мені взагалі не передавати дані в ГА4.
Але з рішенням будувати кастомний стрімінг і власне сховище на плечах їде і певний трейд-оф: ви б тільки знали, скільки ботів бігає по моєму сайту (як мінімум, я такого не очікував). Навіть на етапі розробки самого сайту, коли я ще не презентував його публічно, в мене генерувалося порядка 1-2к івентів щоденно тільки від ботів. Так, дещо з цього – мої власні автоматичні перевірки, але все ж.
Система простенька – в її основі певний набір правил на основі даних + дві
результуючі метрики: bot_signals_against & bot_signals_for. Фактично, це
обвинувачення і виправдання факту належності хіта до боту. Виходить такий собі
суд, де кожне правило або обвинює, або захищає.
| Сигнал | Сторона | Спрацьовує, коли |
|---|---|---|
tool_name |
проти | юзер-агент називає відомий інструмент або бібліотеку |
scan_path |
проти | шлях у запиті схожий на сканування вразливостей |
no_user_agent |
проти | юзер-агента немає взагалі |
no_language |
проти | accept-language порожній |
bot_cipher |
проти | набір шифрів TLS такий, якого браузери не пропонують |
hosting_network |
проти | адреса належить мережі-хостеру, і це обвинення враховується тільки коли захисту немає жодного |
http3 |
за | реквест прийшов по HTTP/3 |
browser_facts |
за | приїхала роздільна здатність екрана, тобто скрипт виконав справжній браузер |
Останнє «проти» – найобережніше: мережа-хостер сама по собі не доказує нічого.
Одного обвинення без жодного захисту досить, щоб поставити
bot_verdict = 'bot'. Одного захисту без обвинень – для 'human'. А коли
доводи є з обох боків або немає взагалі, вердикт 'unknown': краще мати хіт,
який я не можу класифікувати, ніж людину, записану роботом.
Коли сайт побачить світ і я запущу реальний трафік на нього, є бажання глянути
на точність моїх правил порівняно з антиботом від ГА4 шляхом джойну двох
датасетів (нативного БК-експорту і мого власного) по ключу event_key.
Етап 6: GA4, як користувач нашими даними, а не їх джерело
Тут може бути дещо трікі. Для 99% (умовно) сайтів світу Гугл аналітика виступає основним джерелом даних для бізнесу, що найменш по роботі з веб-даними. Причини всім відомі – безкоштовність, екосистема Гугл (а багато хто користується Гугл рекламою) і купа інших причин. Чому ГА4 – джерело даних? Бо ми ставимо скрипт, що називається gtag, на фронт-енд сайту і він починає збирати дані з браузера, компонувати їх в хіти-івенти і надсилати в Гугл напряму або в серверний контейнер у тих, хто шарить.
У мене на сайті цього скрипта нема зовсім, і це свідомий вибір – памʼятаєте, що я цілюсь в ЧИСТИЙ серверний трекінг, а не гібридний, де дані народжуються в браузері, а потім пересилаються на серверний контейнер. Як результат, у мене, до прикладу, немає веб контейнера ГТМу в принципі (такий от я збочинець).
Незважаючи на те, що дані я збираю сам на сервері, формат даних на виході виходить такий самий, як з пейлоуду, сформованого гтагом. От і виходить: з сервера я відправляю дані на сГТМ і він, завдяки дефолтному клієнту GA4 без питань приймає мої дані і розкладає їх на івент дату. Далі очевидно – використовуємо тег GA4 для відправки даних і вуаля: ГА4 офіційно стає користувачем даних, котрі МИ створили.
Резюмуючи: тепер ГА4 має вірити моїм даним, а не я даним ГА4. Якщо я кажу, що цей юзер прийшов з Бразилії, значить воно так і є. Якщо я повідомив аналітиці, що цей конкретний користувач не дав згоду себе трекати, то аналітика сприймає це на віру і отримує від мене так званий кукілесс хіт в якості івенту.
У когось може виникнути питання, для чого мені тоді ГА4? По факту ні для чого важливого. Хочу я цього чи ні, але ГА4 – це стандарт ринку. Копатися під капотом і тримати руку на пульсі нововведень – важлива річ для мене, як для професіонала. BI-репорти, як логічний наступний крок, будуть будуватися мною точно в обхід GA4.
Висновок
Тож повертаючись до питання тайтлу. І я б його дещо перефразував: «Чи можливий чистий серверний трекінг» розбив би на «А чи взагалі потрібен чистий?» + «А наскільки чистий серверний трекінг?».
Спойлер – чистого на 100% s2s-трекінгу не може бути. Є деякі речі, котрі серверу ніяк не можуть бути відомі, на кшталт роздільної здатності екрана, часу активної взаємодії і тд.
Дуже суттєвою перевагою «чистого» сервер-сайду є те, що оскільки формування даних відбувається на сервері, нам нестрашні блокувальники реклами.
Основна перевага трекінг-аналітичного сетапу, що я обрав для блогу – незалежність від GA4, її обмежень, постпроцесінгу і можливість обрати власний шлях, котрий навряд буде колись залежати від потенційних «змін на краще» з боку Гугла. Завдяки досвіду і глибокому розумінню підкапотної частини (а також АІ-шці для реверс-інжинірингу), я зміг підтюнити кожен етап до прийнятного саме для мене рівня. Результатом дуже задоволений.
Якщо вам вистачило наснаги дочитати до кінця – дякую. Коментарів поки що нема, але якщо є що сказати / запитати / подискутувати, будь ласка, пишіть в форму – повідомлення прийде мені в телеграм-бота.