LW IT Solutions
« Blog Overview /Digital Analytics / gtag(’set’) w praktyce: przekazanie User ID do...
This post in other languages:

gtag(’set’) w praktyce: przekazanie User ID do już załadowanego Google Tag

Spis treści
  1. Pięć poleceń gtag i wzajemne oddziaływanie ich zakresów
  2. Przypadek szczegółowo: późne przekazanie User ID
  3. Parametr update: scalanie zamiast ponownej inicjalizacji
  4. Droga przez Google Tag Manager
  5. Przypadek pokrewny: Consent Mode
  6. Pułapki i kontrole
  7. Podsumowanie
  8. Źródła

Aplikacja webowa z logowaniem zwykle dowiaduje się, kim jest odwiedzający, o chwilę za późno. Strona się ładuje, Google Tag się inicjalizuje, polecenie config wysyła swój page_view — a dopiero potem formularz logowania zwraca sesję albo aplikacja single-page ustala konto na podstawie wywołania API. Zanim User ID zaistnieje, pierwszy hit już opuścił przeglądarkę.

Odruchem w takiej sytuacji jest ponowne skonfigurowanie tagu z dołączonym identyfikatorem. Ten odruch jest kosztowny i zbędny. Już załadowany Google Tag nie musi być przeładowywany ani ponownie inicjalizowany tylko dlatego, że jedna wartość dotarła z opóźnieniem: pojedyncze polecenie set przekazuje tę wartość, a każde zdarzenie wysłane później na tej stronie ją niesie.

Dwie osie czasu w porównaniu: ponowne uruchomienie Google Tag tworzy zdublowany page_view, natomiast jedno polecenie set przekazuje User ID do działającego tagu
Ten sam moment, dwie drogi: ponowne uruchomienie Google Tag inicjalizuje go jeszcze raz i zapisuje drugi page_view w sesji, natomiast jedno polecenie set przekazuje User ID do działającego tagu, a każde kolejne zdarzenie je niesie.

Pięć poleceń gtag i wzajemne oddziaływanie ich zakresów

API gtag.js zna dokładnie pięć poleceń, a podział zadań między nimi jest tym, co umożliwia późne przekazanie wartości.

Polecenie Sygnatura Cel Zasięg
config gtag('config', '<TARGET_ID>', {…}) Dodaje informacje konfiguracyjne do celu; TARGET_ID decyduje, dokąd gtag.js wysyła dane zdarzeń, a kolejne wywołanie dodaje kolejny cel. Wszystkie zdarzenia do tego jednego TARGET_ID.
set gtag('set', {…}) Definiuje parametry powiązane z każdym kolejnym zdarzeniem na stronie. Istnieje też forma z nazwaną grupą, na przykład gtag('set', 'campaign', {…}). Globalny, od momentu wywołania, wyłącznie bieżąca strona.
event gtag('event', '<event_name>', {…}) Wysyła dane zdarzenia, zarówno zdarzenia rekomendowanego, jak i własnego. To jedno zdarzenie.
get gtag('get', '<target>', '<field>', callback) Odczytuje wartości z gtag.js, w tym wartości przypisane poleceniem set: client_id, session_id, session_number, gclid. Dostęp do odczytu; callback otrzymuje pole albo undefined.
consent gtag('consent', 'default'|'update', {…}) Ustawia początkowy stan zgody albo aktualizuje go, gdy decyzja już istnieje. Sygnały zgody dla strony.

Istnieją zatem trzy zakresy: pojedyncze zdarzenia, wszystkie zdarzenia do określonego TARGET_ID oraz globalnie wszystkie zdarzenia. Gdy ten sam parametr zostaje przypisany w więcej niż jednym z nich, przy przetwarzaniu zdarzenia używana jest tylko jedna wartość, a kolejność brzmi: event przed config przed set. Rozstrzygający szczegół znajduje się wiersz niżej w dokumentacji referencyjnej: pierwszeństwo to nie nadpisanie.

Wartości parametrów ustawione w jednym zakresie nie zmieniają wartości ustawionych dla tego samego parametru w innym zakresie.

