Wszystkie wpisy

5 czerwca 2026

Server-side GTM — jak odzyskać dane tracone przez ad-blockery i Safari

Według raportu IAB Polska z 2024 roku blokery reklam używa 45% polskich internautów. Globalnie średnia to około 29%. Oznacza to, że Polska jest jednym z trudniejszych rynków dla trackingu — i że jeśli mierzysz kampanie, optymalizujesz konwersje lub karmisz algorytmy Smart Bidding danymi, pracujesz na wycinku rzeczywistości.

Ten artykuł wyjaśnia skąd bierze się ta luka, czemu standardowy Google Tag Manager jej nie zamyka, i jak server-side GTM przez same-origin proxy rozwiązuje problem. Łączy perspektywę biznesową — ile danych realnie tracisz — z techniczną: jak to wdrożyć. Decyzja o sGTM jest jednym i drugim naraz.

Dwa osobne problemy

Utrata danych analitycznych ma dwa różne źródła, które często są mylone.

Ad-blockery działają przez listy znanych domen. googletagmanager.com, google-analytics.com, doubleclick.net — wszystkie figurują w popularnych listach blokujących (uBlock Origin, AdBlock Plus, Brave). Rozszerzenie w przeglądarce widzi request do takiej domeny i go blokuje, zanim trafi do sieci. Twój serwer analityczny nigdy nie dostaje tego hitu.

Safari ITP i Firefox to osobny mechanizm — nie blokują domen, tylko ograniczają cookies. Safari (Intelligent Tracking Prevention, aktywne od wersji 14) wygasza cookies JavaScript po 7 dniach, a przy link decoration nawet po 24 godzinach. Third-party cookies są martwe w Safari od dawna. Firefox ma podobne ograniczenia w trybie Enhanced Tracking Protection.

Efekt praktyczny: GA4 traktuje powracającego użytkownika Safari jako nową osobę co tydzień. Modele atrybucji nie widzą całej ścieżki zakupowej. Algorytmy Google Ads optymalizują się na danych, które są niekompletne.

Stan blokad per przeglądarka zmienia się przy każdej większej aktualizacji — bieżące zestawienie prowadzi cookiestatus.com.

Dlaczego standardowy GTM nie wystarczy

Client-side GTM działa tak: strona ładuje skrypt z googletagmanager.com, ten skrypt odpala tagi, tagi wysyłają hity bezpośrednio do zewnętrznych systemów (Google Analytics, Ads, Meta, itd.). Przeglądarka jest pośrednikiem — widzi każdy request, każdą domenę.

To właśnie trafia na listy blokujące: zewnętrzne domeny są widoczne w ruchu sieciowym i dopasowywane do blacklist. Bloker nie musi rozumieć co robi skrypt — wystarczy, że rozpoznaje domenę.

Rozwiązanie: server-side GTM

Server-side GTM przenosi część tej logiki na serwer. Przeglądarka wysyła hit do Twojej własnej domeny — nie do Google. Twój serwer (GTM server container) odbiera, przetwarza i przekazuje dalej do faktycznych odbiorców (GA4, Google Ads, itd.).

Client-side GTM (przed):
przeglądarka → googletagmanager.com → google-analytics.com   ← bloker widzi obie domeny

Server-side GTM (po):
przeglądarka → twojadomena.pl/gtm → [serwer GTM] → google-analytics.com

Przeglądarka widzi tylko twojadomena.pl. Bloker nie ma czego blokować — to Twoja własna domena, identyczna z resztą ruchu na stronie.

Same-origin — dlaczego ta opcja wygrywa

sGTM można podpiąć na trzy sposoby:

OpcjaURLITP SafariCloudflareZmiany DNS
Same-origin¹twojadomena.pl/gtmnie potrzebny ¹0
Subdomena + Cloudflaregtm.twojadomena.plwymagany2 CNAME
Bare CNAMEgtm.twojadomena.plnie2 CNAME

