Zdarzenie purchase nie dochodzi, a przychód w GA4 nie zgadza się z tym, co widzisz w PrestaShop? Najczęściej problem nie leży w samym GA4, tylko w tym, że zdarzenia wysyła więcej niż jedno miejsce albo wysyła je miejsce, które nie ma dostępu do danych zamówienia. Ta część artykułu jest organizacyjna: dostajesz listę typowych błędów wraz ze sposobem ich wykrycia, checklistę wdrożeniową i pytania, które najczęściej padają przy audytach. Część techniczna — mapa zdarzeń z przypisaniem do hooków i poprawki w kontrolerze zamówienia — jest w dalszych sekcjach. Jeśli po drodze okaże się, że problem jest szerszy niż sam tag, punktem wyjścia mogą być integracje PrestaShop i dokumentacja deweloperska PrestaShop.

5 objawów, że integracja PrestaShop z GA4 jest zepsuta

Zanim zaczniesz grzebać w szablonie, zrób autodiagnozę. Poniższe pięć objawów pokrywa większość przypadków, z którymi mierzymy się przy audytach sklepów na PrestaShop.

ObjawNajbardziej prawdopodobna przyczynaGdzie szukać poprawki
Brak purchase mimo zamówieńBrak danych zamówienia w momencie odpalenia tagu lub przekierowanie po płatnościMapa zdarzeń — purchase
Przychód w GA4 wyższy niż w PrestaShopPodwójne purchase (moduł + GTM) albo zamówienia anulowane wliczone w valueKonflikt implementacji: jedno źródło prawdy
Brak add_to_cart przy koszyku AJAXBrak nasłuchu na odpowiedź kontrolera koszyka — tag tylko na page_viewMapa zdarzeń — add_to_cart
(not set) w item_idBrak reference i id_product_attribute w tablicy itemsMapa zdarzeń — struktura items
page_view liczone podwójnieGTM i moduł Google Analytics aktywne jednocześnieKonflikt implementacji: jedno źródło prawdy

Najczęstsza przyczyna: stary UA, GTM i moduł gtag jednocześnie

Zasada jest jedna: zdarzenia wysyła dokładnie jedno miejsce. GTM może być warstwą pośrednią — zbiera dataLayer i wysyła dalej — ale nie drugim nadawcą obok modułu.

Jak znaleźć pozostałości starych wdrożeń:

Trzy warianty wdrożenia i ich konsekwencje:

Pułapka, o której mało kto pamięta: moduł Google Analytics po aktualizacji PrestaShop potrafi włączyć się ponownie i wysyłać page_view niezależnie od GTM. Po każdej aktualizacji sprawdź jego status — PrestaShop 9.2: co sprawdzić przed aktualizacją sklepu to dobre miejsce, żeby zacząć.

Mapa zdarzeń: co musi wysyłać sklep i z którego miejsca w PrestaShop

Poniższa tabela to punkt odniesienia do weryfikacji wdrożenia. Nazwy hooków i kontrolerów pochodzą z dokumentacji dla deweloperów PrestaShop — warto sprawdzić je w wersji, na której stoi Twój sklep, bo rejestr hooków zmienia się między 1.7, 8 i 9.

Zdarzenie GA4Miejsce w PrestaShopUwagi wdrożeniowe
view_item_listCategoryController, kontroler wyszukiwania, nowości; hook displayHeaderRaz na widok listy, paginacja bez duplikatów
select_itemKlik w kafelek produktu (JS, delegacja zdarzeń)Nie licz jako view_item
view_itemProductController, hook displayProductAdditionalInfoCena z aktualnej kombinacji, nie z produktu bazowego
add_to_cartKontroler koszyka (AJAX) lub hook actionCartSaveNasłuch na odpowiedź JSON, nie na page_view
remove_from_cartAkcja usuwania w kontrolerze koszyka (AJAX)Również przy zmianie liczby sztuk na 0
begin_checkoutOrderController, wejście na pierwszy krokJedno zdarzenie na sesję checkout
add_shipping_infoOrderController, zmiana opcji dostawy (JS)W checkoutcie 1.7/8 nie ma osobnego kontrolera — tylko JS
add_payment_infoOrderController, zmiana opcji płatności (JS)Jak wyżej
purchaseOrderConfirmationController oraz hook displayOrderConfirmationBlokada po id_order — odświeżenie strony zdubluje transakcję

