Ladenkäufe per Measurement Protocol nach GA4 hochladen: Die Kundenkartennummer als Schlüssel

Management Summary
Ladenkäufe können Websiteergebnisse in Google Analytics ergänzen, wenn eine überprüfte Kundenkartenverbindung beide Systeme zusammenführt. Das Measurement Protocol ist die Schnittstelle, über die der Unternehmensserver solche Käufe meldet. Dadurch lassen sich Onlineaktivität und Ladenumsatz gemeinsam betrachten. Eine Kartennummer allein beweist jedoch weder eine Person noch einen früheren Besuch. Erforderlich sind zulässige Verarbeitung, verlässliche Zuordnung und die tatsächliche Kaufzeit; nicht zuordenbare Belege bleiben in der eigenen Auswertung.
Inhalt
Eine Kasse liefert Waren, Beträge und einen Verkaufszeitpunkt. Eine Kundenkarte kann zusätzlich auf ein Kundenkonto verweisen. GA4 arbeitet dagegen mit Kennungen aus der Online-Messung. Für einen gemeinsamen Bericht braucht es deshalb eine verlässliche Zuordnung zwischen beiden Systemen. Eine passende Zeichenfolge allein beweist weder eine Person noch eine frühere Sitzung.
Das Measurement Protocol ist ein Weg, solche Serverereignisse an GA4 zu übermitteln. Dieser Leitfaden beschreibt eine bewusst begrenzte Umsetzung: Verkäufe mit überprüfter Zuordnung und zulässiger Übermittlung. Belege ohne passende Online-Kennung bleiben zunächst in der eigenen Auswertung.

