Zum Hauptinhalt springen

Google Analytics ohne Cookies nutzen

Datenschutzorientiertes, cookiefreies Tracking mit Google Analytics durch die Nutzung des Measurement Protocols.

Seit Start der DSGVO bin ich auf der Suche nach einer cookiefreien Google Analytics-Alternative. Mich interessiert, welche Seiten meines Blogs aufgerufen werden, woher die Besucher stammen und seit dem Relaunch meines Blogs auch, welche Sprache sie sprechen. Außerdem möchte ich die Daten in aggregierter Form betrachten können, beispielsweise als einfaches Dashboard. Und da mein Blog nur mein Privatvergnügen ist, habe ich keine Lust, jeden Monat Unmengen an Geld für die Analysedaten zu bezahlen. All das ist mit Google Analytics einfach umsetzbar – wäre da nicht die DSGVO.

# Das Problem

Möchte ich Google Analytics datenschutzkonform einsetzen, benötige ich die Zustimmung der Besucher. Also klatsche ich einem neuen Nutzer direkt ein Banner vor die Nase, “Zustimmen” oder “Ablehnen” als Möglichkeiten. Nur um anschließend seine Daten an Google zu geben und ihn verfolgbar auf zahlreichen Webseiten zu machen.

Weiterer Nachteil: Immer mehr Menschen sind mit Erweiterungen wie Ghostery unterwegs, die Google Analytics direkt beim Seitenaufruf wegblocken. Spätestens mit der Weiterentwicklung der Browser (wie der Intelligent Tracking Prevention in WebKit) werden die Daten immer weniger zuverlässig.

Alternativen zu Google Analytics gibt’s einige: Direkte GA-Konkurrenten wie Simple Analytics, Plugins wie Statify oder Umstieg auf Server-Log-Analysetools, z.B. mit Netlify Analytics. Die meisten von denen kosten allerdings und beschränken mich auf die mit dem entsprechenden Tool gesammelten Daten. Ich bin großer Fan des Google Data Studios, damit ich gleichzeitig auch Daten der Search Console und von anderen Quellen auswerten kann.

Sogar Experimente mit Firestore habe ich hinter mir. Mit eigenem Trackingpixel habe ich dort die Nutzerdaten hinterlegt – allerdings muss ich dann ALLES selber bauen. Vom einfachen Bot-Filter, über die Einsortierung der Quellen in Channels bis zur Schnittstelle mit dem Data Studio.

Ich will also Google Analytics – nur ohne Cookies und DSGVO-konform.

# Möglichkeit 1: Standardeinbindung mit Parametern

Auch mit der Standardeinbindung von Google Analytics ist ein cookiefreies Tracking möglich. Dazu müssen lediglich zwei Parameter händisch gesetzt werden:

ga('create', 'UA-XXXXX-Y', {
'storage': 'none',
'storeGac': 'false',
'anonymizeIp': 'true'
});

Damit werden von GA keine Cookies mehr gesetzt und die IP des Nutzers wird innerhalb der GA-Library gekürzt und erst dann übermittelt. Vom Datenschutz her also ein guter Anfang. Geladen werden trotzdem die vollen 40kb an Gtag.js - das geht besser. Und was Google im Hintergrund mit dem Skript noch alles sammelt, möchte ich gar nicht erst wissen 😄

# Das Tracking beschränkt sich auf Pageviews

Um den kompletten Browse-Verlauf eines Nutzers zu speichern, müsste ich einem Nutzer mehrere Pageviews zuordnen. Klappt auch mit dem Measurement Protocol – ich müsste allerdings eine User-ID als Cookie oder im LocalStorage ablegen, um die Variable über mehrere Seitenaufrufe hinweg kostant zu halten. Das widerspricht aber meinem Grundgedanken, komplett auf Cookies (und auch auf den LocalStorage) zu verzichten.

Stattdessen generiert jeder Pageview eine neue User-ID und startet quasi bei jedem Seitenwechsel eine neue Session. Das bedeutet: Kein Seitenfluss, keine Anzahl an Nutzern (die wird zwar dargestellt, ist aber gleich den Pageviews), keine Einstiege oder Absprünge. Jeder Pageview ist ein neuer Einstieg und jeder Seitenwechsel bedeutet einen Absprung.

# Möglichkeit 2: Measurement Protocol

Option 2 ist das Measurement Protocol. Dahinter versteckt sich nichts anderes als eine Schnittstelle zur Übermittlung von Rohdaten als HTTP-Request. Wer mit dem Measurement Protocol spielen möchte, der kann sich mit dem Hit Builder austoben.