Purchase: duplikaty transakcji i zamówienia, które nie dochodzą

Zacznij od rozdzielenia dwóch problemów: zawyżony przychód i brakujące zamówienia mają inne przyczyny. Mieszanie ich w jednym audycie kończy się podwójnym poprawianiem tego samego miejsca.

Duplikaty. Strona potwierdzenia zamówienia to zwykły adres GET z parametrami id_order i key. Klient odświeża ją (F5), wraca przyciskiem „wstecz” z bramki płatności, klika link z maila potwierdzającego, a przeglądarka po restarcie przywraca kartę. Każde z tych zdarzeń uruchamia skrypt purchase od nowa — jeden klient potrafi wygenerować 2–4 transakcje.

Nie zakładaj, że GA4 odrzuci powtórzone zdarzenie po transaction_id. Zabezpieczenie musi być po Twojej stronie: flaga w localStorage lub sessionStorage (klucz typu dd_purchase_ + ID zamówienia) sprawdzana przed każdą wysyłką, albo znacznik w bazie ustawiany przez kontroler. localStorage trzyma dłużej niż sesja, więc wyłapuje też powrót z maila następnego dnia.

Bramki płatności. Przelewy24, PayU i Autopay mają w panelu adres powrotu. Jeśli wskazuje stronę potwierdzenia — dostajesz drugi purchase. Jeśli osobną stronę „dziękujemy” bez kodu trackingowego — nie dostajesz żadnego. Sprawdź w panelu bramki, gdzie realnie wraca klient, i porównaj z tym, co zakłada moduł płatności.

Backstop. Zamówienia, które wypadły (klient zamknął kartę, adblock), dosyłaj przez Measurement Protocol po zmianie statusu na „Płatność zaakceptowana”. Potrzebujesz api_secret, client_id z cookie _ga i tego samego transaction_id. Wysyłka serwerowa jest odporna na blokery skryptów.

Jeśli po audycie okaże się, że purchase odpala kilka modułów naraz, uporządkowanie tego to zwykle część integracji PrestaShop, a nie sama poprawka w szablonie.

Porównanie liczb. Zakres dat 1:1, ta sama strefa czasowa po obu stronach, wykluczone statusy: oczekiwanie na płatność przelewem, anulowane, zwrot. Tolerancja 2–5% jest normalna; powyżej 10% szukaj błędu w skrypcie.

ObjawPrawdopodobna przyczynaZabezpieczenie
Przychód w GA4 wyższy niż w PrestaShopodświeżenie lub powrót na order-confirmationflaga w localStorage po transaction_id
Dokładnie 2× purchase na zamówieniepowrót z bramki na ten sam URLjeden punkt wysyłki, reszta wyłączona
Zamówienia widoczne w sklepie, brak w GA4powrót z bramki na stronę bez kodu trackingowegoMeasurement Protocol po zmianie statusu
Brak purchase tylko przy przelewachstatus „oczekiwanie na płatność” bez wysyłkibackstop serwerowy po akceptacji płatności

PrestaShop 1.7, 8 i 9 oraz motyw classic vs hummingbird — co zmienia wdrożenie

Ten sam plik JS nie zachowa się identycznie na 1.7, 8 i 9 — i nie chodzi tylko o wersję PHP.

Koszyk AJAX. Nie podpinaj wysyłki pod klik w przycisk „Do kosza”. PrestaShop emituje zdarzenia na obiekcie prestashop: prestashop.on('updateCart', function(params){...}) odpala się po dodaniu, zmianie ilości i usunięciu — niezależnie od tego, czy klient kliknął na karcie produktu, w quick view czy w mini-koszyku. W motywie classic nasłuch siedzi w skryptach motywu. Hummingbird ma własne pliki, częściowo bez jQuery: zanim wkleisz stary kod, sprawdź w konsoli, czy zdarzenie faktycznie leci.