Drei Kennungen mit verschiedenen Aufgaben
client_id bezeichnet im Web eine Browserinstanz und ist im Web-Measurement-Protocol erforderlich. Ein anderer Browser oder gelöschte Cookies können eine andere Kennung bedeuten. user_id ist eine optionale, vom Unternehmen vergebene Nutzerkennung. Eine gleichbleibende User-ID kann geräteübergreifende Auswertungen unterstützen, wenn die Integration und die Berichtsidentität dazu passen.
Eine Kundenkartennummer ist zunächst nur eine Kennung aus dem Kassensystem. Familienkarten, übertragene Karten oder neu vergebene Nummern widerlegen die Annahme „eine Karte entspricht immer einer Person“. Solche Fälle brauchen eine eigene Regel; eine Haushaltskarte darf nicht ohne Weiteres als persönliche User-ID dienen.
Ein Hash schützt die Nummer, ersetzt aber keine Berechtigung
Ein HMAC erzeugt aus einer Kartennummer und einem geheimen Schlüssel einen reproduzierbaren Prüfwert. Dieselbe Nummer und derselbe Schlüssel ergeben denselben Wert. Ohne den Schlüssel lässt sich eine Liste möglicher Kartennummern nicht einfach mit den gespeicherten Werten abgleichen. Das ist ein Schutz der Zuordnung, keine automatische Anonymisierung: Der Betreiber kann weiterhin Verbindungen zum Kundenkonto herstellen.
Das Beispiel verwendet HMAC nur als internen Suchschlüssel. Eine bereits vorhandene, zufällig vergebene Analytics-User-ID bleibt davon getrennt. Dadurch muss ein Wechsel des HMAC-Schlüssels nicht zugleich die User-ID verändern. Einwilligung, erlaubter Zweck, Aufbewahrung und Löschung bleiben eigenständige Anforderungen.
Die PHP-Funktion akzeptiert ausschließlich das hier angenommene Kartenformat: LW und acht Ziffern, optional mit Leerzeichen oder Bindestrichen an den gezeigten Stellen. Beliebige Sonderzeichen werden abgelehnt statt still entfernt. Das verhindert, dass verschiedene ungültige Eingaben durch Bereinigung versehentlich dieselbe Nummer ergeben.
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);
}Der Schlüssel muss aus mindestens 32 kryptografisch zufälligen Bytes bestehen und außerhalb öffentlicher Dateien liegen. Die Längenprüfung im Beispiel misst keine Zufälligkeit. Kartenformat und Normalisierung müssen in Kasse und Backend identisch sein. Die Funktion prüft das Format, nicht die Echtheit oder Berechtigung einer Karte.
Die Verbindung beim angemeldeten Besuch erfassen
Eine Bindung darf erst entstehen, nachdem das Backend die Berechtigung des angemeldeten Kontos für die Karte geprüft hat. Die bloße Eingabe einer fremden Kartennummer reicht nicht. Zusätzlich muss die Online-Erfassung und spätere Verbindung zulässig sein. Die dokumentierte Tag-Schnittstelle gtag('get', 'G-XXXXXXXXXX', 'client_id', callback) liefert die Client-ID; fehlt der Wert oder bleibt der Aufruf aus, entsteht keine Zuordnung. Ein selbst gebauter Cookie-Parser ist dafür unnötig.
Der Browser übermittelt die Kennung an einen authentifizierten Backend-Endpunkt mit Schutz vor fremden Formularanfragen. Das Backend bestimmt Konto und geprüfte Karte aus der Sitzung, prüft Eingaben und Berechtigungen und speichert nur die erforderliche Verbindung. Eine Client-ID ist keine Anmeldung und kein Nachweis der Kontoinhaberschaft.
Eine Zuordnung enthält beispielsweise den internen Kartenprüfwert mit Schlüsselversion, die Client-ID, den Zeitpunkt der bestätigten Verbindung und deren Gültigkeit. Ein Widerruf oder eine gelöste Kartenbindung muss weitere Übermittlungen verhindern. Unter mehreren gültigen Verbindungen kann die zuletzt bestätigte gewählt werden; das ist eine dokumentierte Auswahlregel, kein Beweis, dass genau dieser Browser den Ladenkauf verursacht hat.
Ein Kauf als JSON
Die Adresse enthält measurement_id und das vertrauliche api_secret als URL-Parameter. Der folgende Rumpf ist ein Strukturbeispiel für einen zugeordneten Kauf. Client-ID, Belegnummer und Zeitpunkt sind Platzhalterwerte. Der Zeitstempel steht auf Anfrageebene als Zahl in Mikrosekunden und muss dem tatsächlichen Kauf entsprechen.
{
"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 steht innerhalb des Items, weil Google dieses Feld auf Artikelebene definiert. value entspricht der Summe aus Preis mal Menge ohne separat ausgewiesene Steuer und Versandkosten. Preise sind JSON-Zahlen, keine lokal formatierten Zeichenketten wie „48,90“. Die Belegkennung muss Käufe auch zwischen Filialen unterscheiden, beispielsweise durch Filialkürzel plus Belegnummer, und bei Wiederholungen gleich bleiben.
Das Beispiel erfindet keine Sitzung und keine Interaktionszeit. Ein Kassenvorgang hat nicht automatisch eine Browser-Sitzungskennung oder eine gemessene Online-Interaktionsdauer. Ohne solche Angaben sind Sitzungs-, Interaktions- und Echtzeitauswertungen eingeschränkt. Auch eine optionale User-ID macht daraus nicht automatisch einen einer Werbesitzung zugeordneten Kauf.
Zeit und Zuordnung sind unterschiedliche Grenzen
Google erlaubt eine Rückdatierung bis zu 72 Stunden. Bei älteren Zeitpunkten begrenzt RELAXED den Zeitpunkt auf 72 Stunden vor Empfang; ENFORCE_RECOMMENDATIONS lehnt ab. Ein verspäteter Wochenlauf verliert deshalb nicht zwangsläufig pauschal die Hälfte aller Belege, kann aber falsche Tageszuordnungen verursachen. Ein Prozentanteil verspäteter Belege hängt außerdem von der tatsächlichen zeitlichen Verteilung der Verkäufe ab.
Für die Zuordnung zu einer Online-Sitzung gelten zusätzliche Bedingungen: Die Use-Case-Dokumentation verlangt unter anderem die echte Sitzungskennung, Empfang spätestens 24 Stunden nach Sitzungsbeginn und einen Ereigniszeitpunkt innerhalb der Sitzung. Ein später Ladenkauf erfüllt diese Bedingungen häufig nicht. Die allgemeine Versand-Anleitung nennt außerdem 48 Stunden für die gemeinsame Verarbeitung mit Tag- oder SDK-Ereignissen. Eine gültige Client-ID allein garantiert folglich keine Werbezuordnung.
Ein häufiger Versand reduziert Wartezeit und schafft Spielraum bei Störungen. Eine überwachte Warteschlange speichert Kaufzeit, Versandversuche und Prüfstatus. Zukünftige Zeitpunkte oder zweifelhafte Uhrzeiten werden geklärt statt still auf „jetzt“ geändert. Eine lokale Uhrzeit braucht die korrekte Zeitzone, besonders beim Wechsel zwischen Sommer- und Winterzeit.
Prüfung und Wiederholung
Eine Anfrage kann höchstens 25 Ereignisse enthalten und muss unter 130 kB bleiben. Die Kennungen auf Anfrageebene gelten für alle enthaltenen Ereignisse; verschiedene Kunden gehören nicht in dieselbe Anfrage. In dieser einfachen Umsetzung wird pro Beleg eine Anfrage mit dessen Zeitpunkt erzeugt. Damit entfällt die widersprüchlich dokumentierte Platzierung einzelner Ereigniszeitstempel.
Der Prüfendpunkt /debug/mp/collect untersucht Nutzlasten mit ENFORCE_RECOMMENDATIONS. Testereignisse erscheinen nicht in Berichten; Datenstromkennung und Geheimnis werden dort nicht geprüft. validation_behavior ist auch am Produktivendpunkt ein dokumentiertes Feld. Google empfiehlt dort das Weglassen, um weniger Ereignisse abzulehnen.
Eine 2xx-Antwort belegt nur den Empfang. Deshalb braucht der Betrieb einen späteren Abgleich der vorgesehenen Belege mit den GA4-Daten. Vor jedem Versand prüft der eigene Code Zuordnung, aktuelle Berechtigung, Betrag, Währung, Artikel und Belegnummer. Bei einem Verbindungsabbruch ist unklar, ob die erste Anfrage bereits angekommen ist. Ein erneuter Versuch verwendet dieselbe Belegnummer und eine kontrollierte Wiederholungslogik; ein einzelner HTTP-Code ist kein vollständiger Zustellnachweis.
Rückgaben und ältere Daten
Eine Rückgabe ist ein neues Ereignis. Wird ein vor einer Woche gekaufter Artikel heute erstattet, kann ein refund mit dem heutigen Erstattungszeitpunkt und der ursprünglichen transaction_id übermittelt werden. Der Zeitpunkt muss nicht auf den Kauf zurückgesetzt werden. Für Artikelkennzahlen enthält die Rückgabe die betroffenen Items und Mengen. Ein erst heute entdeckter, bereits vor einer Woche erfolgter Refund ist dagegen ein verspätetes Ereignis.
Für eine eigene historische Auswertung lassen sich Kassendaten mit vorhandenen GA4-Exportdaten in BigQuery verbinden. Dieses Zusammenführen erzeugt eine separate Auswertung und schreibt keine fehlenden Ereignisse rückwirkend in die GA4-Oberfläche. Es hängt von verfügbaren Exporten, eindeutigen Kennungen, Aufbewahrung und zulässiger Verarbeitung ab; unbegrenzte Historie ist damit nicht garantiert.
Fragen und Antworten
Was passiert ohne Online-Zuordnung?
Diese Umsetzung sendet keinen erfundenen Ersatz-Client an GA4. Der Beleg bleibt in der eigenen Kassenanalyse. Eine separat entworfene Offline-Messung benötigt eigene Ziele und Prüfungen; eine formal passende Zufallskennung stellt keine Verbindung zu einem Online-Besuch her.
Was bewirkt ein Schlüsselwechsel?
Die internen HMAC-Suchwerte ändern sich. Versionierte Schlüssel und eine kontrollierte Migration der rechtmäßig verfügbaren Kartendaten ermöglichen neue Zuordnungen. Die getrennte Analytics-User-ID kann gleich bleiben. Alte Schlüssel und Tabellenkopien benötigen ein festgelegtes Löschverfahren; ein kompromittierter Schlüssel darf nicht unbegrenzt weiterverwendet werden.
Warum nicht einfach SHA-256 ohne Schlüssel?
Bei einem festen Präfix und acht Ziffern gibt es nur 100 Millionen mögliche Nummern. Ohne geheimen Schlüssel kann eine vorberechnete Liste diese Werte mit gespeicherten Hashes vergleichen. HMAC erschwert diesen Angriff bei einem ausreichend starken, geschützten Schlüssel. Die Zuordnung bleibt trotzdem personenbezogen, solange ein Bezug zum Konto möglich ist.