Markus Baersch

Software · Beratung · Lösungen

Start » Blog » Analytics / PHP / Trackingschutz

16.10.2019

Nachdem der Sinn und Unsinn sowie die Herausforderungen von cookielosem Tracking im ersten Teil der Serie behandelt wurden, wird es Zeit für einen Praxisfall anhand von Google Analytics. Wie auch andere Webanalysesysteme kann nämlich auch Google Analytics auf die Verwendung von Cookies verzichten. Und wie alle anderen ist dann das heikle Thema der Identität nicht mehr in der Hand von Cookies, sondern muss an anderer Stelle verwaltet werden. Während das eine oder andere System dann von selbst oder per Option steuerbar auf andere Wege wie localStorage oder Fingerprinting ausweicht (oder Cookies damit gegen Trackingschutz und Cookielöschung ergänzt), liegt im Fall von Google Analytics die Verantwortung zu 100% beim Websitebetreiber. Aber fangen wir ganz vorn an...

TL;DR

Vorbemerkung: Ja, man kann GA ohne (analytics-eigene) Cookies betreiben. Hier wird auch beschrieben, wie das geht. Es ist allerdings nicht zu erwarten, dass damit Consent-Problemen aus dem Weg gegangen werden kann. Ich selbst nutze es z. B. derzeit nur zu Testzwecken und um ITP aus dem Weg zu gehen. Nach wie vor wird der Analytics-Trackingcode von Google im Browser bezogen. Daher ist dieses Verfahren für Tracking ohne Consent ziemlich sicher _keine_ Lösung. Das wollte es gleich am Anfang loswerden. Gegen ITP hilft es aber je nach Gestaltung des eigenen Weges zur Verwaltung einer Client ID durchaus. Zu 100%. Wer jetzt immer noch wissen will, wie es geht (und welchen Unterschied es ausmacht), darf gern weiterlesen 😉

Google Analytics ohne Cookies

Seit ITP angefangen hat, auch First-Party-Cookies zu attackieren, erfreuen sich alternative Wege zur Verwaltung und Übergabe einer clientId an den Google Analytics Trackingcode steigender Beliebtheit. Für UA-Tags im Google Tag Manager, Universal Analytics oder gtag.js existieren Optionen zur Übergabe der clientId oder um Cookie Updates zu unterbinden. Allen Lösungen gemeinsam ist aber (meistens), dass parallel zu einer sichereren oder zumindest alternativen Speichermethode weiterhin das _ga-Cookie und seine Begleiter im Einsatz sind. Ob diese nun (je nach Aufgabe und Lösung) seltener aktualisiert werden oder nicht: sie existieren noch.

Das ist durch eine weniger verbreitete Option aber zu verhindern. Ein Abschnitt in der Referenz von Universal Analytics benennt die Option. Das Zauberwort zum Abschalten heißt storage : 'none' und in den folgenden Abschnitten wird auch gleich gezeigt, dass und wie man die clientId dann selbst verwalten muss. Auch das Abschalten der Cookies nach dem Muster _gac_12345678-9 ist möglich mit storeGac: false. Alle benötigten Felder - clientId, storeGac und storage - können bei der Initialisierung eines Google Analytics Trackingcodes oder eines UA-Tags im Google Tag Manager verwendet werden, um Cookies zu deaktivieren und die Identität selbst zu verwalten.

Beispiel für Universal Analytics

Ein angepasster UA - Trackingcode hat folgenden Aufbau. Wir unterstellen dabei, dass die zu übergebende Client ID in der globalen Variable window._clientId zu diesem Zeitpunkt zur Verfügung steht. Wie sie dahin kommen könnte, klären wir danach ;).

Hinweis: Ich habe auch allen erforderlichen Code der Beispiele auf Github abgelegt.

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-12345678-1', 'auto', 
{'storage':'none', 
 'storeGac' : false, 
 'clientId': window._clientId}
);
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');

Der Unterschied zu einem normalen Code (inkl. IP-Anonymisierung) steckt in der markierten Inititialisierung des Trackers. Hier werden die o. a. Felder verwendet, um Cookies abzuschalten und die Client ID selbst zu definieren.

Woher kommt die Client ID?

Das ist genau die Kernfrage, der wir uns im ersten Teil gewidmet haben. Gehen wir also die dort genannten Optionen durch. Offensichtliche Alternativen wie localStorage oder andere Browserspeicher sind dabei zwar einsetzbar, aber kein wirklicher Ausweg aus der "Cookie-Falle". Weil sie weder das Consent- noch das Trackingschutzproblem lösen. Den Anfang machen die ggf. bestehenden oder selbstverwalteten Cookies.

