LW IT Solutions
« Blog Overview /Data Privacy/Tutorials / Tutorial: Personenbezogene Daten in GA4-Seitenpfaden finden und...
This post in other languages:

Tutorial: Personenbezogene Daten in GA4-Seitenpfaden finden und entfernen

Tutorial: Personenbezogene Daten in GA4-Seitenpfaden finden und entfernen
Inhalt
  1. Was in einem Seitenpfad personenbezogen ist
  2. Die Seitenpfade aus der Property holen
  3. Die Muster, nach denen sich zu suchen lohnt
  4. Am Stream schwärzen statt im Tag
  5. Der bereits gespeicherte Bestand
  6. Was der Suchlauf nicht sieht
  7. Quellen

Personenbezogene Daten gelangen nicht durch eine Entscheidung in eine Analyse-Property. Sie gelangen dorthin, weil ein Formular per GET statt per POST absendet, weil ein Link zum Zurücksetzen des Passworts eine Adresse trägt oder weil ein Suchfeld das Eingetippte in die Adresse schreibt.

Nichts in der Oberfläche meldet das. Der Seitenpfad ist bloss eine Dimension, und ein Pfad mit einer Mailadresse sieht in einer Liste von viertausend aus wie jeder andere. Ihn zu finden kostet eine Abfrage und sechs Muster; ihn loszuwerden kostet zwei getrennte Massnahmen, denn das Leck und der gespeicherte Bestand sind verschiedene Aufgaben.

Eine Adresse mit Mailadresse auf dem Weg vom Browser über Tag und Datenstream in die Property und den Bericht, die zwei Stellen zum Schwärzen markiert, daneben eine Tabelle der Fundstellen
Zwei der fünf Stationen können den Wert noch entfernen. Ab der vierten ist er gespeichert, und daran ändert nur ein Löschauftrag etwas.

Was in einem Seitenpfad personenbezogen ist

Die offensichtlichen Fälle sind Mailadressen und Telefonnummern. Die weniger offensichtlichen bereiten mehr Ärger, denn sie werden gar nicht als personenbezogen erkannt.

Eine Bestellnummer ist personenbezogen, sobald sie sich in einem anderen System zu einer Person auflösen lässt – und das lässt sie sich meistens. Ein Token zum Zurücksetzen eines Passworts ist nicht personenbezogen, aber ein Geheimnis, und ein Geheimnis in einem Analysebericht steht jedem offen, der die Property lesen darf. Ein Suchbegriff ist personenbezogen, sobald Leute den eigenen Namen oder die eigene Adresse in das Suchfeld tippen – in einem Shop mit Bestellsuche täglich.

Allen gemeinsam ist der Weg über die Adresse, und die Adresse erreicht GA4 vollständig. Alles hinter dem Fragezeichen wird Teil der Seitendimension, und das Fragment hinter der Raute ist der einzige Teil, der den Browser nie verlässt.

Die Seitenpfade aus der Property holen

Die Data API liefert dieselben Dimensionen wie die Berichte, ohne deren Zeilengrenzen. Eine Anfrage über einen langen Zeitraum bringt alles zurück, was je erfasst wurde.

curl -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/123456789:runReport" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges":  [{ "startDate": "395daysAgo", "endDate": "today" }],
    "dimensions":  [{ "name": "pagePathPlusQueryString" }],
    "metrics":     [{ "name": "screenPageViews" }],
    "limit": 100000,
    "orderBys": [{ "metric": { "metricName": "screenPageViews" }, "desc": true }]
  }'

Drei Einzelheiten entscheiden, ob das Ergebnis vollständig ist. Die Dimension muss die mit der Abfragezeichenfolge sein – pagePath allein schneidet genau den Teil ab, in dem die Daten üblicherweise stecken. Der Zeitraum sollte so weit zurückreichen, wie die Property Daten vorhält, denn ein vor einem halben Jahr behobenes Leck steckt weiterhin in den gespeicherten Zeilen. Und eine Property mit vielen Pfaden braucht Seitenaufteilung: Die Antwort trägt eine Zeilenzahl, und alles jenseits der Grenze verlangt eine zweite Anfrage mit Versatz.

