Markus Baersch

Software · Beratung · Lösungen

Suche im Blog

Sign In

Monday, 23 November 2015

Das Google Analytics Measurement Protocol: Dem Googlebot zuschauen (serverseitiges Tracking)

Dieser Beitrag ist Teil einer Artikelserie zum Measurement Protocol. Diesmal geht es wieder um den Kern von Analytics: Echte Webanalyse. Nur schauen wir nicht (nur) auf reale Besucher, sondern primär auf Bots, die sich naturgemäß sonst aus der Sache gern heraushalten. Statt Spambots auszuschließen, laden wir diesmal also Crawler ein, sich von uns über die Schulter schauen zu lassen.

Alle Teile dieser Serie

Serverside: Vor- und Nachteile

Wie im zweiten Beitrag angesprochen, kann man mit serverseitigem Tracking eine Menge Probleme umgehen. Nicht nur, aber auch das aktive Blockieren von Trackingmaßnahmen und die "Unsichtbarkeit" des Trackings sind für viele ein schlagendes Argument, auf diese Variante zu setzen.

Dafür werden Dinge plötzlich zu Problemen, die von Anbietern in diesem Bereich unterschiedlich angegangen werden müssen, während das clientseitige Tracking per JavaScript davon kaum betroffen ist. Der Cache des Browsers ist ein solcher Kandidat, denn eine vorher besuchte Seite wird damit nicht neu vom Server abgerufen, während das JavaScript-Tracking den Hit davon unbeeindruckt an die Webanalyse sendet. Proxies, CDNs etc. kommen als weitere Problemquellen dazu. Da wir uns hier aber nicht mit Problemen, sondern neuen Einsatzgebieten des Measurement Protocols befassen wollen, schieben wir diese Punkte erst einmal beiseite. Die meisten Sites betreiben ohnehin klassisches Tracking und auf diese Zahlen wollen wir auch gar nicht verzichten.

Serverside Tracking mit dem Measurement Protocol: Einsatzmöglichkeiten

Seitenaufrufe und Sitzungen der gleichen Website zu vergleichen, die sowohl client- als auch serverseitig gesammelt wurden, kann ungeachtet dieser Einschränkungen interessante Einblicke gewähren. Außerdem bekommen wir am Server alle Hits mit; also auch die vom geliebten Googlebot und anderer Besucher. Deren Spuren bleiben oft in nie ausgewerteten Serverlogs verborgen - das soll hier mit Hilfe von Google Analytics geändert werden.

Kein Ersatz für Logfileanalyse

Das folgende Beispiel soll möglichst alle Hits erfassen, die Seiten betreffen, welche von einem PHP-basierten CMS ausgeliefert werden. Das kann z. B. Wordpress sein. Alles andere wird allerdings dabei bewusst nicht abgedeckt. Nun besteht eine Website aber aus einer ganzen Menge an weiteren Dingen wie Bildern, Scriptfiles, CSS-Dateien, PDFs, Downloads und mehr. Während in einem Serverlog alle Zugriffe auf diese Ressourcen nachverfolgen lassen, beschränken wir uns auf "CMS-Inhalte" im weitesten Sinn. Durch andere Ansätze, die direkt am Server implementiert werden, können solche Lücken zwar geschlossen werden, aber im Sinne eines möglichst einfachen Beispiels begnügen wir uns mit dem, was das CMS ausliefert.

Ebenso kann anders als hier bei der Logfileanalyse auf Besonderheiten wie Zugriffe auf nicht vorhandene, nicht öffentlich zugängliche oder weitergeleitete URLs geschaut werden. Selbst mit diesen Einschränkungen kann ein "Bot-Tracking" über das Measurement Protocol viele spannende Fragen beantworten. Unter anderem:

  • Welche Bots kommen überhaupt auf meine Site?
  • In welcher Tiefe und Frequenz befasst sich der Googlebot (oder ein anderer) mit den Inhalten?
  • Wann wurde Seite x zuletzt von Bot y besucht?
  • Wie lange brauchen neue Inhalte, bis diese gefunden und besucht wurden?

