Server-side tracking 8 września 2026 12 min czytania

Consent trap Shopera: ukryłeś baner platformy i funnel umarł po cichu

Shoper RWD bramkuje własne integracje (GA4, Meta, GTM z panelu) natywną zgodą. Ukryjesz baner przy wdrażaniu CMP i nowi klienci znikają z pomiaru. Mechanizm, dowód i trzy wyjścia.

Wdrażasz zewnętrzny CMP na sklepie Shoper RWD. Cookiebot, CookieYes, własny baner, wszystko jedno. Natywny widget cookies Shopera przestaje być potrzebny, a dwa banery na jednej stronie to zła obsługa klienta, więc w panelu chowasz ten platformowy. Ruch logiczny, zrobiłby go każdy. Dwa dni później liczba dodań do koszyka w Menedżerze zdarzeń Meta spada o połowę, a w Twojej przeglądarce wszystko dalej działa.

Tak wyglądała awaria, którą znalazłem w audycie wdrożenia na jednym sklepie, a potem ten sam mechanizm zobaczyłem przy audycie drugiego. Shoper RWD bramkuje swoje integracje partnerskie (konektor GA4, silnikowe pushe e-commerce, kontener GTM z panelu, własny piksel Meta platformy) natywnym systemem zgód. Nie zgodą z Twojego CMP. Swoją. Jeśli system zgód jest włączony, a widget ukryty, nowy użytkownik nie ma jak tej zgody udzielić i integracje dla niego nie startują. Nigdy.

Poniżej pełny mechanizm z kodu silnika, dowód z podmianą jednego znaku w locie, test na pięć minut i trzy wyjścia. Plus jedno, którego nie rób, bo naprawia pomiar kosztem RODO.

Objaw: u Ciebie działa, u nowych klientów nie

Najbardziej zdradliwe w tej awarii jest to, że nie ma jej w żadnym narzędziu, którym normalnie sprawdzasz pomiar. Tag Assistant w Twojej przeglądarce pokazuje view_item, add_to_cart, begin_checkout. Podgląd GTM widzi zdarzenia. Menedżer zdarzeń Meta przyjmuje pingi. Wszystko, co robisz własnymi rękami, działa.

Awarię widać dopiero na wykresie wolumenu. W sklepie, o którym mowa (Shoper RWD, ruch rzędu 150 tys. odsłon miesięcznie, niemal wyłącznie nowi użytkownicy), dodania do koszyka spadły w ciągu kilku dni z około 200 dziennie do 50-70. Realna strata sygnału: 55-65%. Dla użytkownika, który trafił do sklepu pierwszy raz, strata wynosiła 100%.

Różnica między Tobą a nowym klientem sprowadza się do jednego wpisu w localStorage. Ty masz zapisaną zgodę z czasów, gdy natywny widget jeszcze się wyświetlał. Nowy klient nie ma i nie może jej uzyskać. Właśnie dlatego to pułapka: testujesz na sobie i widzisz sklep, którego nowi klienci nie widzą.

Co Shoper bramkuje natywną zgodą

W kodzie silnika RWD (bundle frontstore) wszystkie integracje partnerskie są opakowane w jedno wywołanie:

window.customerPrivacy.onPlatformConsentGranted(function () {
  Shop.values.partnerEE = true;
  // dopiero tutaj startują integracje partnerskie
});

Pod tą bramką siedzi więcej, niż się wydaje:

  • partnerski konektor GA4 (flaga partner_google_analytics_v4, tagi “_Product-Owned Activity Tag”), który pcha zdarzenia e-commerce do dataLayer,
  • silnikowe pushe e-commerce do shopLayer i dataLayer, z których korzysta większość wdrożeń GTM na RWD,
  • kontener GTM wpięty przez panel Shopera,
  • kontener Shoper Campaigns GTM-T68LWS, wstrzykiwany na każdy sklep, który niesie też platformowy piksel Meta (loader z agent="plshoper", inicjalizowany identyfikatorem z konfiguracji sklepu).