Ein Wort zum Kontingent. Die API rechnet Marken je Property und Tag ab, und eine Abfrage über vierhundert Tage mit hunderttausend Zeilen ist nicht umsonst. Sie einmal im Quartal zu fahren, ist sinnvoll; sie beim Entwickeln in einer Schleife zu fahren, verbraucht das Tageskontingent an einem Nachmittag.

Die Muster, nach denen sich zu suchen lohnt

Sechs Muster decken fast jede Fundstelle ab, und sie gehören auf die rohe und auf die dekodierte Form des Pfads angewandt – denn eine Adresse kommt ebenso oft als %40 an wie als @.

import re, urllib.parse

MUSTER = {
    "mail":       re.compile(r"[\w.+-]+@[\w-]+\.[\w.]{2,}"),
    "mail_kod":   re.compile(r"[\w.+-]+%40[\w-]+"),
    "telefon":    re.compile(r"(?:\+|00)\d{7,15}|\b0\d{8,13}\b"),
    "schluessel": re.compile(r"[?&](?:token|hash|auth|key|sig|pwd|password)=", re.I),
    "namensfeld": re.compile(r"[?&](?:name|vorname|nachname|first|last|user)=", re.I),
    "suche":      re.compile(r"[?&](?:q|s|search|query)=", re.I),
}

def pruefe(pfad):
    formen = {pfad, urllib.parse.unquote(pfad)}
    return {name for name, m in MUSTER.items() if any(m.search(f) for f in formen)}

Die letzten beiden verlangen einen zweiten Blick, bevor etwas gemeldet wird. Ein Parameter namens name trägt oft einen Produktnamen und keine Person, und ein Suchparameter ist nur dann ein Problem, wenn Leute Personenbezogenes hineinschreiben – das klärt das Lesen von zwanzig echten Werten, nicht der Parametername.

Das Telefonmuster erzeugt die meisten Fehltreffer von allen: Bestellnummern, Artikelnummern und Daten der Form 20260920 passen allesamt auf eine lange Ziffernfolge. Es auf die Parameter einzugrenzen, in denen es auftritt, statt auf den ganzen Pfad, beseitigt das grösstenteils.

Am Stream schwärzen statt im Tag

Liegen die Fundstellen vor, wird das Leck an der frühesten beherrschbaren Stelle geschlossen. GA4 bietet das am Datenstream selbst an, und es gilt für alles, was der Stream empfängt, unabhängig davon, welches Tag gesendet hat.

Die Einstellung sitzt in der Verwaltung beim Web-Datenstream in den Tag-Einstellungen unter Daten schwärzen. Sie besteht aus zwei Teilen: einem automatischen Entfernen von allem, was wie eine Mailadresse aussieht, und einer Liste von Parameternamen, deren Werte vor dem Speichern ersetzt werden.

token, hash, auth, key, sig, pwd, password,
email, mail, e-mail, user, username,
phone, tel, mobile,
name, firstname, lastname

Diese Liste gehört an dieselbe Stelle wie die Ergebnisse des Suchlaufs und sollte nachgezogen werden, sobald der Lauf einen neuen Parameter findet. Das Schwärzen arbeitet exakt: Ein Parameter, der auf einer Seite anders geschrieben ist – e_mail statt email -, geht unberührt hindurch.

Zwei Bemerkungen zur Einordnung gegenüber den anderen Wegen. page_location im Tag-Manager zu überschreiben funktioniert auch und greift früher, aber nur für die Treffer dieses einen Tags; ein zweites Tag oder ein fest im Theme stehender gtag-Aufruf umgeht es. Das Bereinigen in einem Servercontainer ist der stärkste Weg und der einzige, der auch die Weitergabe an Werbeplattformen schützt – eine eigene Arbeit mit eigenem Artikel. Die Stream-Einstellung ist die, die zehn Minuten kostet und alles abdeckt.

Der bereits gespeicherte Bestand

Das Schwärzen gilt für Treffer von jetzt an. Es ändert nichts an den Zeilen, die bereits in der Property liegen – und genau die zählen für eine datenschutzrechtliche Frage.