Obwohl sich das unten stehende Implementierungsbeispiel primär auf Bots konzentriert, werden alle anderen Besucher mit getrackt und - zumindest zum Teil - anhand des _ga Cookies identifiziert, der für das klassische Tracking mit Analytics zuständig ist. Es wird also unterstellt, dass Analytics bereits genutzt wird. Ist das nicht der Fall, landen die "echten" Besucher alle in einem Segment für "Unbekannte" Hits.

Auch kein Ersatz für klassische Implementierung?

Nein, in dieser Form für die meisten Sites nicht. Das liegt an einer Einschränkung beim Tracking echter Besucher, die hier der Einfachheit halber nicht gelöst wurde: Der Einstieg eines Erstbesuchers. Dieser ist in diesem vereinfachten System problematisch, weil der zur Identifizierung erforderliche Cookie erst nach dem Aufruf der ersten Seite generiert wird. Ein Henne/Ei-Problem also. Das kann man lösen; es soll hier aber vereinfachend nicht beachtet werden. Für einen Vergleich von Zahlen reicht es zu wissen, dass ein Teil der Sitzungen "bekannter" Besucher im Segment für die "Unbekannten" steckt, so dass die Besuchsdauer, Anzahl der Seiten / Besuch und auch die Gesamtzahl aller Sitzungen direkt davon beeinflusst werden.

Für Portale oder Anwendungen, die hinter einem Login liegen, reicht das Beispiel hingegen schon aus, um alle Daten zu erheben, die bei der Auswertung normalerweise benötigt werden... solange es nicht um den Weg vor der Login-Seite geht.

PHP-Codebeispiel

Der folgende Code zeigt zwei Varianten einer abgeschlossenen Funktion, welcher als Parameter nur der Dokumenttitel übergeben werden muss, der beim Hit verzeichnet werden soll - diese Information hat man i. d. R. spätestens bei der Generierung des Footers einer Seite in einer Variable zur Verfügung. Ist der Titel unbekannt, wird die Funktion zur Not mit einem konstanten Titel versorgt... primär interessiert bei Besuchen von Bots ohnehin eher die URL. Die Variante A trackt alle Besucher, Variante B beschränkt sich auf Bots.

Was passiert da?

Zunächst benötigt die Funktion zur Konfiguration die Angabe der Profil-ID aus Analytics $ua und darunter als $segments ein Array von Angaben zu Bots, die zu einer eigenen "Quelle/Medium"-Kombination führen sollen. So sind diese später separat auszuwerten oder per Filter in eigenen Datenansichten zu sammeln.

Das "Bot-Array"

Weil ich jedem Bot eine eigene ID geben will und mein Gesang besser ist als mein PHP, habe ich vermutlich nicht die effizienteste Lösung gewählt, um Bots zu erkennen. Sie reicht (mir) aber aus. Im Array ist für jeden Bot ein Key/Value-Paar vorhanden, in dem der Key der cid eines eindeutigen Nutzers entspricht, so dass jeder Bot als separater Nutzer in Analytics gezählt wird. Der String-Value enthält zuerst den gewünschten "Klarnamen" des Bots, wie er später im "Medium" wieder zu finden sein soll und nach einem "::" als Trenner ein RegEx-Filtermuster, anhand dessen der Bot erkannt wird.

