LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Przegląd bloga /Digital Analytics/Tutorials / Przesyłanie zakupów sklepowych do GA4 przez Measurement...
Ten artykuł w innych językach:

Przesyłanie zakupów sklepowych do GA4 przez Measurement Protocol: numer karty lojalnościowej jako klucz

Przesyłanie zakupów sklepowych do GA4 przez Measurement Protocol: numer karty lojalnościowej jako klucz

Management Summary

Zakupy w sklepie mogą uzupełniać wyniki witryny w Google Analytics, jeśli zweryfikowane powiązanie karty lojalnościowej łączy oba systemy. Measurement Protocol to interfejs do przesyłania takich zakupów z serwera firmy. Umożliwia wspólną analizę aktywności online i sprzedaży sklepowej, lecz sam numer karty nie potwierdza osoby ani wcześniejszej wizyty. Potrzebne są dopuszczalne przetwarzanie, wiarygodne dopasowanie i rzeczywisty czas zakupu. Niepowiązane paragony pozostają we własnej analizie firmy.

Spis treści
  1. Trzy identyfikatory o różnych zadaniach
  2. Skrót chroni numer, ale nie zastępuje uprawnienia
  3. Zapis połączenia podczas zalogowanej wizyty
  4. Zakup jako JSON
  5. Czas i przypisanie mają różne ograniczenia
  6. Walidacja i ponowienia
  7. Zwroty i starsze dane
  8. Pytania i odpowiedzi
  9. Źródła

Kasa dostarcza produkty, kwoty i czas sprzedaży. Karta lojalnościowa może dodatkowo wskazywać konto klienta. GA4 używa natomiast identyfikatorów z pomiaru online. Wspólny raport wymaga więc wiarygodnego powiązania obu systemów. Pasujący ciąg znaków sam w sobie nie potwierdza osoby ani wcześniejszej sesji.

Measurement Protocol jest jedną z dróg przesyłania takich zdarzeń serwerowych do GA4. Ten przewodnik opisuje rozwiązanie o celowo ograniczonym zakresie: sprzedaż ze sprawdzonym powiązaniem i dopuszczalną wysyłką. Paragony bez odpowiedniego identyfikatora online pozostają początkowo we własnej analizie firmy.

Sprawdzone powiązanie karty, rzeczywisty identyfikator online i skontrolowane dane zakupu.
Każdy etap wymaga własnego potwierdzenia; karta nie dowodzi sesji online.

Trzy identyfikatory o różnych zadaniach

client_id oznacza instancję przeglądarki i jest wymagane w internetowym Measurement Protocol. Inna przeglądarka lub usunięte cookies mogą oznaczać inny identyfikator. user_id to opcjonalny identyfikator użytkownika nadawany przez firmę. Stałe User-ID może wspierać raporty obejmujące różne urządzenia przy odpowiedniej integracji i tożsamości raportowania.

Numer karty lojalnościowej jest początkowo tylko identyfikatorem z systemu kasowego. Karty rodzinne, przekazane karty i ponownie nadane numery przeczą założeniu, że jedna karta zawsze oznacza jedną osobę. Takie przypadki wymagają osobnej reguły; karta gospodarstwa domowego nie może automatycznie służyć jako osobiste User-ID.

Skrót chroni numer, ale nie zastępuje uprawnienia

HMAC tworzy powtarzalną wartość z numeru karty i tajnego klucza. Ten sam numer i klucz dają ten sam wynik. Bez klucza lista możliwych numerów kart nie pozwala na proste porównanie z zapisanymi wartościami. To ochrona powiązania, a nie automatyczna anonimizacja: operator nadal może połączyć wartość z kontem klienta.

Przykład używa HMAC wyłącznie jako wewnętrznego klucza wyszukiwania. Istniejące, losowo nadane Analytics User-ID pozostaje oddzielne. Wymiana klucza HMAC nie musi wtedy zmieniać User-ID. Zgoda, dopuszczalny cel, okres przechowywania i usuwanie nadal są osobnymi wymaganiami.

Funkcja PHP przyjmuje wyłącznie założony format karty: LW i osiem cyfr, opcjonalnie rozdzielonych spacjami lub myślnikami w pokazanych miejscach. Dowolne znaki specjalne są odrzucane zamiast cichego usuwania. Zapobiega to przypadkowemu sprowadzeniu różnych niepoprawnych danych do jednego numeru.

PHP
function card_key(string $card, string $key): string {
    if (strlen($key) < 32) {
        throw new InvalidArgumentException('HMAC key too short');
    }
    if (!preg_match('/\ALW[ -]?([0-9]{4})[ -]?([0-9]{4})\z/iD', trim($card), $m)) {
        throw new InvalidArgumentException('Invalid card format');
    }
    $canonical = 'LW' . $m[1] . $m[2];
    return hash_hmac('sha256', 'loyalty-lookup-v1:' . $canonical, $key);
}