Ostatni punkt wyjaśnia przy okazji zagadkę z drugiego audytu: nagranie ruchu na świeżym profilu nie widziało żadnego wywołania /tr do Mety, mimo że w Menedżerze zdarzeń kanał wyglądał na żywy. Ten sam ukryty nadawca, o którym pisałem przy ukrytym duplikacie Purchase, jest bramkowany tą samą platformową zgodą. Bez niej świeży profil nie zobaczy go wcale.

Jeśli Twój funnel w GTM opiera się na którymkolwiek z tych źródeł, jego los zależy od natywnego widgetu cookies Shopera. Nawet jeśli obok stoi Cookiebot z poprawnie skonfigurowanym Consent Mode v2.

Dwa ustawienia, jedna martwa kombinacja

Panel: Wygląd i treści, Ustawienia plików cookies. W źródle strony materializuje się to jako dwie zmienne:

Shop.cookiesViewType = '2';
Shop.displayCookieInfo = '0';
  • cookiesViewType mówi, jaki system zgód działa. '1' to stary pasek informacyjny: silnik woła disable() i wszystkie callbacki onPlatformConsentGranted odpalają się natychmiast, bezwarunkowo. '2' to pełny widget zgód (od marca 2024, pod Consent Mode v2): callbacki czekają na zgodę platformową.
  • displayCookieInfo mówi, czy widget jest widoczny. '1' renderuje go, '0' nie.

Kombinacja '2' plus '0' oznacza: bramkowanie włączone, ale nie istnieje żaden interfejs, w którym dałoby się zgody udzielić. Callbacki czekają w nieskończoność. Użytkownicy ze starym wpisem user_consents w localStorage przechodzą, bo silnik czyta zapisany stan. Wszyscy pozostali stoją przed zamkniętymi drzwiami bez klamki.

Centrum pomocy Shopera nigdzie o tym nie ostrzega. Jedynym dowodem jest kod silnika i zachowanie sklepu na czystym profilu.

Dlaczego umiera stopniowo, a nie od razu

Gdyby funnel padł do zera w dniu ukrycia widgetu, każdy by to zauważył. Nie pada, bo istnieje pula zapisanych zgód. Powracający klienci z zapisanym user_consents dalej generują zdarzenia. Pula się nie odnawia (nikt nowy nie może dołączyć), więc sygnał wygasa w tempie, w jakim starzy użytkownicy przestają wracać.

W sklepie z dużym udziałem powracających klientów spadek rozciąga się na tygodnie i ginie w naturalnej zmienności. W sklepie napędzanym reklamą, gdzie prawie każdy użytkownik jest nowy, wygląda jak nagła awaria. W obu przypadkach wykres schodzi po zboczu, nie z klifu, i to jest najgorszy możliwy kształt dla kogoś, kto ogląda panel raz na tydzień.

W opisywanym sklepie spadek dodatkowo maskowała wcześniejsza duplikacja: natywna wtyczka GA4 Shopera pchała każde zdarzenie dwa razy (push i komenda gtag, z różnymi identyfikatorami), więc liczby sprzed awarii były zawyżone, a po niej “tylko” niższe. Dwa błędy, które nawzajem się zasłaniają, to na Shoperze norma, nie wyjątek.

Dowód: podmiana jednego znaku w locie

Wnioskowanie z kodu to za mało, żeby iść z tym do klienta. Potrzebny był eksperyment, który odróżni tę hipotezę od dziesięciu innych. Zrobiłem go w headless Chrome z przechwytywaniem odpowiedzi HTML:

  1. Świeży profil, bez żadnego localStorage. Wejście na kartę produktu, akceptacja banera CMP. W dataLayer brak view_item, Shop.values.partnerEE nie jest true.
  2. Ten sam świeży profil, ale w odpowiedzi HTML podmieniam w locie displayCookieInfo = '0' na '1'. Nic więcej. Natywny widget Shopera wraca na ekran.
  3. Akceptacja natywnego widgetu. Shop.values.partnerEE przechodzi na true, w dataLayer pojawia się view_item, konektor GA4 i kontener platformy startują.

Powtórzone dwa razy, w tym z maskowaniem headless (żeby wykluczyć, że silnik traktuje bota inaczej). Jedna zmienna, jeden znak, funnel wraca. To jest moment, w którym hipoteza staje się diagnozą.