W udokumentowanym przykładzie campaign_id zostaje przypisany globalnie jako '1234', a następnie jako 'ABCD' w wywołaniu config; potem wartość globalna nadal wynosi '1234'. Zakresy zachowują swoje wartości obok siebie, a hierarchia rozstrzyga dopiero w momencie przetwarzania, która z nich obowiązuje. Połączenie obu reguł prowadzi do konsekwencji, której dokumentacja nie wypowiada wprost: wywołanie set wydane po config nie wypiera wartości, jaką config już zajmuje dla danego celu, i działa dla parametrów pozostawionych przez config nietkniętymi.

W kwestii powtórzeń dokumentacja jest jednoznaczna: config należy wywoływać raz na Google Tag, a każde kolejne wywołanie powinno korzystać z set. Zaleca też config lub event zamiast set wszędzie, gdzie to możliwe, co dotyczy zwłaszcza własnych parametrów zdarzeń, ponieważ set może nie przekazywać ich niezawodnie do wszystkich strumieni pomiarowych Google Analytics. Dla udokumentowanych parametrów globalnych, takich jak user_id, page_title czy currency, set jest narzędziem przewidzianym.

Przypadek szczegółowo: późne przekazanie User ID

User ID to samodzielnie przydzielane identyfikatory poszczególnych użytkowników; konsekwentne ich przypisywanie należy do operatora, zwykle przy logowaniu. Tam, gdzie identyfikator jest znany już w momencie renderowania, może podróżować wewnątrz wywołania config. Tam, gdzie staje się znany dopiero po załadowaniu strony, gtag('set') jest drogą udokumentowaną. Snippet na stronie pozostaje dokładnie taki, jak został zainstalowany.

<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
</script>

Po nadejściu odpowiedzi logowania wystarczy jedno polecenie. Bez drugiego config, bez drugiego snippetu, bez przeładowania.

fetch('/api/session')
  .then(function (response) { return response.json(); })
  .then(function (session) {
    if (session.analyticsId) {
      gtag('set', { 'user_id': session.analyticsId });
    }
    gtag('event', 'login', { 'method': 'password' });
  });

To, co dzieje się dalej, rozdziela się między przeglądarkę a stronę przetwarzania. W przeglądarce efekt zaczyna się w momencie wywołania i trwa do końca strony. Każde zdarzenie wysłane po poleceniu set niesie user_id; żadne zdarzenie wysłane wcześniej go nie niesie. Sformułowanie z dokumentacji — parametry powiązane z każdym kolejnym zdarzeniem na stronie — ogranicza efekt do przodu w czasie oraz do bieżącego dokumentu. Klasyczna witryna wielostronicowa wydaje więc to polecenie ponownie przy każdym załadowaniu strony; aplikacja single-page wydaje je raz na czas życia dokumentu.

Po stronie przetwarzania wcześniejsze zdarzenia nie przepadają. Analytics wiąże zdarzenia wysłane przed ustawieniem User ID z tym User ID. Udokumentowany przykład prowadzi przez sesję rozpoczętą bez zalogowania: zdarzenie 1 i zdarzenie 2 nie niosą identyfikatora, użytkownik się loguje, następuje zdarzenie 3 — a potem zdarzenia 1, 2 i 3 są powiązane z identyfikatorem tego użytkownika. Obowiązują dwie granice. Powiązanie opisano w obrębie sesji i nie sięga ono wstecz do danych zebranych, zanim implementacja istniała; takie dane nie są przetwarzane ponownie. Czy obejmuje ono wcześniejsze, już zamknięte sesje na tym samym urządzeniu, nie zostało podane w źródłach pierwotnych.

Wylogowanie jest odbiciem lustrzanym. Wartość zostaje ustawiona na null — nie na pusty ciąg, nie na spację, nie na ciąg "null".

gtag('set', { 'user_id': null });

Analytics przestaje wtedy wiązać kolejne zdarzenia z tym User ID: w udokumentowanym przykładzie zdarzenia od 1 do 3 pozostają powiązane, a zdarzenie 4 nie. Ponowne zalogowanie tym samym identyfikatorem w obrębie tej samej sesji wznawia powiązanie.