Dabei muss man sich mit Regular Expressions nicht großartig auskennen, denn alle Bots, die als solche erkannt werden wollen, nennen sich "IrgendwasBot" in der einen oder anderen Form, so dass man mit reinen Zeichenketten ohne RegEx-Besonderheiten auskommt. So enthält im Beispiel (außer Google und Baidu) keine der angegebenen Regeln mehr als nur den Namen des Bots aus dem User Agent in Klammern. Im Fall von Baidu gibt es zwei unterschiedliche Schreibweisen, die beide abgedeckt werden sollen. Zur Trennung von optionalen Zeichenketten als Treffer dient in RegEx ein "|". Die "komplexeste" Definition ist der Googlebot in der ersten Zeile mit dem Muster (Googlebot|Mediapartners-Google|AdsBot-Google), der damit alle Varianten abdeckt. In anderen Fällen möchte man ggf. differenzierter segmentieren und erstellt genauere Muster gemäß der Liste der User Agents, die Google verwendet. Wer bestimmte Bots im Sinn hat, aber nicht genau weiß, welche Kennung(en) diese nutzen, kann entweder nach dem Betreiber bzw. Bot inkl. "User Agent" googeln oder bei UserAgentString.com nachsehen, wo eine beachtliche Liste zu finden ist.

Im Fall der Domain, die unten in den Beispielauswertungen genutzt wird, werden z. B. die Besuche des darauf zielenden Monitors UptimeRobot und ein paar SEO-Tools wie Majestic und andere separat getrackt. Jede Domain wird eine eigene sinnvolle Definition benötigen. Um einzusteigen, reicht ein unverändertes Array und es muss nur eine passende Analytics-ID eingetragen werden, um mit Hilfe des Beispielcodes Daten zu erhalten.

Funktionsweise

Da Variante A dazu dienen soll, alle Besuche zu erfassen, wird zuerst über die oben definierte Funktion get_client_id() der Analytics-Cookie ausgelesen und - wenn vorhanden - die cid des bekannten Besuchers zurückgegeben. In diesem Fall landet der Besucher in einem Medium namens "Tracked Users". Auf diese Weise wird auf ein in der Website integriertes Analytics-Tracking aufgesetzt. Troubleshooting Tipp für ältere Fassungen von Analytics: Wenn auf der Website noch der gute alte pageTracker im Einsatz sein sollte, wird das nicht funktionieren und alle Besucher landen im "Unknown"-Segment. Daher muss die Funktion zur Ermittlung der Id angepasst werden, weil die gesuchten Angaben im Cookie ___utma und nicht in __ga gespeichert sind. Die entsprechende Zeile wie folgt anpassen: $cv = explode('.', $_COOKIE["__utma"]);

Ist damit der Ursprung des Requests nicht geklärt, wird danach die Bot-Erkennung versucht und daraus ggf. eine cid für den Nutzer und ein Medium ermittelt. Schlägt auch das fehl, wird der Einfachheit halber eine konstante cid=555 verwendet und das Medium mit "Unknown" belegt. An dieser Stelle könnte alternativ eine Zufallszahl als cid zum Einsatz kommen, was die Anzahl der Nutzer in Analytics deutlich verändern würde. Für dieses Beispiel reicht ein "Sammelnutzer" aus.

Get To Know "Unknown"

Ganz unbekannt ist nicht, wer hier landet. Es sind zum Einen alle Besucher der Website, die ein Plugin zur Blockierung von Tracking im Allgemeinen oder Analytics im Besonderen einsetzen. Auf meiner Website wären es - wenn das Script in unveränderter Form dort eingesetzt würde - auch alle, die sich im Footer gegen ein Tracking ausgesprochen haben. Eine Echtimplementierung sollte daher ggf. vorhandene Cookies mit Informationen der Wünsche des Besuchers berücksichtigen und ein Tracking unterlassen.

Ebenso finden sich in diesem Segment alle Bots und Crawler wieder, die sich nicht im User Agent String als solcher outen und wie ein normaler Besucher daherkommen. Das ist in manchen Fällen übrigens auch Google (genau: um Cloaking zu entdecken). Und schlussendlich kommen (leider) in dieser vereinfachten Implementierung auch die Aufrufe von Einstiegsseiten aller Erstbesucher dazu, die zu diesem Zeitpunkt noch keinen Cookie des noch auszuliefernden Analytics-Scripts verpasst bekommen haben. Was das bedeutet (und warum das nicht so schlimm ist, wie es klingt), wird unten bei den Auswertungen aus Analytics noch gezeigt. Typischer Ghost-Spam hingegen sollte in einem solchen Profil kaum auftauchen, wenn die Id der Property nicht zufällig vom Spammer erraten und auf gut Glück mit Spam beballert wird.