Szablony i hooki. Plik potwierdzenia to themes/<motyw>/templates/checkout/order-confirmation.tpl. Hook displayOrderConfirmation dostaje obiekt zamówienia w $params['order'] i działa niezależnie od motywu — to najbezpieczniejsza droga. Część hooków z 1.7 została wycofana lub zmieniła sygnaturę (m.in. displayOrderConfirmation2).

Przed aktualizacją do 9.x. Sprawdź trzy rzeczy: czy moduł analityczny nie został wyłączony jako niekompatybilny, czy snippet GTM nie był wstrzykiwany przez moduł, który po upgrade przestanie działać, oraz czy nowy motyw nie nadpisał customowego head.tpl. Po aktualizacji przejdź całą ścieżkę zakupu na stagingu i porównaj z DebugView. Zanim wejdziesz na produkcję, przejrzyj co sprawdzić przed aktualizacją do PrestaShop 9.2.

Override czy hook. Override szablonu lub klasy kontrolera stosuj tylko wtedy, gdy hook nie ma dostępu do danych, których potrzebujesz. Override w /override/ nie jest przenoszony automatycznie i po aktualizacji potrafi wywalić błąd 500, bo zmieniła się sygnatura metody.

Wersja / motywGdzie szukać emisji updateCartGdzie wstawić purchaseNa co uważać
1.7.x, classicskrypty motywu, prestashop.emit('updateCart')hook displayOrderConfirmationzdarzenie leci też przy zmianie ilości w koszyku
8.x, classicjak w 1.7hook displayOrderConfirmationmoduły analityczne z 1.7 wymagają sprawdzenia kompatybilności
8.x / 9.x, hummingbirdwłasne pliki motywu, część bez jQueryhook, nie wklejka w .tplkod oparty o $ może w ogóle nie wystartować
9.x po aktualizacji——moduły analityczne wyłączone lub nadpisane, nowy head.tpl

Consent Mode v2 to cztery sygnały i warto wiedzieć, co który blokuje:

Kolejność ładowania. Wywołanie gtag('consent','default',{analytics_storage:'denied', ad_storage:'denied', ad_user_data:'denied', ad_personalization:'denied'}) musi wykonać się przed pierwszym hitem i przed wczytaniem GTM. Jeśli banner startuje asynchronicznie i dopiero wtedy ustawia stan, pierwszy page_view albo leci bez zgody, albo przepada. Praktyka: domyślny stan wpisany na sztywno w <head>, banner tylko wywołuje gtag('consent','update',...). Przy wdrożeniach PrestaShop ten fragment często siedzi w module CMP — sprawdź, czy nie ładuje się po tagu Google.

Weryfikacja w DebugView. Wejdź w zakładkę Consent i sprawdź konkretnie purchase: czy w chwili wysyłki analytics_storage ma stan granted. Jeśli update zgody dochodzi po zakupie, zdarzenie poleci jako denied.

Ile tracisz. Podziel liczbę purchase w GA4 przez liczbę zamówień w PrestaShop z tego samego okresu, po wykluczeniu anulowanych. 1000 zamówień i 780 purchase to luka 22% — suma odmów i błędów technicznych. Rozdziel je, mierząc osobno odsetek sesji z odmową.

Modelowanie konwersji. Wymaga ruchu z EEA i progów wolumenowych, których Google nie publikuje. Uzupełnia raporty i konwersje Ads, ale nie naprawi zepsutego skryptu i nie da danych per zamówienie. Przy kilkuset zamówieniach miesięcznie punktem odniesienia powinny być zamówienia z PrestaShop, a GA4 — źródłem trendów.

Weryfikacja: 6 testów, które potwierdzają, że integracja działa