Parametr update: scalanie zamiast ponownej inicjalizacji

Polecenie set odpowiada na jedno pytanie: która wartość ma odtąd
towarzyszyć wszystkiemu, co strona wysyła. Drugie, węższe narzędzie odpowiada na
inne: jak zmienić istniejącą konfigurację bez skutków ubocznych świeżego
wywołania config. Tym narzędziem jest parametr update,
przekazywany wewnątrz samego config.

Ustawiony na true parametr update scala nowe lub zmienione parametry z istniejącą konfiguracją Google tag, ale nie wysyła dla tej aktualizacji zdarzenia page_view. Stosuje się to zwykle w aplikacjach jednostronicowych, aby aktualizować parametry bez ponownej inicjalizacji tagu.

Pole jest wartością logiczną i domyślnie ma false. Właśnie ta
wartość domyślna tłumaczy zdublowane trafienie z poprzedniej sekcji: bez
update wywołanie liczy się jako świeża konfiguracja, a świeża
konfiguracja wysyła page_view.

gtag('config', 'G-XXXXXXXXXX', {
  'update': true,
  'page_location': 'https://example.com/new-page'
});

Od set odróżniają to dwie rzeczy. Pierwsza to zasięg:
update scala z konfiguracją jednego wskazanego celu, podczas gdy
set przypisuje globalnie dla każdego kolejnego zdarzenia i każdego
celu. Druga to zamiar: update poprawia to, co tag już przechowuje,
natomiast set dokłada wartość obok, nie naruszając tego, co zajmuje
config.

Wybór jest zatem dość jasny. User ID przychodzące po zalogowaniu należy do
set — jest globalną właściwością wszystkiego, co następuje. Zmiana
trasy w aplikacji jednostronicowej należy do config z
update ustawionym na true, ponieważ
page_location i page_title są konfiguracją tego jednego
strumienia, a towarzyszący im page_view lepiej wysłać świadomie niż
mimochodem.

Droga przez Google Tag Manager

Tag Manager i gtag.js dzielą jeden globalny obiekt window.dataLayer; na stronę obsługiwany jest tylko jeden taki obiekt, a gtag() jest wrapperem, który wpycha do niego swoje argumenty. Google Tag wdrożony przez GTM przetwarza również polecenia gtag() ze strony, obok ustawień skonfigurowanych w interfejsie. Dla wspólnego kontekstu kilku Google Tags strona pomocy GTM wskazuje gtag.js w samej witrynie — z zastrzeżeniem, że parametry globalne są odczytywane przez wszystkie Google Tags w witrynie i powinny nieść wyłącznie dane niewrażliwe.

Czego interfejs GTM nie oferuje, to gotowego typu tagu dla późnego set. Zmienna Configuration settings ustawia parametry ładowane wraz z Google Tag — mechanizm z czasu ładowania; zmienna Event settings dodaje parametry per zdarzenie. Żadna z nich nie aktualizuje Google Tag, który już działa. Odpowiednik po stronie kontenera leży o poziom niżej niż interfejs, w Custom Templates API: gtagSet(object) wpycha polecenie gtag set do data layer, do przetworzenia, gdy tylko bieżące zdarzenie i wywołane przez nie tagi się zakończą, a dokumentacja gwarantuje, że ta aktualizacja zostanie obsłużona w kontenerze przed elementami już oczekującymi w data layer. Droga jest zatem udokumentowana; brakuje jedynie wstępnie skonfigurowanego typu tagu, wobec czego aktualizacja przebiega przez własny szablon. Spakowany tag o takim zachowaniu nie jest opisany w przejrzanej tu dokumentacji, co stanowi ustalenie negatywne, a nie wyraźne wykluczenie ze strony Google.