Übertragung des Pageview-Hits über das Measurement Protocol

Ist eine Entscheidung für ein Medium getroffen und eine Id bestimmt, werden URL der Seite und Referrer ermittelt, die Tracking-URL zusammengesetzt und mittels CURL an Analytics übertragen. Das ist nicht die ideale Lösung, aber es werden zumindest neben dem restlichen Aufwand nicht mehr als 50 Millisekunden investiert, um den Hit abzusetzen. Mit dem Wert für CURLOPT_TIMEOUT_MS kann man je nach Ausstattung des eigenen Servers noch spielen und den Wert so lange reduzieren, bis im Echtzeitbericht des beschickten Profils keine Daten mehr ankommen, wenn man parallel in einem zweiten Tab eine Seite auf der eigenen Site neu lädt (via STRG+F5).

Troubleshooting Tipp 2: Sollte das Ganze übrigens nach Implementierung nicht funktionieren, kann das an der eingesetzten PHP-Version liegen. Im Verdachtsfall die Zeile o. g. auskommentieren. Wenn dann Daten ankommen, auf CURLOPT_TIMEOUT umsteigen und als Wert "1" verwenden, denn in diesem Fall reden wir von Sekunden statt Millisekunden. Mehr als eine Sekunde will bestimmt niemand investieren.

Bei Variante B passiert im Prinzip genau das Gleiche, nur ist die Funktion auf die Bot-Erkennung reduziert und kümmert sich nicht um Cookies oder Besucher mit "normalen" User-Agent-Kennungen. Die Reduktion dient dabei dazu, möglichst keine Zeit zu verschwenden und keine Hits an Analytics zu senden, die für die Erfüllung der Aufgabe des Bot-Trackings nicht erforderlich sind. Die Konfiguration und alles andere stimmen komplett mit Variante A überein.

Was es zu beachten gibt

Wer die Funktion in ein eigenes System implementieren möchte, sollte auf jeden Fall ein separates Profil dafür in Analytics anlegen und gerade bei größeren Sites engmaschig kontrollieren. In vielen Fällen kommen auf diesem Weg schnell sehr viele Daten zusammen, so dass man abwägen muss, welchen Wert man aus den Daten ziehen und wie man sie minimieren oder durch Anpassung des Trackings so organisieren kann, dass sie übersichtlich bleiben.

Das Tracking kostet Zeit. Diese geht direkt in die serverseitige Latenz der Website ein. Wenngleich der Beispielcode den Trackingaufruf bereits "quasiasynchron" absetzt und nicht auf Antwort wartet, sind ausgereiftere Methoden sinnvoll, wenn man damit jenseits von ein paar Tests länger arbeiten will. Es wurde zur Übersichtlichkeit des Beispiels bewusst auf "Overhead" verzichtet. Der Echtbetrieb sollte den Faktor "PageSpeed" aber nicht einfach so ignorieren.

Wer das Tracking z. B. in ein Wordpress-Blog einbauen will, muss dazu nur in der footer.php möglichst weit unten einen PHP-Block einfügen oder im letzten Block, in dem i. d. R. wp_footer() aufgerufen wird, die gewünschte Variante der Trackingfunktion anfügen. Id eintragen, ggf. Bot-Array anpassen und unter der Definition der Funktion diese direkt aufrufen (hier für Variante B, sonst analog mit track_hit()):

track_bot_hit(wp_title('-', false));

Nach dem Hochladen auf den Server sollte der Echtzeitbericht in Analytics direkt Daten anzeigen, wenn man sich für das Tracking aller Besucher entschieden hat und die Site selbst aufruft. Sonst dauert es ggf. etwas, bis der erste Bot vorbeikommt und Spuren hinterlässt. Auf jeden Fall sollte nach der Anpassung des Templates geprüft werden, ob die Site noch funktioniert oder ob Probleme durch die Änderung entstanden sind. Troubleshooting Tipp 3: Kommen keine oder nur verdächtig wenig Daten an, wird das am Einsatz eines der beliebten und sinnvollen Plugins zum Caching in Wordpress liegen. Das macht die Site zwar schnell, hilft aber nicht beim serverseitigen Tracking und muss deshalb wohl oder übel ausgeschaltet werden. Zumindest solange, wie man auf diese Weise Daten über Bots und / oder Besucher sammeln will.