Klucz musi składać się z co najmniej 32 kryptograficznie losowych bajtów i pozostawać poza publicznymi plikami. Sprawdzenie długości w przykładzie nie mierzy losowości. Kasa i backend potrzebują identycznych reguł formatu i normalizacji. Funkcja sprawdza format, a nie autentyczność karty lub uprawnienie konta do karty.

Zapis połączenia podczas zalogowanej wizyty

Powiązanie powstaje dopiero po sprawdzeniu przez backend uprawnienia zalogowanego konta do karty. Samo wpisanie cudzego numeru nie wystarcza. Zbieranie online i późniejsze połączenie również muszą być dopuszczalne. Udokumentowany interfejs tagu gtag('get', 'G-XXXXXXXXXX', 'client_id', callback) pobiera Client ID. Brak wartości lub wywołania zwrotnego oznacza brak powiązania. Własny parser cookies jest zbędny.

Przeglądarka wysyła identyfikator do uwierzytelnionego endpointu backendu chronionego przed żądaniami formularzy z obcych witryn. Backend ustala konto i zweryfikowaną kartę na podstawie sesji, sprawdza dane oraz uprawnienia i zapisuje tylko potrzebne połączenie. Client ID nie jest logowaniem ani dowodem własności konta.

Powiązanie może zawierać wewnętrzny skrót karty z wersją klucza, Client ID, czas potwierdzenia i okres ważności. Wycofanie zgody lub odłączenie karty musi zatrzymać dalsze przesłania. Spośród ważnych powiązań można wybrać ostatnio potwierdzone; to jawna reguła wyboru, a nie dowód, że właśnie ta przeglądarka doprowadziła do zakupu w sklepie.

Zakup jako JSON

Adres zawiera measurement_id i poufny api_secret jako parametry URL. Poniższa treść ilustruje zakup z powiązaniem. Client ID, numer paragonu i czas są przykładowymi wartościami. Znacznik na poziomie żądania jest liczbą mikrosekund i musi odpowiadać rzeczywistemu czasowi zakupu.

JSON
{
  "client_id": "1899482740.1757000000",
  "timestamp_micros": 1792301400000000,
  "events": [
    {
      "name": "purchase",
      "params": {
        "transaction_id": "HH-ALT-2026-1016-0007",
        "value": 48.9,
        "currency": "EUR",
        "items": [
          {
            "item_id": "SKU-3391",
            "affiliation": "Hamburg-Altona",
            "price": 48.9,
            "quantity": 1
          }
        ]
      }
    }
  ]
}

affiliation znajduje się wewnątrz pozycji, ponieważ Google definiuje to pole na poziomie artykułu. value odpowiada sumie ceny pomnożonej przez ilość, bez oddzielnie wykazanych podatków i kosztów dostawy. Ceny są liczbami JSON, a nie lokalnie sformatowanym tekstem, takim jak „48,90”. Identyfikator paragonu musi rozróżniać zakupy także między sklepami, na przykład przez kod sklepu i numer paragonu, oraz pozostać niezmienny przy ponowieniach.

Przykład nie tworzy fikcyjnej sesji ani czasu zaangażowania. Operacja kasowa nie ma automatycznie identyfikatora sesji przeglądarki lub zmierzonego czasu aktywności online. Bez tych danych raporty sesji, zaangażowania i czasu rzeczywistego są ograniczone. Opcjonalne User-ID również nie zmienia automatycznie zakupu w konwersję przypisaną do sesji reklamowej.

Czas i przypisanie mają różne ograniczenia

Google dopuszcza datowanie wstecz do 72 godzin. Przy starszych znacznikach RELAXED przesuwa czas na 72 godziny przed odbiorem, natomiast ENFORCE_RECOMMENDATIONS odrzuca zdarzenie. Spóźniona wysyłka tygodniowa nie musi więc tracić połowy paragonów, ale może przypisywać je do niewłaściwych dni. Udział spóźnionych paragonów zależy również od rzeczywistego rozkładu sprzedaży w czasie.

Przypisanie do sesji online ma dodatkowe warunki. Dokumentacja zastosowań wymaga między innymi prawdziwego identyfikatora sesji, odbioru najpóźniej 24 godziny od rozpoczęcia sesji i czasu zdarzenia mieszczącego się w sesji. Późniejszy zakup sklepowy często nie spełnia tych warunków. Ogólna instrukcja wysyłania podaje także 48 godzin dla wspólnego przetwarzania ze zdarzeniami tagu lub SDK. Sam poprawny Client ID nie gwarantuje więc przypisania reklamowego.