Kolejka jest tym, co dzieli obie ścieżki. Tag Manager przetwarza komunikaty first in, first out, po jednym naraz, w kolejności otrzymania. Wywołanie gtag() lub dataLayer.push() z kodu strony albo z tagu Custom HTML trafia do kolejki za wszystkimi oczekującymi komunikatami, a dostępność zaktualizowanych wartości dla następnego zdarzenia nie jest gwarantowana; to samo dotyczy zwykłego pushu do data layer z kodu szablonu. Dwa dedykowane API szablonów stanowią udokumentowany wyjątek: gtagSet i pokrewne updateConsentState mają gwarancję przetworzenia w kontenerze przed czymkolwiek, co czeka w kolejce data layer. Ograniczeniem nie jest więc kontener jako taki, lecz wybrana przez niego droga — surowy push nie niesie gwarancji kolejności, API szablonów tak.

Ponowne uruchomienie Google Tag w celu wstrzyknięcia identyfikatora jest niewłaściwą dźwignią również z drugiego powodu. Polecenie config inicjuje w niektórych produktach zdarzenie pageview, w Google Analytics wysyła page_view przy ładowaniu tagu, a dwukrotne skonfigurowanie tego samego Google Tag na jednej stronie może prowadzić do zduplikowanych danych albo pomieszanych ustawień. To, że drugie uruchomienie Google Tag z GTM wytwarza drugi page_view, jest uzasadnionym wnioskiem z tych elementów, a nie stwierdzeniem Google dla tego typu tagu. Tłumienie jest możliwe przez send_page_view: false — w snippecie, globalnie przez set albo w zmiennej Configuration settings — ale to ustawienie nie przenosi się między stronami.

W obraz wpisuje się zapowiedź datowana na 20 maja 2026: nowe snippety wdrożeniowe mają być jednolite i zrezygnują z polecenia gtag config, a inicjalizacja będzie konfigurowana przez regułę gtm init, która może też zaczekać na polecenie config, aby zachować starszą konfigurację. Nic nie zmienia się automatycznie, zachowanie na stronie opisano jako nienaruszone, a przykład instalacji w dokumentacji dla programistów nadal pokazuje gtag('config', 'TAG_ID');.

Przypadek pokrewny: Consent Mode

Consent Mode ma ten sam kształt — wartość nieznana w chwili ładowania tagu, przekazana później bez przeładowywania czegokolwiek — z innym celem i ostrzejszym porządkiem. Domyślnie żadne wartości consent mode nie są ustawione. Polecenie default musi wykonać się na każdej stronie przed jakimkolwiek poleceniem wysyłającym dane pomiarowe; wywołane poza kolejnością, wartości domyślne nie działają.

gtag('consent', 'default', {
  'ad_storage': 'denied',
  'ad_user_data': 'denied',
  'ad_personalization': 'denied',
  'analytics_storage': 'denied',
  'wait_for_update': 500
});

Wartość wait_for_update w milisekundach steruje tym, jak długo tag czeka przed wysłaniem danych, co ma znaczenie dla rozwiązań zgody ładowanych asynchronicznie; tam, gdzie w grę wchodzą żądania sieciowe, sugerowane jest co najmniej 500 milisekund. Wartości domyślne można różnicować regionalnie zgodnie z ISO 3166-2, przy czym wygrywa region bardziej szczegółowy.

Aktualizacja następuje na stronie, na której zapada decyzja, przed jakimkolwiek przejściem na inną stronę, ponieważ Consent Mode sam nie przechowuje wyboru.

gtag('consent', 'update', {
  'ad_storage': 'granted',
  'ad_user_data': 'granted',
  'ad_personalization': 'granted',
  'analytics_storage': 'granted'
});

Przeładowanie nie jest wymagane, a sama zmiana stanu wytwarza sygnał: consent state pings są wysyłane z każdej strony, na której consent mode jest włączony, a dla części tagów są dodatkowo wyzwalane, gdy stan zmienia się z denied na granted. W implementacji zaawansowanej tagi ładują się natychmiast i przy braku zgody wysyłają pomiary bez cookies. Wewnątrz szablonów Tag Managera polecenia gtag consent wyraźnie nie należy używać — API updateConsentState istnieje po to, aby aktualizacje zgody były przetwarzane przed elementami czekającymi w data layer, czyli z tą samą gwarancją kolejności, jaką gtagSet niesie dla parametrów.