Bestehende oder eigene (Session-) Cookies

Der zweifelsfrei üblichste Weg zur Speicherung von Informationen zwischen zwei oder mehr Seitenaufrufen ist und bleibt ein Cookie. Wie jetzt? cookieloses Tracking und dann doch ein Cookie? Ja, vielleicht. Denn wie schon im ersten Beitrag beschrieben mag es Umstände geben, unter denen ein Cookie trotz fehlendem Consent nutzbar und / oder systembedingt unvermeidbar ist. Wenn hier Identität bezogen werden kann (sei es nur für die Sitzung oder darüber hinaus), geschieht das Tracking mit Analytics zweifelsohne ohne (eigene) Cookies. Dieses Detail ist durchaus hinsichtlich Cookie-Consent (wir erinnern uns: nicht unbedingt gleich Tracking Consent) und  Datenschutz ein Unterschied zur normalen Nutzung. Denn mit _ga-Cookie können sowohl Google als auch andere Dienste Zugriff auf den Cookiewert nehmen und kennen auch dessen Zweck. Problemfeld Profilbildung und so weiter. Hatten wir ja schon alles. Mit einem httpOnly Cookie in Eigenregie sieht das schon anders aus. Oder vielleicht auch mit einem vergleichweise harmlosen Session Cookie, das man selbst erzeugt.

Cookie oder Sitzung im Browser selbst erzeugen

Der einfachste Fall ist das Setzen eines ID-Cookies z. B. nur für die Sitzung direkt per JavaScript unmittelbar vor der Nutzung durch den Trackingcode. Was freilich nur die Identifizierung für die Lebensdauer der Sitzung erlaubt, aber dennoch ggf. eine Lösung ist, die unter bestimmten Umständen als letzte Option immer noch besser ist, als nichts (oder nur Hits mit stets neuer zufälliger ID) zu messen. Wie man ein Cookie setzt und liest, ist bei Stackoverflow ausreichend dokumentiert. Verzichten wir daher darauf und verwenden ersatzweise sessionStorage (weil es weniger Code braucht :)). Wer ein entsprechendes Beispiel sucht, findet es in der Sammlung zu diesem Beitrag auf GitHub.

Wer ITP aus dem Weg gehen will, setzt ein Cookie hingegen lieber serverseitig und / oder nutzt die bestehende PHP Session und deren Cookie, wenn es im Browser gelesen werden kann und nicht httpOnly ist (s. u.).

Serverseitiger Zugriff...

Komplizierter wird das Ganze, wenn eine ID in einem Cookie steckt, das nicht direkt per JavaScript gelesen werden kann. Das kann ein selbsterstelltes Cookie sein (ein Beispiel folgt im nächsten Beitrag der Serie) oder z. B. auch die o.g. PHPSESSID des Servers, die ggf. bereits vorhanden ist. Ist dieses Cookie als Secure und httpOnly (und ggf. noch samesite) erstellt worden, kann es nur vom Server be- und verarbeitet werden. Das ist nicht die Regel, aber durchaus möglich und für dieses Beispiel nehmen wir diesen Fall nun an. Denn es bedeutet, dass wir den Wert nicht direkt lesen, sondern den Server danach fragen müssen. Und dieses Prinzip ist dann natürlich nicht nur auf Cookies, sondern auch Fingerprints oder andere IDs anwendbar, die man vielleicht von seinem Server beziehen kann (bis hin zur ID eines bekannten, weil angemeldeten Benutzers des eigenen Systems). Dabei ist man nicht auf PHP beschränkt; das folgende kurze Code-Beispiel nutzt es aber.

Bevor wir fragen können, muss jemand da sein, der die Frage versteht und eine Antwort liefert. Das kann je nach System ein bereits bestehender Endpunkt sein oder man pflegt diesen per Plugin nach. Wir erzeugen für das Beispiel einen einfachen PHP-Zweiteiler auf dem eigenen Server, nennen diese Datei z. B. "getclient.php" und rufen sie später auf, um die ID zu erhalten. Zu Demozwecken steuern wir hier die Optionen des Session Cookies selbst. Diese Arbeit kann man sich bei einem bestehenden System sparen, wenn es ohnehin schon eine Session erzeugt. Mehr dazu in den Kommentaren im Beispielcode zu getclient.php auf Github.

session_start(['cookie_secure' => true, 'cookie_httponly' => true, 'cookie_samesite' => true]);
echo session_id();