Tipp: Variante B auf "benötigte" Bots beschränken

Wer den Code einsetzt und auf den Kernzweck des Trackings von Bots beschränken will, kann zur schrittweisen Konfiguration und Reduktion der Hits wie folgt vorgehen:

  1. Die eingeschränkte Variante B implementieren und mit den vorkonfigurierten Bots starten
  2. Das Medium für "Other" regelmäßig nach Bots durchsuchen, deren Besuche man separat tracken möchte. Dazu das Tracking so erweitern, dass der User-Agent-String ($agent) z. B. als benutzerdefinierte Dimension übergeben wird, die man dann in Analytics-Berichten einblenden und nach Kandidaten durchsuchen kann. Hier beispielhaft Details zum Googlebot aus einem Testprofil:
    User Agents des Googlebot in Analytics sichtbar gemacht
  3. Für diese Bots eigene Segmente über das Array erzeugen und so "Other" so weit wie möglich minimieren
  4. Bei vielen Hits für jeden relevanten Bot ggf. ein eigenes Profil anlegen.
  5. Nur Tracken, was man tracken muss: Mittelfristig unbekannte oder "irrelevante" Bots aus dem Tracking ausschließen, indem der letzte Eintrag des Segment-Arrays entfernt wird.

Tipp: Parameter ausbauen und Cache Buster nutzen

Da die realistische Möglichkeit besteht, dass identische Requests mehrfach angesetzt werden, sollte die Tracking-URL noch um den Parameter z ergänzt werden, der mit einem Zufallswert zu belegen ist. In den meisten Fällen reicht es aus, dazu date("YmdHisu") zu verwenden.

Weitere Angaben wie die IP des Aufrufs sind per PHP auszulesen und dem Aufruf hinzuzufügen, wenn reale User getracked werden. Die IP dabei zu anonymisieren, sollte dann dazu gehören. Genau wie der Hostname und... Naja: eben möglichst alles, was man in der Referenz bei Google findet, leicht (meint: schnell) auslesen kann und auch wirklich auswerten will.

Das Ergebnis in Google Analytics

Implementiert man die eine oder andere Variante, sammelt selbst eine kleine Website schnell Daten und schon nach einem Tag lohnt sich ein Blick in die Auswertungen unter "Akquisition". Dort sieht man im Bericht zu "Quelle/Medium" die Verteilung der Sitzungen nach verschiedenen Bots - und im Fall von Variante A auch bekannte Besucher und den Rest.

Bots und User in einem Analytics-Profil

Dashboards

Mit diesen Daten lassen sich auch hilfreiche Dashboards aufsetzen, die z. B. neben einer Übersicht über alle Bots einen detaillierteren Blick auf Besuche oder Seitenaufrufe des Googlebots bieten.

Dashboard für Bots in Analytics

Googlebot-Besuche auf Seitenebene

Für jeden Bot lassen sich über das Medium separate Segmente bilden. Damit lässt sich ein zentraler Bericht wie "Verhalten - Website-Content - Alle Seiten" exklusiv für diesen besonderen Besucher anfertigen. Ein Klick auf eine Seite und schon ist erkennbar, wann und wie oft diese von Google besucht wurde. Auch die Information, welche Seiten nicht besucht wurden, ist ermittelbar, wenn man die Daten z. B. per API regelmäßig abgreift und mit der eigenen Sitemap abgleicht.

Seitenaufrufe der Startseite durch den Googlebot

Jede Menge Kennzahlen

