{"id":455,"date":"2026-09-09T18:40:00","date_gmt":"2026-09-09T16:40:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/?p=455"},"modified":"2026-10-24T01:50:52","modified_gmt":"2026-10-23T23:50:52","slug":"sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/","title":{"rendered":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych"},"content":{"rendered":"<p>Aplikacja SPA aktualizuje widoki bez pobierania nowego dokumentu HTML przy ka\u017cdej zmianie trasy. Zdarzenia DOM-ready i window-load opisuj\u0105 wi\u0119c pocz\u0105tkowe \u0142adowanie, a nie p\u00f3\u017aniejsze widoki produkt\u00f3w czy dzia\u0142ania w kasie. Wiarygodny pomiar GA4 e-commerce wymaga jasnego zdarzenia aplikacji, kompletnych danych i osobnej regu\u0142y ograniczaj\u0105cej duplikaty.<\/p>\n<h2>1. Nawigacja, gotowo\u015b\u0107 danych i dzia\u0142anie biznesowe<\/h2>\n<p>Zmiana historii przegl\u0105darki potwierdza nawigacj\u0119, lecz nie zako\u0144czenie zapytania o produkt lub koszyk. Widok produktu powinien by\u0107 zg\u0142aszany po przygotowaniu potrzebnych danych widoku, <code>add_to_cart<\/code> po udanym dodaniu, a <code>purchase<\/code> po osi\u0105gni\u0119ciu ustalonego stanu zako\u0144czonego zam\u00f3wienia.<\/p>\n<p>GTM utrzymuje wewn\u0119trzny model danych. Zale\u017cnie od konfiguracji zmiennych kolejne aktualizacje mog\u0105 zachowywa\u0107 lub scala\u0107 wcze\u015bniejsze warto\u015bci zagnie\u017cd\u017cone. Wyczyszczenie <code>ecommerce<\/code> zapobiega przenoszeniu starych p\u00f3l. Nie usuwa jednak tablicy dataLayer ani ca\u0142ego stanu GTM. Brak resetu nie oznacza te\u017c automatycznego zdublowania ka\u017cdego produktu.<\/p>\n<figure class=\"lw-diagram\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/dia-455-spa-20261024.png\" width=\"1120\" height=\"580\" alt=\"Kolejno\u015b\u0107 zdarzenia SPA po przygotowaniu danych\"><figcaption>Po zako\u0144czonej akcji powstaj\u0105 kopia danych, reset i jedna wiadomo\u015b\u0107 zdarzenia. Zgody i duplikaty wymagaj\u0105 osobnej kontroli.<\/figcaption><\/figure>\n<h2>2. Reset i wsp\u00f3lna wiadomo\u015b\u0107 zdarzenia z danymi<\/h2>\n<p>Przyk\u0142ady GTM Google czyszcz\u0105 <code>ecommerce<\/code> przed nast\u0119pnym zdarzeniem e-commerce. Nazwa zdarzenia i komplet danych nale\u017c\u0105 do tej samej kolejnej wiadomo\u015bci. Dzi\u0119ki temu wyzwalacz odczytuje warto\u015bci danego zdarzenia. GTM przetwarza wiadomo\u015bci w kolejno\u015bci nadej\u015bcia. Ten wzorzec porz\u0105dkuje dane, ale nie gwarantuje bezpiecze\u0144stwa w\u0105tkowego, dostarczenia ani ca\u0142kowitego wyeliminowania wy\u015bcig\u00f3w.<\/p>\n<p>Poni\u017csza funkcja JavaScript kopiuje dane przed umieszczeniem w kolejce. P\u00f3\u017aniejsze zmiany aplikacji nie zmieniaj\u0105 zg\u0142oszonej kopii. Przyk\u0142ad wymaga obs\u0142ugi <code>structuredClone<\/code> w przegl\u0105darce i zwraca false podczas renderowania serwerowego lub po b\u0142\u0119dzie kopiowania.<\/p>\n<pre><code>function dispatchGa4EcommerceEvent(eventName, ecommercePayload) {\n  if (typeof window === &#x27;undefined&#x27;) return false;\n  if (typeof eventName !== &#x27;string&#x27; || !eventName) return false;\n  if (!ecommercePayload || !Array.isArray(ecommercePayload.items)) return false;\n  if (typeof structuredClone !== &#x27;function&#x27;) return false;\n\n  let snapshot;\n  try {\n    snapshot = structuredClone(ecommercePayload);\n  } catch (error) {\n    return false;\n  }\n  window.dataLayer = window.dataLayer || [];\n  window.dataLayer.push({ ecommerce: null });\n  window.dataLayer.push({ event: eventName, ecommerce: snapshot });\n  return true;\n}\n<\/code><\/pre>\n<p>True oznacza wy\u0142\u0105cznie umieszczenie dw\u00f3ch wiadomo\u015bci w kolejce, a nie odbi\u00f3r lub akceptacj\u0119 przez GA4. Funkcja nie sprawdza ca\u0142ego schematu GA4 ani zg\u00f3d, nie czeka na odpowiedzi API i nie usuwa duplikat\u00f3w zakup\u00f3w. Nazwy zdarze\u0144, produkty, liczbowe ceny i ilo\u015bci, waluta oraz identyfikatory transakcji wymagaj\u0105 kontroli przed wywo\u0142aniem. Aplikacja musi obs\u0142u\u017cy\u0107 b\u0142\u0119dy i wynik false.<\/p>\n<h2>3. Powi\u0105zanie zdarze\u0144 aplikacji z GTM<\/h2>\n<ol>\n<li>Wyzwalacz Custom Event odpowiada konkretnej nazwie, np. <code>add_to_cart<\/code> lub <code>purchase<\/code>. Zmiana trasy i All Pages nie zast\u0119puj\u0105 zako\u0144czonego dzia\u0142ania biznesowego.<\/li>\n<li>Tag zdarzenia GA4 u\u017cywa w\u0142a\u015bciwej nazwy i wysy\u0142a dane e-commerce z Data Layer. Osobna zmienna ca\u0142ego obiektu <code>ecommerce<\/code> pomaga przy w\u0142asnym mapowaniu lub kontroli, ale nie jest zawsze potrzebna przy bezpo\u015brednim odczycie z Data Layer.<\/li>\n<li>Domy\u015blny stan zg\u00f3d musi by\u0107 ustalony przed tagami pomiarowymi. Szablony CMP powinny korzysta\u0107 z GTM Consent APIs do warto\u015bci domy\u015blnych i aktualizacji. Sekwencjonowanie tag\u00f3w nie zast\u0119puje rzeczywistej decyzji o zgodzie ani wymaganej obs\u0142ugi zg\u00f3d.<\/li>\n<li>Dozwolony User-ID powinien by\u0107 dost\u0119pny przed zdarzeniem, je\u015bli jest potrzebny, i usuwany w odpowiednim momencie, np. po wylogowaniu. Pole nie mo\u017ce zawiera\u0107 adresu e-mail ani innych bezpo\u015brednio identyfikuj\u0105cych danych.<\/li>\n<\/ol>\n<h2>4. Efekty i powtarzaj\u0105ce si\u0119 zdarzenia<\/h2>\n<p>React <code>useEffect<\/code> uruchamia si\u0119 po zatwierdzeniu renderowania, ale nie czeka na wszystkie zapytania asynchroniczne. Zmiany koszyka cz\u0119sto lepiej zg\u0142asza\u0107 z obs\u0142ugi zako\u0144czonej powodzeniem operacji. Efekty zwi\u0105zane z widokiem wymagaj\u0105 jawnego warunku gotowo\u015bci i ochrony przed sp\u00f3\u017anionymi odpowiedziami dla opuszczonej trasy.<\/p>\n<p>React por\u00f3wnuje zale\u017cno\u015bci za pomoc\u0105 <code>Object.is<\/code>. Nowe referencje obiekt\u00f3w mog\u0105 ponownie uruchamia\u0107 efekt. Strict Mode mo\u017ce dodatkowo wykona\u0107 cykl setup\/cleanup tylko w \u015brodowisku deweloperskim. Wy\u0142\u0105czenie tego trybu ukrywa przydatny test, zamiast naprawia\u0107 duplikaty. Ponowne montowanie, ponowienia i wielokrotna rejestracja handler\u00f3w wymagaj\u0105 kontroli tak\u017ce w produkcji.<\/p>\n<p>Zakupy potrzebuj\u0105 stabilnego, niepustego <code>transaction_id<\/code>, unikalnego dla zam\u00f3wienia. GA4 dokumentuje deduplikacj\u0119 zakup\u00f3w przez identyfikatory transakcji w strumieniach webowych. Znacznik w <code>sessionStorage<\/code> mo\u017ce ograniczy\u0107 powt\u00f3rzenia w jednej karcie, ale nie jest rejestrem mi\u0119dzy urz\u0105dzeniami ani potwierdzeniem dostarczenia. Znacznik zapisany przed nieudan\u0105 wysy\u0142k\u0105 mo\u017ce tak\u017ce zablokowa\u0107 p\u00f3\u017aniejsz\u0105 poprawn\u0105 pr\u00f3b\u0119.<\/p>\n<h2>5. Jedna zaplanowana \u015bcie\u017cka pomiaru ods\u0142on<\/h2>\n<p>Automatyczne ods\u0142ony oparte na historii mog\u0105 pasowa\u0107 do SPA, je\u015bli widoki i metadane s\u0105 poprawne. Alternatyw\u0105 s\u0105 ods\u0142ony r\u0119czne. Je\u015bli aplikacja samodzielnie zg\u0142asza pierwsz\u0105 ods\u0142on\u0119, <code>send_page_view: false<\/code> wy\u0142\u0105cza pocz\u0105tkowe zdarzenie tagu Google. Pomiar rozszerzony oparty na historii jest osobnym ustawieniem i r\u00f3wnie\u017c wymaga wy\u0142\u0105czenia przy r\u0119cznej obs\u0142udze tych przej\u015b\u0107.<\/p>\n<p>Nie ka\u017cda zmiana historii odpowiada nowemu istotnemu ekranowi. Plan pomiaru powinien okre\u015bla\u0107 liczone przej\u015bcia oraz aktualny tytu\u0142, pe\u0142ny URL i w\u0142a\u015bciwy referrer poprzedniego widoku. Kontrola \u0142adunk\u00f3w sieciowych i DebugView powinna obejmowa\u0107 pierwsze wej\u015bcie, nawigacj\u0119 wstecz\/dalej i widoki asynchroniczne. Samo liczenie adres\u00f3w \u017c\u0105da\u0144 nie wystarcza, poniewa\u017c zdarzenia mog\u0105 by\u0107 grupowane lub przesy\u0142ane przez proxy.<\/p>\n<div class=\"lw-faq\">\n<h2>Pytania i odpowiedzi<\/h2>\n<h3>Czy ecommerce: null uruchamia tag purchase?<\/h3>\n<p>Pokazany reset nie zawiera klucza event i sam nie uruchamia tagu Custom Event. Czy\u015bci tylko ga\u0142\u0105\u017a ecommerce. W\u0142asny kod obserwuj\u0105cy wywo\u0142ania push pozostaje poza tym stwierdzeniem.<\/p>\n<h3>Czy wzorzec gwarantuje prawid\u0142owy przych\u00f3d?<\/h3>\n<p>Nie. Testy musz\u0105 obejmowa\u0107 wielokrotne klikni\u0119cia, b\u0142\u0119dy API, zmian\u0119 trasy podczas \u0142adowania, od\u015bwie\u017cenie potwierdzenia, zmian\u0119 zg\u00f3d, b\u0142\u0119dne dane i blokad\u0119 wysy\u0142ki. Build produkcyjny i uzgodnienie z zako\u0144czonymi zam\u00f3wieniami uzupe\u0142niaj\u0105 kontrol\u0119 licznik\u00f3w w \u015brodowisku deweloperskim.<\/p>\n<\/div>\n<div class=\"lw-quellen\">\n<h2>\u0179r\u00f3d\u0142a<\/h2>\n<ul>\n<li><a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/reference\/events\" target=\"_blank\" rel=\"noopener noreferrer\">Google Analytics 4 event reference<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Web Docs<\/a><\/li>\n<li><a href=\"https:\/\/developers.google.com\/tag-platform\/tag-manager\/datalayer\" target=\"_blank\" rel=\"noopener noreferrer\">FIFO processing, event bundling and Consent APIs<\/a><\/li>\n<li><a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/single-page-applications\" target=\"_blank\" rel=\"noopener noreferrer\">History\/custom-event pageviews and DebugView<\/a><\/li>\n<li><a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/views\" target=\"_blank\" rel=\"noopener noreferrer\">Initial send_page_view versus separate history measurement<\/a><\/li>\n<li><a href=\"https:\/\/developers.google.com\/tag-platform\/security\/guides\/consent\" target=\"_blank\" rel=\"noopener noreferrer\">Consent defaults and updates<\/a><\/li>\n<li><a href=\"https:\/\/support.google.com\/analytics\/answer\/12313109\" target=\"_blank\" rel=\"noopener noreferrer\">Purchase transaction-ID deduplication, web streams and empty IDs<\/a><\/li>\n<li><a href=\"https:\/\/react.dev\/reference\/react\/useEffect\" target=\"_blank\" rel=\"noopener noreferrer\">Commit timing and Object.is dependencies<\/a><\/li>\n<li><a href=\"https:\/\/react.dev\/reference\/react\/StrictMode\" target=\"_blank\" rel=\"noopener noreferrer\">Development-only extra effect cycle<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/structuredClone\" target=\"_blank\" rel=\"noopener noreferrer\">Deep-copy behavior and failures<\/a><\/li>\n<li><a href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/ga4-ecommerce-item-array-validator\/\" target=\"_blank\" rel=\"noopener noreferrer\">Local tool claims checked against authoritative Pi WordPress content and items-core.js<\/a><\/li>\n<\/ul>\n<\/div>\n<p><!-- lw-items-practice:start --><\/p>\n<h2>Kontrola praktyczna: tablica items przed wys\u0142aniem<\/h2>\n<p>Zdarzenie e-commerce mo\u017ce dotrze\u0107 do Google mimo b\u0142\u0119dnych danych produkt\u00f3w. <a href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/ga4-ecommerce-item-array-validator\/\">GA4 E-Commerce Item Array Validator<\/a> sprawdza tablic\u0119 JSON lokalnie i wskazuje konkretne pole, na przyk\u0142ad <code>items[0].price<\/code>. Cena zapisana w cudzys\u0142owie, taka jak <code>\"12.50\"<\/code>, jest zg\u0142aszana jako b\u0142\u0105d typu zamiast automatycznej zamiany na liczb\u0119.<\/p>\n<p>Kontrola rozr\u00f3\u017cnia b\u0142\u0119dy i uwagi. Powt\u00f3rzone identyfikatory produkt\u00f3w mog\u0105 oznacza\u0107 warianty i nie dowodz\u0105 podw\u00f3jnego zarejestrowania zakup\u00f3w. Brak ceny uniemo\u017cliwia obliczenie pe\u0142nej warto\u015bci. Ilo\u015b\u0107 zero pozostaje zerem, a brak ilo\u015bci oznacza jeden. Suma uwzgl\u0119dnia cen\u0119 po rabacie, bez podatku i wysy\u0142ki. Waluta i identyfikator transakcji na poziomie zdarzenia nadal wymagaj\u0105 osobnej kontroli.<\/p>\n<p>Przydatny przebieg pracy \u0142\u0105czy kontrol\u0119 tablicy, sprawdzenie rzeczywistego \u017c\u0105dania sieciowego i p\u00f3\u017aniejsze uzgodnienie zam\u00f3wie\u0144. Poprawna struktura nie dowodzi poprawnego zbierania ani raportowania danych. Podstaw\u0105 s\u0105 <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/ecommerce\">przewodnik Google po e-commerce<\/a> oraz <a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/reference\/events#purchase\">dokumentacja purchase<\/a>.<\/p>\n<p><!-- lw-items-practice:end --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Techniczny przewodnik wdro\u017cenia deterministycznego \u015bledzenia e-commerce GA4 bez zjawiska wy\u015bcigu w aplikacjach SPA (React, Vue, Next.js).<\/p>\n","protected":false},"author":1,"featured_media":23081,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[117],"tags":[92113,92100,92133,92271,92499,92044,92238],"class_list":["post-455","post","type-post","status-publish","format-standard","hentry","category-tutorials-pl","tag-e-commerce-pl","tag-google-analytics-4-pl","tag-google-tag-manager-pl","tag-javascript-pl","tag-single-page-application-pl","tag-tracking-pl","tag-tutorial-pl"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-09T16:40:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-23T23:50:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-455-ga4-e-commerce-enhanced-tracking-spa-g.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych\",\"datePublished\":\"2026-09-09T16:40:00+00:00\",\"dateModified\":\"2026-10-23T23:50:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/\"},\"wordCount\":1099,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-455-spa-title-20261024-dunkel.png\",\"keywords\":[\"E-Commerce\",\"Google Analytics 4\",\"Google Tag Manager\",\"JavaScript\",\"Single-Page Application\",\"Tracking\",\"Tutorial\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/\",\"name\":\"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-455-spa-title-20261024-dunkel.png\",\"datePublished\":\"2026-09-09T16:40:00+00:00\",\"dateModified\":\"2026-10-23T23:50:52+00:00\",\"description\":\"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-455-spa-title-20261024-dunkel.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/hero-455-spa-title-20261024-dunkel.png\",\"width\":1200,\"height\":630,\"caption\":\"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/digital-analytics-pl\\\/tutorials-pl\\\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik","description":"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/","og_locale":"en_US","og_type":"article","og_title":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik","og_description":"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-09-09T16:40:00+00:00","article_modified_time":"2026-10-23T23:50:52+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/09\/hero-455-ga4-e-commerce-enhanced-tracking-spa-g.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych","datePublished":"2026-09-09T16:40:00+00:00","dateModified":"2026-10-23T23:50:52+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/"},"wordCount":1099,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-455-spa-title-20261024-dunkel.png","keywords":["E-Commerce","Google Analytics 4","Google Tag Manager","JavaScript","Single-Page Application","Tracking","Tutorial"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/","name":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-455-spa-title-20261024-dunkel.png","datePublished":"2026-09-09T16:40:00+00:00","dateModified":"2026-10-23T23:50:52+00:00","description":"E-commerce GA4 w aplikacjach SPA: moment aktualizacji dataLayer, wyzwalacze GTM i kontrola tablicy items przed wys\u0142aniem.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-455-spa-title-20261024-dunkel.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/hero-455-spa-title-20261024-dunkel.png","width":1200,"height":630,"caption":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/digital-analytics-pl\/tutorials-pl\/sledzenie-e-commerce-ga4-w-aplikacjach-spa-bez-zjawiska-race-condition\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"GA4 e-commerce w aplikacjach SPA: koordynacja zdarze\u0144 i danych"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/455","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=455"}],"version-history":[{"count":9,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/455\/revisions"}],"predecessor-version":[{"id":23083,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/455\/revisions\/23083"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/23081"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}