Das war schon alles. Jetzt muss die ID nur noch abgerufen werden, bevor sie für das Tracking nutzbar ist.

... und Abruf im Client

Das fällt etwas komplexer aus, da der Vorgang "asynchon" ist. Ist keine ID da, muss diese angefordert werden und erst dann kann das Tracking stattfinden. Auch hier sei auf die Variante 2 aus dem Beispielcode verwiesen. Nach gleichem Vorbild können theoretisch auch alle anderen Cookies verwendet werden. IDs für Sessions und User muss man dazu nur suchen und finden, wie z. B. erforderlichem Speicher für das eingesetzte Shopsystem oder auch Cookies der Consent Manager, wie im ersten Teil schon beschrieben.

Was ist mit dem Google Tag Manager?

Im Fall des Trackings via Google Tag Manager wird eine Id nach ihrem Abruf statt an den Trackingcode einfach - z. B. über den dataLayer - an den GTM übergeben. Im ersten (einfacheren) Fall der Variante 1 kann die ID "synchron" gelesen oder generiert und sofort verwendet werden. Daher ist die Übergabe einfach zu erledigen: Nach Ausführen des Codes steht die ID ja in einer globalen Variable und kann im GTM als JavaScript Variable window._clientId eingelesen werden. Selbst Code zur Verwaltung der (Session-) ID kann der GTM selbst ausspielen, bevor dann das Tracking stattfindet.

Wenn erst der Server befragt werden muss, steht an der per Kommentar markierten Stelle für den Trackingcode ersatzweise für den GTM ein Push in den dataLayer. Dabei wird die Client ID als Variable im dataLayer ablegt und idealerweise auch ein Event auslöst. Alle Tags müssen also warten, bis dieses Event stattgefunden hat, damit eine Client ID aus dem dataLayer oder der o. g. JavaScript Variable ausgelesen werden kann (Meint: Trigger müssen angepasst werden). Auch dies zeigt die Variante 2 des Beispielcodes auf Github.

100% cookielos (AKA Fingerprinting)

Nach dem ganzen Zinnober zum serverseitigen Auslesen eines Cookies und der Weitergabe an den Trackingcode (und / oder den dataLayer, wenn der Tag Manager im Spiel ist), ist das Thema "Fingerprinting" nun schnell abgehandelt: Es funktioniert genau wie im zweiten Fall, in dem ein Cookiewert vom Server erfragt werden muss. Es kann zwar auch direkt im Browser ein Fingerabdruck gebildet werden, aber da dies erstens u. U, viel Zeit benötigt und zudem durch Browser absichtlich erschwert wird, setzen wir auf eine serverseitige Variante.

Tauscht man dazu die PHP Datei getclient.php auf dem Server aus und liest hier kein Cookie, sondern bildet einen Fingerprint oder nutzt andere Mittel, eine Kennung zu erzeugen, bleibt der Rest komplett gleich. Bevor wir über Ethik und Grenzen von Fingerprinting, Datenschutz oder andere Aspekte diskutieren: Wir folgen exemplarisch dem Beispiel von Matomo und nutzen anonymisierte IP, den User Agent sowie die Sprache des Browsers. Auf Plugins verzichten wir, es geht um das Prinzip und mehr Signale senken nur die Wahrscheinlichkeit von Gleichheit bei mehreren Clients, aber eliminiert sie nicht. Das ist allein deshalb unvermeidlich, weil mehrere Besucher mit der gleichen anonymisierten IP in der Realität vorkommen können. Nutzen diese auch noch (weil z. B. im selben Unternehmen) Systeme und Browser, die zu übereinstimmenden User Agents führen, wird der gleiche Abdruck entstehen.

Generell kann man mit der gewählten Methode und den genutzten Merkmalen vielleicht die Nutzbarkeit hinsichtlich Datenschutz beeinflussen... oder auch nicht. Wir werden es sehen. Der Code der beispielhaften Generierung einer Id findet sich bei Github als getclient2.php. Darin enthalten sind ein paar Hinweise zum Verfahren der Generierung eines Schlüssels (in diesem Fall ein Hash) und dem daraus resultierenden Schutz der zur dessen Bildung verwendeten Informationen. Ganz ehrlich: ob ein Hash nun die dadurch repräsentierten Daten ausreichend schützt oder ob es reicht, "nur" die anonymisierte IP zu verwenden, ist bestimmt strittig. Vor allem, wenn man es mit den "billigen" Mitteln des Beispielcodes versucht. Matomo macht es vermutlich ganz anders und (hoffentlich) viel sicherer. Mir ging es primär darum, das Prinzip zu verdeutlichen. Ob das so aber im Licht einer angepassten Rechtslage Bestand haben wird, werden wir am Beispiel von Matomo viel besser beobachten können.