Was sie entfernt, ist ein Löschauftrag, in der Verwaltung auf Ebene der Property. Der einschlägige Typ löscht ausgewählte Parameter über alle Ereignisse hinweg, und die Seitenadresse ist einer dieser Parameter.

Drei Eigenschaften dieses Verfahrens lohnen sich vor dem Auslösen zu kennen. Es hat eine Wartezeit von einigen Tagen, in der es sich zurücknehmen lässt – das ist Absicht und nützlich. Einmal angelaufen, dauert die vollständige Anwendung bis zu etwa zwei Monaten. Und es ist unumkehrbar: Die Seitendimension dieses Zeitraums ist danach fort, auch für die unbedenklichen Pfade, wenn der Auftrag den ganzen Parameter umfasste.

Was der Auftrag nicht anfasst, ist der BigQuery-Export. Daten, die vor der Löschung exportiert wurden, liegen in einem Datensatz, über den die Property keine Verfügung mehr hat, und dort sind sie eigens zu entfernen – eine DELETE-Anweisung oder eine neu gebaute Tabelle, für denselben Zeitraum.

UPDATE `projekt.analytics_123456789.events_*`
SET event_params = ARRAY(
      SELECT AS STRUCT
        p.key,
        IF(p.key = 'page_location',
           STRUCT(REGEXP_REPLACE(p.value.string_value,
                  r'([?&](?:email|token|phone)=)[^&]*', r'\1[entfernt]')
                  AS string_value, p.value.int_value,
                  p.value.float_value, p.value.double_value),
           p.value) AS value
      FROM UNNEST(event_params) AS p)
WHERE _TABLE_SUFFIX BETWEEN '20260101' AND '20260920';

Was der Suchlauf nicht sieht

Drei Orte tragen dieselbe Art von Daten und tauchen in diesem Bericht nicht auf.

Der erste sind Ereignisparameter ausserhalb der Seitenadresse. Eine Formularmessung, die den eingegebenen Wert als Parameter sendet, legt ihn in eine benutzerdefinierte Dimension, und der obige Lauf schaut dort nie hin. Dieselbe Data-API-Abfrage mit der benutzerdefinierten Dimension anstelle des Seitenpfads findet ihn, und diese Abfrage lohnt sich für jede angemeldete Dimension einmal.

Der zweite ist das Feld für die Nutzerkennung. Eine Property, die eine Nutzerkennung empfangen soll und stattdessen eine Mailadresse bekommt, ist ein Lehrbuchverstoss und in Berichten unsichtbar, weil das Feld in den meisten davon gar nicht erscheint. Die Prüfung ist dieselbe wie überall: die echten Werte ansehen, nicht den Feldnamen.

Der dritte ist alles, was das Haus schon verlassen hat. Gingen die Treffer auch an eine Werbeplattform, ändert das Schwärzen in GA4 nichts an der Kopie, die dort ankam – und diese Plattform hat ihren eigenen Löschweg. Die Liste der Empfänger lohnt sich vor dem ersten Löschauftrag aufzuschreiben, denn der Auftrag selbst erzeugt sie nicht.

Lukas Wojcik

Lukas Wojcik

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.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Kommentar schreiben

Die E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind mit einem Stern versehen.

ALL ARTICLES & CATEGORIES

CCTV

Diese Rubrik per RSS verfolgen

Cloud & AI

Diese Rubrik per RSS verfolgen

Data Privacy

Alle 13 Artikel dieser Rubrik Diese Rubrik per RSS verfolgen

Digital Analytics

Alle 50 Artikel dieser Rubrik Diese Rubrik per RSS verfolgen

Digital Marketing

Alle 30 Artikel dieser Rubrik Diese Rubrik per RSS verfolgen

IT & Networks

Alle 16 Artikel dieser Rubrik Diese Rubrik per RSS verfolgen

Music Production

Diese Rubrik per RSS verfolgen

Raspberry Pi

Diese Rubrik per RSS verfolgen

Smart Home

Alle 18 Artikel dieser Rubrik Diese Rubrik per RSS verfolgen

Web Entwicklung

Diese Rubrik per RSS verfolgen

WordPress-Plugins & Tricks

Diese Rubrik per RSS verfolgen