Częsta wysyłka skraca opóźnienie i pozostawia czas na usunięcie awarii. Monitorowana kolejka przechowuje czas zakupu, próby wysyłki i stan kontroli. Przyszłe lub wątpliwe czasy wymagają wyjaśnienia zamiast cichej zmiany na „teraz”. Czas lokalny wymaga poprawnej strefy, zwłaszcza przy zmianie czasu letniego i zimowego.

Walidacja i ponowienia

Żądanie może zawierać najwyżej 25 zdarzeń i musi mieć mniej niż 130 kB. Identyfikatory na poziomie żądania obowiązują wszystkie zdarzenia; różni klienci nie należą do jednego żądania. W tym prostym rozwiązaniu każdy paragon otrzymuje osobne żądanie ze swoim czasem. Omija to sprzecznie udokumentowane umiejscowienie znacznika pojedynczego zdarzenia.

Endpoint /debug/mp/collect bada ładunki z ENFORCE_RECOMMENDATIONS. Zdarzenia testowe nie pojawiają się w raportach, a identyfikator strumienia i sekret nie są tam sprawdzane. validation_behavior jest udokumentowanym polem także na endpointcie produkcyjnym. Google zaleca pominięcie tego pola w produkcji, aby ograniczyć odrzucanie zdarzeń.

Odpowiedź 2xx potwierdza tylko odbiór. Działający system potrzebuje więc późniejszego porównania przewidzianych paragonów z danymi GA4. Przed każdą wysyłką kod nadawcy sprawdza powiązanie, aktualne uprawnienie, kwotę, walutę, pozycje i numer paragonu. Zerwane połączenie pozostawia niepewność, czy pierwsze żądanie dotarło. Ponowienie zachowuje numer paragonu i korzysta z kontrolowanych reguł powtórzeń; pojedynczy kod HTTP nie jest pełnym dowodem dostarczenia.

Zwroty i starsze dane

Zwrot jest nowym zdarzeniem. Jeśli produkt kupiony tydzień temu zostaje zwrócony dzisiaj, refund może zawierać dzisiejszy czas zwrotu i pierwotne transaction_id. Znacznik nie wymaga cofania do daty zakupu. Raporty na poziomie artykułów wymagają odpowiednich pozycji i ilości. Zwrot faktycznie dokonany tydzień temu, lecz odkryty dopiero dzisiaj, jest natomiast spóźnionym zdarzeniem.

Do własnej analizy historycznej dane kasowe można połączyć z dostępnymi eksportami GA4 w BigQuery. Powstaje osobna analiza; brakujące zdarzenia nie są wstecznie dopisywane do interfejsu GA4. Wynik zależy od dostępnych eksportów, spójnych identyfikatorów, przechowywania i dopuszczalnego przetwarzania. Nie oznacza to gwarancji nieograniczonej historii.

Pytania i odpowiedzi

Co dzieje się bez powiązania online?

To rozwiązanie nie wysyła do GA4 wymyślonego klienta zastępczego. Paragon pozostaje we własnej analizie kasowej firmy. Osobno zaprojektowany pomiar offline wymaga własnych celów i kontroli; formalnie poprawny losowy identyfikator nie tworzy połączenia z wizytą online.

Co zmienia wymiana klucza?

Zmieniają się wewnętrzne wartości HMAC używane do wyszukiwania. Wersjonowane klucze i kontrolowana migracja legalnie dostępnych danych kart pozwalają utworzyć nowe powiązania. Oddzielne Analytics User-ID może pozostać bez zmian. Stare klucze i kopie tabel wymagają ustalonej procedury usuwania; ujawniony klucz nie może działać bez końca.

Dlaczego nie zwykłe SHA-256 bez klucza?

Stały przedrostek i osiem cyfr dają tylko 100 milionów możliwych numerów. Bez tajnego klucza wcześniej obliczona lista może porównać te wartości z zapisanymi skrótami. HMAC utrudnia ten atak przy odpowiednio silnym i chronionym kluczu. Powiązanie nadal dotyczy osoby, dopóki możliwe jest połączenie z kontem.

Lukas Wójcik

Lukas Wójcik

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.

Kontakt

Masz pytanie lub pomysł na projekt internetowy? Napisz krótko, o co chodzi. Formularz korzysta z reCAPTCHA do ochrony przed spamem.

Napisanie komentarza

Odmienne wyniki z innych kont i pytania o konfigurację są tu mile widziane.

Adres e-mail nie jest publikowany. Pola obowiązkowe oznaczono gwiazdką.