Die Lösung des cookiefreien Google Analytics-Skripts besteht also in einem Request, in welchem ich einen Grundschatz an Nutzerdaten verpacke und diesen an das Measurement Protocol weitergebe. Ich habe mich für diese Daten entschieden:

  1. User-ID (Voraussetzung von Google für einen gültigen Request)
  2. Useragent (Zur Filterung von Bot-Traffic)
  3. Seitentitel
  4. URL
  5. Referrer
  6. Eingestellte Sprache

Damit werden nur die für mich wirklich notwendigen Daten für eine vernünftige Analyse übertragen. Die User-ID wird komplett zufällig pro Seitenaufruf gesetzt. Und das alles in 17 Zeilen Javascript:

if ("sendBeacon" in navigator) {
navigator.sendBeacon(
"https://www.google-analytics.com/collect",
new URLSearchParams([
["v", "1"],
["t", "pageview"],
["tid", "UA-XXXXXXXX-X"],
["aip", "1"],
["cid", `${new Date().getTime()}${Math.random()}`],
["dt", document.title],
["dl", location.href],
["dr", document.referrer],
["ul", navigator.language],
["ua", navigator.userAgent],
]).toString()
);
}

# Kein IE

Der Internet Explorer versteht kein Senden per Beacon API. Kann man umgehen (per Fetch API statt Beacon), aber diese Variante ist deutlich performanter.

# Keine Zielgruppenanalyse

Ich übertrage nur ein grundliegendes Gerüst an Informationen. Da ich Google nicht genug Informationen gebe, um mehrere Pageviews miteinander zu verketten und damit auch kein seitenübergreifendes Tracking möglich ist, stehen mir auch keine Informationen zur Zielgruppe zur Verfügung. Bedeutet: Keine demografischen Daten, kein Standort, keine Interessen und keine Netzwerkinfos. Könnte man mitgeben, widerspricht aber dem Grundgedanken.

# Ausführlicheres Tracking ist nur sehr umständlich möglich

Zwar lassen sich auch Ereignisse über das Measurement Protocol übermitteln, die Option wäre aber sehr umständlich. Wer auf ausführliches Tracking angewiesen ist, der ist bei dieser Lösung falsch und sollte eher den Google Tag Manager mit individualisierten Triggern und Events nutzen.

# Möglichkeit 3: Measurement Protocol mit Proxy-Skript

Um den Nutzer komplett von Google zu entkoppeln, setze ich jetzt noch ein Skript dazwischen. Statt direkt an https://www.google-analytics.com/collect wird der Request also an einen Punkt auf meinem Server geschickt, der die Angaben dann erweitert und weiterschickt. Aus dem vorherigen Skript wird damit eine noch kürzere Version:

if ("sendBeacon" in navigator) {
const data = JSON.stringify({
title: document.title,
url: location.href,
ref: document.referrer,
language: navigator.language,
useragent: navigator.userAgent,
});
navigator.sendBeacon("/.netlify/functions/pixel", data);
}

Zur weiteren Verarbeitung nutze ich eine Netlify Serverless Funktion - klappt aber auch genauso gut mit PHP, Hauptsache, irgendwie kommen die Daten bei Google an. Google erhält damit ausschließlich die Daten, die ich vom Server weiterleite. Meine Netlify-Funktion schaut so aus:

const fetch = require("node-fetch");

exports.handler = async (event) => {
if (event.httpMethod !== "POST") {
return {
statusCode: 405,
body: "Method Not Allowed",
};
}
if (event.body == null) {
return {
statusCode: 400,
body: "Bad Request",
};
}
const body = JSON.parse(event.body);
const endpoint = "https://www.google-analytics.com/collect?";
const payload = new URLSearchParams([
["v", "1"],
["t", "pageview"],
["tid", "UA-XXXXXXXX-X"],
["aip", "1"],
["cid", `${new Date().getTime()}${Math.random()}`],
["dt", body.title],
["dl", body.url],
["dr", body.ref],
["ul", body.language],
["ua", body.useragent],
]);

try {
const response = await fetch(endpoint + payload, {
method: "POST",
cache: "no-cache",
});
if (response.ok) {
return {
statusCode: response.status,
body: response.statusText,
};
}
} catch (err) {
console.error("Error: " + err);
}
};

# Bonus: Data Studio-Vorlage

Die Daten laufen mit diesen beiden Dateien schon sauber in Google Analytics ein und können dort wie gewohnt gefiltert und ausgewertet werden. Ich bin aber ein Fan vom Google Data Studio, also habe ich mir ein passendes Dashboard mit den übertragenen Daten und den Suchanfragen aus der Search Console gebastelt.

Das Data Studio kannst du dir hier anschauen und kopieren. Einfach die Datenquellen tauschen und schon hast du einen guten Startpunkt für dein eigenes Data Studio.