Testy wykonuj zawsze w tej samej kolejności — przed wdrożeniem i po każdym większym narzucie. Inaczej zostaje Ci „wygląda dobrze”, a nie „działa”.

  1. Zamówienie testowe. Włącz w PrestaShop płatność testową (np. „Płatność przy odbiorze” przemianowaną na „TEST” albo moduł czekowy) i złóż zamówienie na dwa produkty z różnych kategorii, w tym jeden z rabatem. Całą ścieżkę przechodzisz w jednej sesji, w trybie incognito, z wyłączonym adblockiem: lista → karta produktu → koszyk → checkout → potwierdzenie. Zanotuj godzinę — w GA4 Realtime zamówienie musi pojawić się w 30–60 s od potwierdzenia.
  2. DebugView. Administracja → DebugView, podgląd przez rozszerzenie GA Debugger albo parametr _dbg=1. Oczekiwana kolejność: view_item_list → view_item → add_to_cart → view_cart → begin_checkout → add_payment_info → purchase. Brak view_item najczęściej oznacza, że motyw nadpisał szablon i zgubił dataLayer.
  3. Kompletność items. purchase musi mieć transaction_id, value, currency, tax, shipping, coupon oraz tablicę items[] z item_id, item_name, price, quantity (dla wariantów też item_variant). Jeden brakujący item_id i produkt ląduje jako (not set), a przychód nie schodzi się z raportem sprzedaży.
  4. Porównanie 7 i 30 dni — liczba zamówień i przychód z PrestaShop kontra GA4, z jawną tolerancją (tabela niżej).
  5. BigQuery. Administracja → Ustawienia produktu → Eksport BigQuery, cykl dzienny. Zapytanie po event_name = 'purchase' z sumą ecommerce.purchase_revenue daje liczbę bez próbkowania i bez wpływu interfejsu — GA4 w UI potrafi próbkować większe zbiory.
  6. Filtry i property. Administracja → Definicje danych → Ruch wewnętrzny: sprawdź, czy reguła nie wycina całego IP biura (testowane z firmowego Wi-Fi zamówienie zniknie z raportów). Osobno potwierdź, że GTM nie wysyła zdarzeń na property deweloperskie — porównaj ID pomiaru w tagu z tym w pliku konfiguracyjnym sklepu.
Co porównujeszTolerancjaReakcja przy odchyleniu
Liczba purchase, 7 dni±3%Sprawdź duplikaty transaction_id i statusy zamówień mapowane jako konwersja
Przychód, 7 dni±2%Porównaj value z suma pozycji + shipping − rabat; szukaj brakującego tax/shipping
Liczba purchase, 30 dni±5%Uwzględnij zwroty i anulacje — sprawdź, czy nie wpadają jako purchase
Przychód, 30 dni±5%Zestaw z eksportem BigQuery, nie z widokiem w UI

Naprawa samodzielna czy developer: realne widełki czasowe

Zakres prac zależy od tego, ile miejsc wysyła zdarzenia i czy purchase dubluje się. Trzy realne scenariusze:

Własny moduł wygrywa z płatną wtyczką z marketplace w trzech sytuacjach: nie dokładasz kolejnej zależności do sklepu (mniej konfliktów przy aktualizacjach), moduł jest pisany pod Twoją wersję PrestaShop i Twój motyw, a nie „pod najpopularniejszą”, oraz nie płacisz abonamentu rocznego za funkcję, która po wdrożeniu się nie zmienia. Wtyczka ma sens, gdy potrzebujesz wsparcia producenta i szybkiego startu.

Do zlecenia przygotuj: dostęp do kontenera GTM (uprawnienia edytora, nie tylko publikującego), dokładną wersję PrestaShop i PHP, nazwę motywu oraz listę statusów zamówienia z informacją, które są mapowane jako konwersja. Do tego zrzut obecnych tagów i przykładowe transaction_id z ostatnich 7 dni.

Kontekst szerszy: integracje PrestaShop i PrestaShop. Jeśli problem dotyczy całego wdrożenia, a nie tylko pomiaru — zobacz wdrożenia PrestaShop: organizacja, terminy, koszty. Hooki i strukturę modułu opisuje dokumentacja dla deweloperów PrestaShop.

ScenariuszWidełkiCo dostajesz
Korekta w GTM4–8 hPoprawione tagi, triggery, parametry items
Moduł z mapą zdarzeń12–24 hKomplet zdarzeń ecommerce z hooków, bez GTM w środku
Deduplikacja + Measurement Protocol20–40 hJedno purchase na zamówienie, także poza przeglądarką

Najczęstsze błędy i jak je wykryć

Dwa źródła zdarzeń działają równolegle: moduł gtag z marketplace i kontener GTM, a do tego stary analytics.js z czasów Universal Analytics.