Bez headless Chrome ten sam test zrobisz ręcznie: nowy profil przeglądarki, karta produktu, konsola:

Shop.cookiesViewType;        // '2' = system zgód włączony
Shop.displayCookieInfo;      // '0' = widget ukryty
Shop.values.partnerEE;       // brak true = integracje partnerskie nie wystartowały
localStorage.user_consents;  // brak = nowy użytkownik, bez zapisanej zgody
dataLayer.filter(e => e.event === 'view_item').length; // 0 = funnel martwy

Jak to sprawdzić u siebie w pięć minut

Kolejność ma znaczenie, bo pierwszy krok rozstrzyga większość przypadków:

  1. Źródło strony. Szukasz displayCookieInfo i cookiesViewType. Para '2' i '0' to potencjalna pułapka. Inne kombinacje: ten problem Cię nie dotyczy, ale czytaj dalej, bo '1' ma własny.
  2. Czy Twój funnel zależy od bramki. Jeśli zdarzenia e-commerce w GTM pochodzą z pushy Shopera (natywna wtyczka GA4, konektor, shopLayer), zależy. Jeśli z własnej warstwy w motywie, nie.
  3. Świeży profil przeglądarki. Nowy profil albo okno prywatne z czystym localStorage. Twój codzienny profil odpada: ma zapisaną zgodę z czasów, gdy widget jeszcze się wyświetlał. To jedyny sposób, żeby zobaczyć sklep oczami nowego klienta.
  4. Akceptacja CMP, karta produktu, konsola. Snippet wyżej. Zero view_item w dataLayer przy partnerEE bez wartości true to potwierdzenie.
  5. Wykres wolumenu w Menedżerze zdarzeń lub GA4 od dnia, w którym ukryłeś widget. Zbocze, nie klif.

Ten sam test warto powtórzyć po każdej zmianie w ustawieniach cookies, po aktualizacji motywu i po każdej publikacji GTM. Statyczny skan strony (curl, checker, crawler) tej awarii nie wykryje, bo tagi bramkowane zgodą nie istnieją w źródle, dopóki ktoś zgody nie udzieli.

Trzy wyjścia i jedno, którego nie rób

Nie rób: przełączenie na stary pasek

Najszybsza “naprawa” to zmiana cookiesViewType na '1'. Silnik woła disable(), callbacki odpalają się natychmiast, funnel wraca w minutę. Wraca też pomiar bez jakiejkolwiek zgody: konektor GA4, kontener platformy i piksel Meta strzelają do każdego użytkownika od pierwszej odsłony, niezależnie od tego, co kliknął w Twoim CMP. Naprawiłeś liczby, kupując sobie incydent RODO.

Wyjście 1: zostaw natywny widget jako źródło zgód

Jeśli nie potrzebujesz zewnętrznego CMP, najprościej jest nie chować widgetu Shopera. Od marca 2024 obsługuje kategorie i Consent Mode v2, można go ostylować, a bramka partnerskich integracji działa wtedy zgodnie z projektem. Ograniczenia: brak rejestru zgód, brak tabeli cookies, brak monitoringu. Dla części sklepów to wystarczy, dla części nie.

Wyjście 2: pomost z CMP do platformy

Jeśli zewnętrzny CMP zostaje, musi rozmawiać z silnikiem. Fasada window.customerPrivacy ma, poza udokumentowanymi callbackami (onAnalyticsConsentGranted, onMarketingConsentGranted, onFunctionalConsentGranted), także metody grantConsents([...]) i withdrawConsents([...]). Po decyzji użytkownika w Twoim banerze wołasz je z odpowiednimi kategoriami, przy każdym załadowaniu strony, bo grantConsents odpala callbacki, ale niczego nie zapisuje. Stan zgód trzymasz po swojej stronie.