rekomendowana dla większości wdrożeń. ¹ „Cloudflare nie potrzebny” odnosi się do prostej strony, gdzie sam kontrolujesz warstwę edge. Na dużej platformie e-commerce sytuacja jest inna — patrz sekcja Skala niżej.

Same-origin wygrywa z jednego powodu: przeglądarka wysyła request do ścieżki na głównej domenie, dostaje IP identyczne z resztą strony. Safari ITP nie widzi żadnej zewnętrznej domeny, więc nie ma czego klasyfikować jako tracking. Subdomena działa tylko z Cloudflare (Anycast zapewnia identyczne IP z apex), bez niego ITP i tak wykrywa różnicę.

Jak to wygląda technicznie

Mechanizm to Edge Function — kod działający na infrastrukturze hostingowej, przed dostarczeniem strony do przeglądarki. Przechwytuje requesty do /gtm/* i proxuje je do backendu sGTM.

Przykładowa implementacja dla Netlify (Deno runtime):

export default async (request, context) => {
  const url = new URL(request.url);
  const targetPath = url.pathname.replace('/gtm', '') || '/';
  const backendUrl = `https://twoj-kontener.stape.net${targetPath}${url.search}`;

  const headers = new Headers(request.headers);
  headers.set('X-Forwarded-For', context.ip);
  headers.set('X-Stape-Host', 'twojadomena.pl');
  headers.delete('host');

  return fetch(backendUrl, {
    method: request.method,
    headers,
    body: request.method !== 'GET' && request.method !== 'HEAD'
      ? request.body
      : undefined,
  });
};

export const config = { path: '/gtm/*' };

twoj-kontener.stape.net to adres backendu Stape przypisanego do Twojego server containera. Ścieżkę /gtm możesz nazwać dowolnie. Edge Function działa server-side — przeglądarka nigdy nie widzi adresu Stape.

Po stronie GTM web containera: tag GA4 dostaje parametr Transport URL ustawiony na https://twojadomena.pl/gtm. Od tego momentu wszystkie hity GA4 lecą przez Twoją domenę, nie bezpośrednio do Google.

Dodatkowa warstwa: Custom Loader

Sama Edge Function rozwiązuje problem ITP i hitów danych. Ale plik inicjalizujący GTM nadal ładuje się z zewnętrznej domeny — bardziej wyrafinowane blokery mogą go złapać po nazwie pliku lub domenie.

Stape oferuje power-up Custom Loader z Enhanced Ad Blocker Protection: generuje obfuskowany plik inicjalizacyjny z losową nazwą i zakodowanym GTM ID. W efekcie w kodzie strony nie ma żadnej wzmianki o googletagmanager.com, a nazwa pliku nie pasuje do żadnych znanych wzorców blokujących.

Pułapka przy wdrożeniu: Stape generuje snippet z własną domeną backendu w parametrze j.src (np. twoj-kontener.stape.net/plik.js). To jest adres bezpośredni — omija proxy i trafia na zewnętrzną domenę widoczną w DevTools. Żeby domknąć same-origin, trzeba ręcznie zmienić j.src na ścieżkę przez proxy:

- j.src="https://twoj-kontener.stape.net/plik.js?"+i
+ j.src="https://twojadomena.pl/gtm/plik.js?"+i

Stape nie dokumentuje tego kroku wprost — snippet wklejony bez tej zmiany wygląda na poprawny, ale loader nadal wychodzi na zewnętrzną domenę.

Zestawienie: co zmienia sGTM

Client-side tylko+ Server-side GTM
Loader GTMprzeglądarka → googletagmanager.com/gtm.jsprzeglądarka → twojadomena.pl/gtm → Edge Function → sGTM
Hit danychprzeglądarka → google-analytics.comprzeglądarka → twojadomena.pl/gtm → Edge Function → sGTM → GA4 / Ads / Meta
Domeny w DevToolsgoogletagmanager.com, google-analytics.comtylko twojadomena.pl (loader + hity przez proxy)
Ad-blockerblokuje po nazwie domenybrak zewnętrznej domeny w ścieżce hitów
Safari ITP_ga skracana do 7 dniFPID server-set, 2 lata, ITP-odporne
IP klienta w tagachEdge Function przekazuje prawdziwy IP → poprawna geolokalizacja kampanii

Skala: same-origin na dużej platformie e-commerce

Powyższy przykład to prosty przypadek — strona statyczna, gdzie sam jesteś właścicielem warstwy edge. Kilka linii Edge Function i gotowe. Na dużej platformie e-commerce same-origin jest wyraźnie bardziej złożone, i tu zaczynają się decyzje architektoniczne.

Różnica jest fundamentalna: na prostej stronie dodajesz warstwę edge. Na dużym sklepie warstwa edge już istnieje — to produkcyjny, skonfigurowany CDN (Cloudflare, Akamai, Fastly) z regułami WAF, cache i load balancingiem. Wstawienie ścieżki trackingowej na głównej domenie oznacza wejście w ten układ, nie obok niego:

  • Reverse proxy zamiast Edge Function — ścieżkę /gtm/* routuje się do backendu sGTM przez Cloudflare Worker, Fastly VCL albo regułę w nginx, w zależności od tego co masz na produkcji.
  • Bypass cache — endpointy trackingowe muszą mieć Cache-Control: no-store. CDN nie może ich cache’ować ani normalizować/sortować query stringów. Normalizacja URL w Cloudflare potrafi popsuć mechanizm pikselowy sendBeacon/sendPixelFromBrowser.
  • WAF i SSL — reguła nie może kolidować z istniejącym Web Application Firewall; Cloudflare wymaga trybu SSL/TLS Full, inaczej proxy łapie błędny redirect 301.

Nie każda platforma w ogóle na to pozwala:

PlatformaSame-origin na apexJak
Statyczna (Netlify / Vercel)łatweEdge Function / rewrite
Magento / Adobe Commercewykonalnereverse proxy w nginx lub Fastly VCL
Własny CDN (Cloudflare / Akamai / Fastly)wykonalneWorker / VCL routujący ścieżkę do sGTM
Shopifyniemożliwe na apexApp Proxy dopuszcza tylko prefiksy apps/tools/… i kieruje do backendu aplikacji — trzeba subdomeny + Cloudflare albo gotowego CDN Stape

Jeśli nie chcesz utrzymywać własnego workera, Stape oferuje warianty managed: Global CDN (zarządzany Cloudflare, redukuje też latencję geograficzną) lub Own CDN (kierujesz swój CDN na Stape, by zachować matchowanie IP i first-party). To kupuje wygodę kosztem mniejszej kontroli.

Realne wdrożenie tego mechanizmu dla sklepu e-commerce — wraz z efektami biznesowymi — opisałem w case study o server-side taggingu.

Co widzisz po wdrożeniu

W DevTools, zakładka Sieć: hity collect idą na twojadomena.pl/gtm/collect — nie ma google-analytics.com w widocznym ruchu. Ad-blocker nie ma nazwy domenowej do dopasowania.

Kilka rzeczy, które mogą wyglądać niepokojąco ale są normalne:

ga-audiences (czerwony) — GA4 odpala ten pixel automatycznie gdy włączone są Google Signals lub powiązane konto Google Ads. Nie jest to tag który wdrożyłeś. Blokowany przez ad-blocker w przeglądarce dewelopera, ale to marginalny sygnał — główny tracking przez sGTM nie jest dotknięty.

Hity do region1.analytics.google.com — consent mode pings, wysyłane przez GA4 nawet przy odmowie zgody, bez danych osobowych, dla celów modelowania behawioralnego Google. Celowo omijają sGTM — to standard Consent Mode v2.

Debugowanie sGTM — co widać, a co nie. Wtyczki przeglądarkowe (dataLayer Inspector+, GA Debugger) dekodują hit wychodzący z przeglądarki do kontenera serwerowego — pokażą pełny payload, który strona wysyła na transport URL: cid, gcs, sst.*, dl i resztę parametrów. To realnie przydatne do sprawdzenia, co opuszcza przeglądarkę. Czego nie zobaczysz w przeglądarce, to przetwarzania po stronie serwera: jak server-side tagi mapują i wzbogacają dane (np. ip_override, obsługa FPID) ani hitów wychodzących z kontenera do GA4 / Meta / Ads. To dzieje się poza przeglądarką — do tego służy GTM Preview na kontenerze serwerowym.

Cookies: co ustawia sGTM

sGTM dopisuje do odpowiedzi HTTP własne cookies — ustawione server-side, poza zasięgiem Safari ITP.

CookieKto ustawiaCelTrwałośćTracking Protection
_gaJavaScript (GA4)Client ID — identyfikacja powracających użytkowników2 lataSafari ITP: skraca do 7 dni; Firefox Strict / Brave: może zablokować żądanie
_ga_[PropertyID]JavaScript (GA4)Sesja: timestamp, numer sesji, liczba hitów2 lataSafari ITP: skraca do 7 dni; Firefox Strict / Brave: może zablokować żądanie
FPIDSerwer (sGTM)Client ID server-side; zastępuje _ga jako główny identyfikator. HttpOnly — JS nie może odczytać2 lataodporne — ustawia serwer HTTP
FPLCSerwer (sGTM)Jednorazowy token synchronizacji FPID między subdomenamikilka godzinodporne — ustawia serwer HTTP

Problem nie dotyczy tylko Safari. _ga to cookie JavaScript — każda przeglądarka z agresywną ochroną przed śledzeniem może go skrócić lub zablokować. Safari ITP (aktywne domyślnie na wszystkich urządzeniach Apple) skraca do 7 dni. Firefox w trybie Strict i Brave mogą zablokować request do zewnętrznej domeny trackingowej zanim cookie w ogóle powstanie. W efekcie bez sGTM tracisz dane od użytkowników Safari, Firefox Strict i Brave jednocześnie — co razem z ad-blockerami może odpowiadać za 40–50% ruchu. Bieżące zestawienie per przeglądarka: cookiestatus.com.

FPID ustawia serwer przez nagłówek Set-Cookie w odpowiedzi HTTP — żadna z tych przeglądarek nie ma mechanizmu ingerencji w server-set cookies. Użytkownik Safari po 7 dniach nieaktywności przestaje wyglądać jak nowy.

Kiedy warto wdrożyć

sGTM warto rozważyć zawsze, gdy zbierasz dane do systemów marketingowych i zależy Ci na ich kompletności. Warto przy tym pamiętać, że sGTM nie naprawi błędów warstwy pomiarowej — błędy wdrożenia GA4 w e-commerce to osobny wektor strat, który działa niezależnie od blokowania ruchu.

Ale jego rzeczywista siła jest szersza niż samo obejście ad-blockerów.

W standardowym podejściu każda platforma dostaje oddzielny tag w przeglądarce: GA4 ma swój, Google Ads ma swój, Meta ma swój, TikTok ma swój. Każdy z tych tagów ładuje skrypt z zewnętrznej domeny — każdy jest osobnym punktem do zablokowania, osobnym obciążeniem przeglądarki, osobnym miejscem gdzie dane mogą być niekompletne przez ITP.

sGTM odwraca ten model: przeglądarka wysyła dane raz, do Twojej domeny. Server container decyduje co dalej — do GA4, do Google Ads, do Meta Conversion API, do TikTok Events API i każdego innego systemu marketingowego obsługiwanego przez GTM. Jedna ścieżka wejścia, wiele wyjść. To jeden z głównych argumentów za sGTM niezależnie od skali projektu.

Koszt wdrożenia przez Edge Function jest niski — nie wymaga dodatkowej infrastruktury poza hostingiem. Koszt to czas konfiguracji, nie miesięczny abonament serwera.

Szczególnie uzasadnione gdy audytorium ma ponadprzeciętny udział Safari (iOS, macOS) lub gdy mierzysz długie cykle decyzyjne — tam 7-dniowy limit cookies Safari uderza najbardziej.

Powiązane wpisy