Jak wykryć: Otwórz źródło strony w przeglądarce i wyszukaj frazy gtag(, gtag/js, analytics.js, GTM-. Jeśli znajdziesz dwa różne identyfikatory strumienia albo dwa wywołania page_view, masz konflikt. W DebugView zobaczysz zdarzenia zdublowane w tej samej sekundzie.

Jak naprawić: Zostaw jedno źródło prawdy. Wyłącz moduł wysyłający gtag albo usuń kontener GTM — ale nie oba naraz. GTM może zostać warstwą pośrednią, pod warunkiem że to on, i tylko on, wysyła zdarzenia do GA4.

Zdarzenie purchase w ogóle nie jest wysyłane, bo implementacja opiera się na szablonie order-confirmation.tpl, którego motyw nie używa albo który został nadpisany przy aktualizacji.

Jak wykryć: Zrób jedno testowe zamówienie w trybie płatności testowej i patrz na GA4 Realtime oraz DebugView. Jeśli nie pojawia się purchase, sprawdź w plikach motywu, czy istnieje plik szablonu strony potwierdzenia i czy zawiera jakiekolwiek wywołanie zdarzenia.

Jak naprawić: Wysyłaj purchase z miejsca, które faktycznie wykonuje się po złożeniu zamówienia — z kontrolera potwierdzenia lub hooka wywoływanego na stronie potwierdzenia, a nie z szablonu, który może być nadpisany. Potwierdź to testem, nie założeniem.

Brak add_to_cart przy koszyku AJAX. Zdarzenie jest podpięte pod przeładowanie strony, a koszyk dodaje produkt bez przeładowania.

Jak wykryć: Kliknij „dodaj do koszyka” i jednocześnie patrz w DebugView. Jeśli strona się nie przeładowuje i nie pojawia się żadne zdarzenie, problem jest potwierdzony.

Jak naprawić: Podepnij zdarzenie pod odpowiedź serwera na żądanie dodania do koszyka (callback po sukcesie) albo pod zdarzenie frontowe emitowane przez motyw. Przetestuj również dodanie z listy produktów i ze strony produktu — to dwa różne miejsca.

(not set) w item_id i zlewanie się wariantów w raportach item, bo w items przekazywane jest samo id_product bez kombinacji.

Jak wykryć: Wejdź w raporty e-commerce GA4, do sekcji pozycji, i sprawdź, czy item_id ma wartość (not set), a produkty z wariantami występują jako jedna pozycja o sumarycznej sprzedaży.

Jak naprawić: Przekazuj item_id jako reference produktu, a dla wariantu dołóż id_product_attribute. Ustal jedną konwencję (np. reference-id_product_attribute) i trzymaj się jej we wszystkich zdarzeniach, nie tylko w purchase.

Zawyżony przychód przez wielokrotny purchase: klient odświeża stronę potwierdzenia, wraca z historii albo otwiera ją z linku w mailu i skrypt wysyła zdarzenie ponownie.

Jak wykryć: Porównaj liczbę purchase w GA4 z liczbą zamówień w PrestaShop w tym samym zakresie dat. Jeśli w GA4 jest ich więcej, sprawdź, czy powtarzają się te same transaction_id.

Jak naprawić: GA4 nie odrzuci drugiego zdarzenia z tym samym transaction_id, więc zabezpieczenie musi być po Twojej stronie: flaga w sessionStorage lub localStorage blokująca ponowną wysyłkę, a przy dużej skali — zapis po stronie serwera. Jako backstop uruchom uzupełnianie brakujących zakupów przez Measurement Protocol po zmianie statusu zamówienia.

Niespójna wartość zamówienia: GA4 dostaje cenę netto bez dostawy, a w PrestaShop porównujesz total_paid brutto z kosztem przesyłki. Albo waluta jest przekazywana tylko w purchase, a w pozostałych zdarzeniach jej brak.

Jak wykryć: Zestaw revenue z GA4 z polem total_paid z PrestaShop dla tych samych, kilku konkretnych zamówień. Różnica stała i powtarzalna oznacza różnicę definicji, nie błąd tagu.

Jak naprawić: Ustal jedną definicję wartości (najczęściej brutto z dostawą) i stosuj ją we wszystkich zdarzeniach oraz w porównaniach raportowych. Walutę przekazuj w każdym zdarzeniu e-commerce, nie tylko w purchase.

Lista kontrolna do odklikania

Podsumowanie

Prawidłowa integracja PrestaShop z GA4 to przede wszystkim jedno źródło zdarzeń i spójna definicja wartości zamówienia. Objawy, które widzisz w raportach — brak purchase, zawyżony przychód, (not set) w item_id — prawie zawsze prowadzą do jednego z dwóch miejsc: konfliktu implementacji albo zdarzenia wysyłanego z miejsca bez dostępu do danych. Zacznij od testowego zamówienia i DebugView, a nie od przebudowy całego sklepu. Checklistę przechodź punkt po punkcie, bo każdy pominięty element wraca w postaci rozjazdu liczb.

Najczęściej zadawane pytania

Czy GA4 sam usuwa duplikaty purchase po transaction_id?

Nie. GA4 nie odrzuca drugiego zdarzenia zakupu z tym samym transaction_id, więc duplikat po prostu zawyża przychód i liczbę transakcji. Zabezpieczenie musi być po stronie skryptu wysyłającego — na przykład flaga w sessionStorage lub localStorage — albo po stronie serwera.

Czy mogę mieć jednocześnie GTM i moduł gtag z marketplace?

Technicznie tak, praktycznie prawie zawsze kończy się to duplikatami page_view i rozjazdem atrybucji. Jeśli GTM ma być warstwą pośrednią, musi być jedynym miejscem, które wysyła zdarzenia do GA4. Moduł gtag wtedy wyłączasz albo ograniczasz do minimum i sprawdzasz w DebugView, czy faktycznie nic nie wysyła.

Dlaczego GA4 pokazuje mniej zamówień niż PrestaShop?

Najczęstsze powody to brak zdarzenia purchase na stronie potwierdzenia, blokada skryptów przez przeglądarkę lub rozszerzenie, odrzucenie zgody w banerze oraz zamówienia, które nie wróciły z bramki płatności na stronę sklepu. Zanim zaczniesz zmieniać kod, porównaj liczby w tym samym zakresie dat i po wykluczeniu statusów anulowanych.

Czy wystarczy wtyczka do GA4 z marketplace PrestaShop?

Czasem wystarczy, ale trzeba sprawdzić dwie rzeczy: czy wysyła wszystkie potrzebne zdarzenia e-commerce, a nie tylko page_view, oraz czy po aktualizacji PrestaShop nie zaczęła wysyłać zdarzeń równolegle do GTM. Moduł, który działał pół roku temu, po aktualizacji może zachowywać się inaczej — dlatego test po każdej aktualizacji nie jest przesadą.

Jak sprawdzić integrację, nie psując statystyk produkcyjnych?

Użyj DebugView i Realtime, a testy rób na strumieniu testowym lub z wykluczeniem ruchu wewnętrznego. Zamówienie testowe wykonaj w trybie płatności testowej. Dopiero po takim teście porównaj dane produkcyjne z PrestaShop za zamknięty zakres dat.

Skąd bierze się (not set) w item_id i czy to problem GA4?

To problem implementacji, nie GA4. Najczęściej zdarzenie nie dostaje identyfikatora produktu, bo jest wysyłane z miejsca, które go nie zna, albo wariant jest mapowany na samo id_product bez kombinacji. Poprawka polega na przekazaniu reference oraz id_product_attribute w strukturze items.

Czy brakujące zakupy da się jakoś dosłać?

Tak — przez Measurement Protocol, uruchamiany po zmianie statusu zamówienia na taki, który oznacza potwierdzoną płatność. To backstop, nie zamiennik poprawnego zdarzenia po stronie sklepu: bez deduplikacji i spójnej definicji wartości dosyłanie tylko powiększy bałagan w raportach.

Jeśli po przejściu checklisty nadal nie wiesz, gdzie ginie purchase albo skąd bierze się nadwyżka przychodu, napisz do nas — przy audycie zwykle wystarczy dostęp do back office i jeden testowy koszyk. Zanim cokolwiek zmienimy, pokażemy Ci, które miejsce wysyła zdarzenia i co konkretnie trzeba wyłączyć.

Źródła i materiały