Dwie uwagi. Po pierwsze, te metody nie są oficjalnie udokumentowane, więc aktualizacja frontstore może je zmienić, a pomost wymaga syntetycznego testu funnela na świeżym profilu, najlepiej cyklicznego. Po drugie, gotowe CMP z pudełka tego pomostu nie mają, bo nie wiedzą o bramce. Konfiguracja Consent Mode v2, którą opisałem przy Cookiebocie i sGTM, załatwia tagi w GTM, ale nie odblokuje integracji partnerskich Shopera. To osobna warstwa.

Wyjście 3: własna warstwa dataLayer w motywie

Najbardziej odporne rozwiązanie odcina zależność u źródła. Pięć zdarzeń e-commerce (view_item, view_item_list, add_to_cart, begin_checkout, purchase) pisanych wprost w szablonach motywu, do dataLayer, bez pośrednictwa wtyczek i konektorów. Zgodami zarządza wtedy wyłącznie Consent Mode v2 w GTM, a bramka Shopera dotyczy już tylko integracji platformy, na których i tak nie powinieneś opierać pomiaru.

To była docelowa naprawa w opisywanym sklepie, wdrożona tego samego dnia, w którym postawiłem diagnozę. Cały przebieg, z dwiema innymi awariami po drodze, opisałem w case study wdrożenia server-side na Shoperze, a mechanikę tego, dlaczego natywne pushe Shopera są kruchym fundamentem, w tekście o natywnej wtyczce GA4 na Shoper RWD. Jedna pułapka do zapamiętania: kliknięcie w koszyk na RWD nawiguje, więc push add_to_cart ginie w przeładowaniu i trzeba go odtworzyć na stronie docelowej z sessionStorage.

Storefront 2026 ma pułapkę odwrotną

Na nowym froncie Shopera (Storefront 2026) ukrycie natywnego widgetu nie zabija pomiaru. Robi coś gorszego. Moduł analityczny ładuje GTM i gtag zawsze, ale komendy Consent Mode (domyślne denied i późniejszy update) wykonują się tylko wtedy, gdy informacja o cookies jest włączona. Wyłączysz ją, a GTM działa bez żadnego Consent Mode: wszystkie tagi strzelają tak, jakby CMP nie istniał. Do tego zdarzenie purchase na Storefront pcha do dataLayer dane klienta (e-mail, telefon, adres), więc tagi bez zgody to już nie luka w danych, tylko incydent.

Dobra wiadomość: Storefront ma oficjalne, udokumentowane customerPrivacyApi z grantConsents, withdrawConsents i saveConsents, więc pomost z własnego CMP buduje się tam na wspieranym API, nie na fasadzie. Zła: trzeba wiedzieć, że jest potrzebny. Pomiar na zamkniętym froncie Storefront, razem z warstwą zgód, to dokładnie ten obszar, w którym pracuję w motywie zamiast we wtyczkach, bo wtyczki tam po prostu nie działają.

Podsumowanie

Shoper RWD bramkuje własne integracje partnerskie natywnym systemem zgód, niezależnie od zewnętrznego CMP. Kombinacja cookiesViewType = '2' i displayCookieInfo = '0' (system zgód włączony, widget ukryty) sprawia, że nowy użytkownik nie może udzielić zgody platformowej, więc konektor GA4, pushe e-commerce, kontener z panelu i piksel platformy nigdy dla niego nie startują. Powracający klienci z zapisaną zgodą działają dalej, przez co funnel wygasa stopniowo i pozostaje niewidoczny w Twojej własnej przeglądarce.

Diagnoza wymaga świeżego profilu i jednej linii w konsoli. Naprawa to wybór między natywnym widgetem, pomostem z CMP do fasady customerPrivacy i własną warstwą dataLayer w motywie. Przełączenie na stary pasek nie jest naprawą, tylko zamianą utraty danych na pomiar bez zgody. A na Storefront 2026 ten sam ruch w panelu daje odwrotny skutek: nie ciszę, ale tagi bez Consent Mode.

Testuj funnel oczami nowego klienta, nie swoimi. Twoja przeglądarka ma zgody, których nikt nowy już nie dostanie.

Porozmawiajmy o Twoim trackingu

30 minut bez zobowiązań. Bez sesji sprzedażowej. Powiem czy mogę pomóc i co realnie da się odzyskać.