Mit solchen Segmenten findet man in fast jedem Analytics-Bericht interessante Daten. Selbst wenn nicht alles stets sinnvoll ist - z. B interessiert die Absprungrate hier wenig -, kann ohne aufwändige Aufbereitung von Logfiledaten direkt in Analytics abgelesen werden, wie oft der Googlebot in einem beliebigen Zeitraum vorbeigekommen ist, wie viele Seiten er sich angesehen hat, wie viel Zeit er "auf der Site" verbracht hat. Nett, oder?

Eigene Analytics-Kennzahlen für den Googlebot

Und die echten Besucher?

Abschließend noch einmal zu den Segmenten "Tracked Users" und "Unknown". Wer sich entscheidet, auch diese serverseitig nachzuverfolgen, sollte ernsthaft über einen Ausbau des Systems nachdenken, um die "Tracked Users" möglichst auch um neue Einstiege zu ergänzen. Dazu reichen serverseitig verwaltete Kennungen als Ersatz zum Analytics-Cookie, der eine parallele clientseitige Implementierung voraussetzt.

Aber selbst ohne Anpassung sind die entstehenden Daten durchaus brauchbar. Vor allem, wenn man bedenkt, dass keine Webanalyse die Wahrheit sagt, wenn es um absolute Zahlen geht, reichen die so gesammelten Daten z. B. für Periodenvergleiche und Langzeittrends. Man sollte aber bedenken, dass clientseitig erhobene Daten in Analytics i. d. R. weitaus vollständiger sind, was den Umfang der pro Hit gesammelten Angaben angeht. Betrachtet man beide Methoden, sind die Ergebnisse zumindest "grob vergleichbar". Dennoch weichen die absoluten Zahlen je nach Zusammensetzung der Besucher sehr stark ab. Konzentriert man sich auf die "Tracked User", sind die Metriken potentiell zu klein, mit "Unknown" zusammengelegt oft um den Faktor 10 oder mehr höher als im parallel betriebenen "klasssischen" Profil. Trends hingegen lassen sich sowohl über längere Zeiträume als auch auf Tagesbasis vergleichen. Sieht man sich die beiden Kurven aus entsprechenden Profilen an, ist der Verlauf vergleichbar:

Das sieht Analytics im Client
Das hat Analytics an diesem Tag durch klassische Sammlung per Trackingcode am Client gesammelt.

Analytics-Verlauf aus Serversicht
Die Zahlen des gleichen Tages für die "Tracked User" des serverseitigen Analytics-Profils: Anders, aber nicht grundsätzlich falsch.

Dass hier bei der zweiten Variante z. B. die Absprungrate anders aussieht, ist nachvollziehbar, denn es fehlt dem zweiten Datenpool jeder Einstieg eines neuen Besuchers - darum sind auch Metriken wie die Seiten pro Besuch potentiell geringer. Trotz solcher Mängel ist diese Methode zur Sammlung von Daten für viele Anwendungsfälle interessant. Wo mit einer eigenen Id für den (z. B. angemeldeten) Benutzer gearbeitet werden kann, verschwinden die meisten Ursachen für die gezeigten Unterschiede zum "normalen" Tracking. Spätestens die Möglichkeit zum Tracking von Bots sollte ausreichen, um eine Implementierung in Betracht zu ziehen - auch parallel zur üblichen Webanalyse und tiefer Tauchgänge in Logfiledaten, die nach wie vor ihren Sinn haben.

Inspiriert?

Wer sich durch die ganze Artikelserie gekämpft hat, wurde hoffentlich mit einem tieferen Einblick und Verständnis für die zahlreichen Möglichkeiten beglückt, die sich mit dem Measurement Protocol ergeben. Ich für meinen Teil habe nun so viel an der Oberfläche gekratzt, dass mir praktisch jeden Tag neue Ideen für den Einsatz kommen. Einen Teil davon werde ich umsetzen und die Serie ggf. um Anwendungsbeispiele und Hinweise erweitern. Umgekehrt freue ich mich über jeden Kommentar mit Vorschlägen zur Verbesserung oder Erweiterung.

#