Nutzbarkeit und Nutzen

Cookieloser Betrieb von Google Analytics ist also streng genommen nicht schwierig. Die Komplexität kommt erst mit der Anforderung, eine Client ID zu erhalten, zu verwalten und zu nutzen. Mit der "Qualität" und Lebensdauer der dabei verwendeten Identität steigt oder fällt der Nutzen der damit in der Webanalyse verbundenen Daten. Ob Session Cookies / kurzlebige Cookies wie bei Piwik PRO oder ein Fingerprint nach Beispiel von Matomo: Schlussendlich sind ggf. Anpassungen erforderlich oder auch diese Verfahren können ohne Consent nicht mehr betrieben werden. Der Punkt ist: Wir wissen es hier und jetzt nicht. Trotzdem kann man über die "Cookiefrage" hinaus ein paar Stärken und Schwächen dieser Lösung ausmachen - unabhängig davon, dass sie als "Ersatztracking" ohne Consent wohl eher nicht geeignet sein wird.

Vorteile

  • Eigene Verwaltung des Clients schützt z. B. je nach Gestaltung wirksam vor Safaris Trackingschutz ITP
  • Wenngleich ITP damit "besiegt" ist, ist der dahinter liegende Zweck doch erfüllt: Die Id bleibt für andere Augen "unsichtbar"
  • Selbst mit einem eigenen Cookie ist der ominöse Nutzen für Google zu Werbezwecken etc. deutlich minimiert, weil die Identität für (andere) Scripts im Browser nicht greifbar ist. Natürlich sind globale Variablen sichtbar, aber da diese heißen und enthalten können, was immer sie wollen, ist der faktische Nutzen für die üblichen "Cookiesammler" gleich Null
  • Von der Client ID abgesehen ist das Tracking und die Sammlung von Informationen / Dimensionen nicht eingeschränkt
  • Damit einher geht die "volle Kompatibilität" zu anderen Systemen, die angebunden werden können und die Daten nutzen
  • Geringer Aufwand bei der Umsetzung: An zentraler Stelle einsetzbar - bei der Intitialisierung des Trackingcodes bzw. in der Einstellungsvariable im Google Tag Manager. Alles andere funktioniert nach wie vor wie gewohnt

Nachteile

  • Bei serverseitg verwalteten und nicht in einem Cookie direkt im Browser sichtbaren IDs kommt ein Timingfaktor hinzu
  • Es ist unwahrscheinlich, dass das Eliminieren der Google Cookies wirklich etwas daran ändert, ob und wie ohne Consent noch ein Einsatz möglich ist
  • Es werden immer noch die Trackingscripts von Google geladen und genutzt. Im Browser hat sich also außer der Verantwortung für die ID nichts geändert
  • ETP in Firefox oder der Trackingschutz in Edge sowie andere Blocker-Mechanismen können daher immer noch verhindern, dass die Scripts überhaupt geladen werden
  • Wie alle Lösungen mit eigener Identität sinkt der Nutzen, wenn deren Lebensdauer - z. B. durch fehlende Berechtigungen - auf einen kleinen Zeitraum oder nur eine Sitzung eingeschränkt wird.

In Summe ist diese Option des Trackings mit Google Analytics aus rechtlicher Sicht vermutlich nicht oder nur geringfügig besser als bei normaler Installation. Aber es sollte zumindest klar sein, dass der Verzicht auf Cookies eigentlich kein Merkmal ist, das eine Lösung automatisch "datensicherer" macht. Es bleibt zu hoffen, dass der Unterschied zwischen Consent und kein Consent im Tracking am Ende darauf hinausläuft, wie und für wie lange dabei die gleiche "Identität" genutzt wird und wie sie ermittelt werden darf. Und natürlich mit welchen Mitteln, denn da hat Google Analytics sicherlich - und sei es auch nur in der Wahrnehmung im Umfeld des Datenschutzes - eine gewisse Sonderstellung.

Einen Schritt weiter geht dementsprechend der Rückzug des Trackings aus dem Browser; also serverseitigem Tracking. Das kann - in der einen oder anderen Weise - auch mit Google Analytics umgesetzt werden. Genau das ist Gegenstand des dritten Teils dieser Serie.

© 2001 - 2019 Markus Baersch