Pułapki i kontrole

  • Zakres, nie nadpisanie. Późny set nie przepisuje tego, co zawiera już config albo parametr na poziomie zdarzenia. Tam, gdzie wartość ma wygrać, jej miejsce jest w wyżej stojącym zakresie.
  • Granice stron i kolejność. set sięga wyłącznie do przodu, w obrębie bieżącego dokumentu; nawigacje renderowane po stronie serwera wymagają ponownego wydania polecenia. Snippet musi znaleźć się powyżej poleceń zdarzeń, a set należy do miejsca powyżej config tam, gdzie kilka identyfikatorów tagów ma odziedziczyć wartości.
  • Droga przez kontener. Wewnątrz GTM gwarancja kolejności przynależy do API szablonów. Późna wartość wypchnięta z tagu Custom HTML konkuruje z kolejką; ta sama wartość przekazana przez gtagSet we własnym szablonie — nie.
  • Higiena identyfikatora. Wartość User ID jest ograniczona do 256 znaków, wyłącznie w UTF-8 według dokumentacji Measurement Protocol, i nie może zawierać informacji, na podstawie których strona trzecia mogłaby ustalić tożsamość użytkownika; jako niedopuszczalne wymieniono adresy e-mail i prywatne numery telefonów komórkowych. Czy kwalifikuje się pochodna zahaszowana, nie da się rozstrzygnąć na podstawie źródeł pierwotnych.
  • Bez custom dimension na identyfikatorze. Rejestrowanie user_id jako custom dimension jest odradzane ze względu na bardzo dużą liczbę różnych wartości.
  • Reporting identity. Raportowanie oparte na urządzeniu nie pokazuje analizy User-ID; wymagane jest Blended albo Observed. Wybór nie wpływa ani na zbieranie, ani na przetwarzanie danych.
  • Weryfikacja. gtag('get', …) odczytuje client_id, session_id, session_number i gclid, a wartość przypisana jednemu z tych pól przez set ma pierwszeństwo przed wyprowadzoną wewnętrznie. Tag Assistant raportuje zgodę w osobnych kolumnach On-page Default i On-page Update.

Podsumowanie

Bilans jest nierówny. Ponowne skonfigurowanie załadowanego Google Tag w celu dołączenia jednej wartości kosztuje zdublowaną inicjalizację, grozi pomieszanymi ustawieniami oraz drugim page_view, a nie przynosi niczego, czego nie dostarcza pojedyncze polecenie set. W przypadku User ID rachunek jest jeszcze wyraźniejszy, ponieważ strona przetwarzania domyka lukę pozostawioną otwartą przez przeglądarkę: zdarzenia wysłane wcześniej w obrębie sesji zostają potem powiązane z identyfikatorem, więc hity sprzed logowania nie są poświęcone.

Czego to podejście nie robi, to przekraczanie granic, których nigdy mu nie nadano. Nie przetrwa przejścia na inną stronę, nie przebije wartości trzymanej już przez wyższy zakres i nie sięgnie wstecz do danych zebranych, zanim implementacja istniała. Consent Mode pokazuje ten sam wzorzec z innej strony: udokumentowany stan domyślny, późniejsza aktualizacja na tej samej stronie, zmiana stanu docierająca do tagów bez przeładowania. Tam, gdzie tagiem zarządza kontener, kolejka jest ograniczeniem, wokół którego trzeba projektować, a gtagSet wraz z updateConsentState stanowią udokumentowane od niego zwolnienie — za cenę własnego szablonu. Zapowiedziane ujednolicenie Google Tag i Tag Managera, w sierpniu 2026 wciąż w czasie przyszłym, warto obserwować, zamiast je wyprzedzać.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *

ALL ARTICLES & CATEGORIES

CCTV

Śledź tę kategorię przez RSS

Data Privacy

Śledź tę kategorię przez RSS

Digital Analytics

Śledź tę kategorię przez RSS

Digital Marketing

Śledź tę kategorię przez RSS

IT & Networks

Śledź tę kategorię przez RSS

Raspberry Pi

Śledź tę kategorię przez RSS

Smart Home

Śledź tę kategorię przez RSS

Tworzenie stron internetowych

Śledź tę kategorię przez RSS

Wordpress Hacks

Śledź tę kategorię przez RSS