Markus Baersch

Analytics · Beratung · Lösungen

Start » Blog » GA4 / Serverside Tracking

04.08.2022

Weil es in GA4 keine Datenansichten gibt und ein eingehender Datenstrom nicht in mehrere GA4 Properties gibt, stellt sich bei vielen Websites die Frage nach dem richtigen Tagging. Wenn z. B. mehrere Sprachen oder Länder, unterschiedliche Teile auf einzelnen Subdomains oder in Ordnern bisher in Universal-Datenansichten getrennt betrachtet wurden, aber eine gemeinsame Property hatten: Wie soll man das in GA4 abbilden? Dieser Blogbeitrag dokumentiert die Ergebnisse einer Untersuchung auf einer größeren, aus mehreren Teilen bestehenden Website. Es geht um die Frage, ob und wie über einen serverside GTM für GA4 eine Zusammenführung von Daten aus verschiedenen Einzel-Properties in einer gemeinsamen Property möglich ist.

Eine oder mehrere Properties?

Eine Property für alle bedeutet viel Filterarbeit in GA4 Reports oder unterschiedliche Reporting UIs via Bibliothek / Menüanpassung für unterschiedliche Teile und Aufgaben. Nicht gelöst ist damit das Problem, dass dann mehrere Zeitzonen bei internationalen Websites in einen Topf geworfen werden, doch das zählt hier nicht als Gegenargument, denn es wäre dann bereits in UA der Fall gewesen. Hat man dort bereits eine parallele UA Property betrieben, würde das bei GA4 nun theoretisch ebenfalls machbar sein.

Unterschiedliche Properties erlauben individuelle Einstellungen, Zugriffsregelung, Zeitzonen etc. Das ist prima, aber ohne paralleles Tagging einer weiteren Property im Browser kommt man nicht zu einer Ansicht, in der alle Daten zu finden sind. Am Beispiel einer Website, die aus mehreren Subdomains besteht, welche alle in einer eigenen Einzel-Property vermessen werden sollen, aber zusätzlich eine "Rollup" / Sammel-Property bedienen sollen, sieht das Ganze vereinfacht für Universal Analytics in etwa so aus:

Doppeltes Tagging im Browser

Genauso gut könnte es auch eine Website mit mehreren Ordnern für unterschiedliche Zwecke, Zielgruppen oder Sprachen haben. Warum auch immer mehrere Properties existieren und egal, ob es ein paralleles Tagging gibt oder alle Hits per customTask dupliziert werden: In der parallel direkt aus dem Browser versorgten Sammel-Property als "Rollup" landen alle Daten, die auch in den einzelnen Properties für die Teile der Website auflaufen.

Data Blending in Google Data Studio, Auswertungen auf Basis der Big Query Daten oder der Umstieg auf GA360 (wo es Sub Properties und RollUp Properties gibt) sind der einzige Ausweg, wenn man das doppelte Tagging im Browser vermeiden möchte. Eigentlich.

Optionen bei Nutzung eines eigenen Endpunkts

Kommt ein serverside GTM als Tracking-Endpunkt (oder ein vergleichbarer „Proxy“ zwischen Browser und Trackingdienst), liegen die Spielregeln anders. Bei Universal Analytics war / ist es absolut machbar, die Hits der unterschiedlichen Properties sowohl an den jeweiligen Empfänger (die „UA-Einzel-Property“) weiterzuleiten, als auch alle Hits aller Teile der Website / Domain an eine weitere Sammel-Property zu senden. Auf Empfängerseite verwaltete Sessions haben so für einen ganz brauchbaren Gesamtblick gesorgt – solange man sich dann mit den Limits und Sampling etc. abfinden konnte.

Property-Konsolidierung via ssGTM für UA

Solange sich der Empfänger - hier Universal Analytics - um die Verwaltung von Sitzung für einzelne Besucher, deren Status, die Anzahl der Besuche, Bestimmung erreichter Ziele etc. kümmern kann, funktioniert das prima.

Kernfrage: Geht das auch bei GA4?

Bei GA4 werden die Karten allerdings schon wieder neu gemischt und das obige Setup scheitert an der Tatsache, dass die Session im Browser verwaltet wird und so jede Property einen anderen Stand hat. Man teilt sich zwar die Client ID, aber Session ID und Nummerierung der Sitzung liegen in der Gewalt des Browsers und sind je Property unterschiedlich. Genauso verhält es sich mit der Information, ob eine Sitzung startet oder ein User neu ist oder nicht. Kann das obige Konstrukt auch für GA4 funktionieren, obschon die Kontrolle über die Sitzung und die anderen o. g. Attribute für Besuche und Besucher in diesem Fall beim Browser - also dem Sender - und nicht dem Empfänger der Hits liegt?

Property-Konsolidierung via ssGTM für GA4

Ich habe verschiedene Optionen erprobt, um genau das herauszufinden.

Einschränkungen bei „einfacher“ Duplizierung von GA4 Datastreams am Endpunkt

Mehrere GA4 Datenstreams zu einem neuen (validen) Stream zu kombinieren am ssGTM Endpunkt ist aus den oben genannten Gründen nicht trivial.

Die Feinde heißen hier:

  • Session ID: Diese wechselt, wenn bei der Navigation von einem Teil der Website zum anderen die Property gewechselt wird. Wenn also zum Beispiel bei getrennten Properties für die Vermessung zwischen Blog und Shop gewechselt wird.
  • Session Nummer: Die Nummer ist aus o. g. Gründen gleichfalls nicht konsistent, wenn man dennoch alle GA4 Hits in ein Sammelbecken wirft. Beim o. a. Wechsel von Blog zu Shop entsteht eine neue Sitzung aus Sicht der Shop-Property mit einer i. d. R. abweichenden Nummer, denn man besucht üblicherweise nicht immer alle Teile einer Website
  • Session Start und First Visit Marker: Wann immer eine Sitzung entsteht, wird ein Marker mit dem Hit gesendet (_ss=1), der dafür sorgt, dass in GA4 ein session_start Ereignis entsteht. Gleichfalls ist (falls die Sitzungsnummer 1 ist) ein Marker für den ersten Besuch (_fv=1) dabei, der das first_visit Ereignis entstehen lässt und dafür sorgt, dass es in GA4 sowas wie eine „First User Source“ etc. gibt

Im Ergebnis entstehen in einer solchen „Sammel-Property“ mit allen ungefilterten Hits aus unterschiedlichen GA4 Datenströmen ohne weitere Anpassungen eine Menge an eigentlich (aus Sicht einer Gesamt-Property) überflüssigen Sitzungen, "neuen" Besuchern und den zugehörigen Events.

GA4 Beispiel: Wiederkehrender Besucher

So sieht das am Beispiel eines wiederkehrenden Besuchers aus, der schon mehrfach auf der www Property und einmal im Shop war.

  • Steigt der erneute Besuch bei der www Property ein, entsteht eine Sitzung und ein Start. Die Session ID ist eindeutig und die Nummer des Besuchs ist 3, da es bereits vorherige Besuche der Property gab. Innerhalb der Property können nun weitere Events folgen
  • Ein Klick führt zum Blog (wo bisher kein Besuch stattgefunden hat). Dort entsteht dort eine neue Sitzung aus Sicht der Blog-Property und es wird ein session_start und first_visit gemeldet - auch an die Rollup Property. Aus deren Sicht hat sich auch die Sitzungs-ID und -nummer geändert
  • Beim Wechsel in den Shop passiert das Gleiche, nur entsteht kein first_visit, weil es schon einen Besuch dort aus einer vorherigen Session gab
  • Vom Shop zurück auf www wechselt nun erneut die Session-ID und Nummer aus Sicht der RollUp Property. Da schon eine www-Session besteht, kommt es auch zu keinen neuen session_start Events

Änderung der Session-Parameter + zu viele Starts

In der Rollup Property kommen auf diese Weise unsinnige und inkonsistente Sitzungsinformationen an und zusätzlich entstehen beim Wechsel ggf. unerwünschte Events. Während also die Anzahl der Seitenaufrufe passen sollte oder Transaktionen korrekt im Sammelbecken landen, ist eine „domainübergreifende“ Attribution von Conversions zu Besuchen und deren Quelle i. d. R. gestört.

Wege zur Lösung für GA4

Ich habe einige Dinge und Basteleien versucht, um eine möglichst sinnvolle Gesamtsicht herzustellen. Dabei sind die o. a. Inkonsistenzen der Sitzungsinformationen und überflüssige Neustarts Probleme, denen man mit den Standard-Mitteln des client- und serverside Google Tag Managers auf unterschiedliche Weise begegnen kann.

  1. Senden aller Hits mittels eines Standard-Tags für GA4 mit überschriebener Measurement Id zur Konsolidierung aller Hits in einer RollUp Property. Geeignet für hauptsächlich getrennte Hosts oder Domains
  2. Wie 1), allerdings mit Sonderbehandlung von Wechseln zwischen den Properties und dabei neu entstehenden Sitzungen. Für eine wirkliche Nutzbarkeit sollte zudem eine eigene, übergreifende Session verwaltet werden. Das kann optional im einem clientseitigen GTM oder von der Serverseite aus gesteuert werden
  3. Verwendung des GA4 Measurement Protocols
  4. Ein eigener Client im ssGTM, der alle Hits an die RollUp Property sendet (bereinigt um weitere Sitzungsstarts und eigener Session-Kontrolle wie bei Option 2) und dann an die normalen Tags weitergibt
  5. Duplizierung von Hits im Client durch Monkey Patching der Sende-Funktion im Browser .Diese Option ist hier nicht behandelt und im Ergebnis vergleichbar mit Option 1. Hier also nur der Vollständigkeit genannt.

Bei Implementierung der Optionen 1 bis 4 sind unterschiedliche Ergebnisse zu erwarten. Nicht jedes Setup muss die „bevorzugte“ Option 2 ziehen. Die folgenden Abschnitte beschreiben die Umsetzung und daraus resultierenden Daten in einer RollUp Property.

Option 1: Standard-GA4-Tag zur Konsolidierung aller Hits in einer Property

Ein einfaches Tag, das bei allen GA4 Hits unabhängig von der Measurement ID feuert und diese mit der neuen ID der Sammel-Property überschreibt, kann nur mit den o. a. Einschränkungen genutzt werden. Selbst das Überschreiben einzelner Felder ist hier keine Hilfe, wenn es sich um das spezielle Feld handelt, um das es geht. Denn die Informationen zu Session Start oder First Visit beim Wechsel von Datenstreams entsteht, stehen in „System Properties“ unter dem Schlüssel x-ga-system_properties im Eventmodell und dort scheint ein Überschreiben nichts am ausgehenden Hit zu ändern. Ich habe es zunächst so versucht, indem ich in einer Variable per Custom Template die Parameter aus den Original-Inhalten der als Objekt gespeicherten Informationen entfernt habe. Das klappt allerdings nicht, denn es wird immer noch ein _ss=1 und ggf. _fv=1 raus gesendet, wenn man sich die ausgehenden Hits anschaut. Ein Entfernen der Angaben durch Überschreiben mit einer „Undefined Value“ Variable hat den gleichen Effekt; dito die Bearbeitungsfunktionen für Parameter, die das Tag mitbringt. Damit ist diese Methode nicht sehr geeignet, weil es so unter Umständen zu einem Überfluss an Sitzungen kommt.

Ist diese Option daher generell ungeeignet? Ich denke nicht. In Fällen, in denen z. B. unterschiedliche Länder oder auf andere Weise getrennte Zielgruppen auf einer Domain erreicht werden, die in einzelnen Properties vermessen werden sollen, ist diese Option mit Abstrichen durchaus brauchbar. Solange sich die Anzahl der „Property-Wechsler“ (sowohl innerhalb einer Sitzung als auch generell) in Grenzen hält, passen die Ergebnisse ganz gut zu dem, was man aus der Summe der Einzel-Properties erhalten würde.

Ein Vorteil dieser Lösung ist es zudem, dass es bei einem „Multi Domain Setup“ einsetzbar ist, bei dem nicht nur mehrere Hosts, sondern unterschiedliche Domains vermessen werden. Mit der Konsolidierung am eigenen Endpunkt löst man allerdings keine Cross Domain Probleme. Wenn dies nicht im Client durch echtes Cross Domain Tracking abgebildet wird, hat jede Domain ihre eigenen Cookies und es wird keine übergreifende ID geben. Wie gesagt: Das muss gar nicht tragisch sein – je nach Grund dafür, warum es mehrere Domains gibt.

Option 2 - Schritt A: Standard-GA4-Tag mit Sonderbehandlung bei Property-Wechsel

Um dennoch irgendwie das Entstehen von weiteren session_start und ggf. first_visit Events zu vermeiden, kann ein anderer Ansatz verfolgt werden.

Damit alle Hits konsistent in GA4 ankommen, ist ein Beibehalten der Session ID und Session Nummer erforderlich. Es geht zudem darum, ein Entstehen von neuen Sitzungen in GA4 und der Attribution von Conversions über eine ungebrochene Gesamtsitzung in einer „Multi-Stream-Rollup-Property“ zu verhindern. Dazu muss also jedes Mal, wenn eine neue Sitzung (aus Sicht der Einzel-Properties, mit deren Measurement-IDs die jeweilige Site getagged ist) beim Domainwechsel entsteht, eine Sonderbehandlung stattfinden. Dazu wird eine unabhängige Session ID und Nummer generiert und durchgehend genutzt. Events beim Wechsel zwischen den Einzelteilen werden übergangen. Anhand des obigen Beispiels sieht das abweichende Handling für die RollUp Property so aus:

Konstante Session-Parameter + Events

Auf diese Weise würden sowohl die Einzel-Properties als auch die RollUp Variante genau das bekommen, was benötigt wird. Klingt gut? Dann fangen wir mit dem zweiten Problem an:

Property-Wechsel erkennen

Um zu erkennen, ob bereits eine Sitzung besteht oder nicht, kann z. B. ein Marker als Session-Cookie herhalten, mit dem man sehen kann, ob der erste Eintritt bereits inkl. Session Start und ggf. First Visit vermessen wurde und ein weiterer Start (aus einer anderen Property) stattgefunden hat. Im aller einfachsten Fall unterbindet man nur per blockierendem Trigger diesen Hit (an den o. a. System Properties und einem eigenen Cookie erkennbar) und verzichtet auf den Messpunkt (wir lösen es allerdings in diesem Beispiel anders und schließen die Lücke).

Erstellt man ein Session-Cookie mit einem beliebigen Wert, kann man daran in einem Trigger auslesen, ob bereits ein Sitzungsstart vermessen wurde oder nicht. Dazu benötigt man ein Tag, dass immer dann feuert, wenn noch kein Marker Cookie besteht, aber ein GA4 Request mit Sitzungsstart-Merkmalen reingekommen ist. Verwenden kann man dazu z. B. das Cookie Monster Tag Template von Simo Ahava. Ein Zeitstempel als Wert tut es hier genauso gut wie eine Konstante, eine „1“, die Client ID aus dem GA4 Cookie oder etwas anderes.

Session Start Cookie setzen

Liest man diesen Cookie Wert in einer Standard-Cookie-Variable aus, kann diese dann a) für den auslösenden Trigger des Cookie Monster Tags genutzt werden (feuern wenn kein Wert da ist) und b) den blockierenden Trigger für das GA4 Sammel-Property-Tag.

Session Start Trigger

Hierbei wird der Marker für den Sitzungs-Start in eingehenden Events (siehe letzte Bedingung) ausgelesen, indem die „System Properties“ (siehe oben) als Event-Parameter per Standard Variable ausgelesen werden und als Eingangswert für eine Extraktionsvariable dienen, die den Wert von „ss“ aus dem JSON Objekt entnimmt.

Extraktion des Session Start Markers

Hört man an dieser Stelle bereits mit der Sonderbehandlung auf, sieht man tatsächlich bereits in der RollUp Property weniger Sessions entstehen, so dass man dies bereits als Teilerfolg verbuchen kann. Es ist aber unschön, weil auf diese Weise Events fehlen (wann immer die Domain gewechselt wird). Außerdem: Wenn man ohnehin eigene Cookies benötigt, kann man gleich den ganzen Weg gehen und versuchen, die komplette Kontrolle über die Sitzung zu erlangen.

Option 2 -Schritt B: Sitzungskontrolle mit eigenen Cookies

Um nicht die ggf. inkonsistente Session-IDs und -nummern in die RollUp Property zu senden, wenn Besucher zwischen den Einzel-Properties wechseln, muss eine unabhängige Sitzung für die RollUp Property her. Diese kann auf verschiedene Weise verwaltet werden; z. B. in einem gemeinsamen Cookie oder in getrennten Cookies – serverseitig oder im Client verwaltet. Im Fall des Clients gibt es Alternativen wie localStorage. Am Server könnte man mit Fingerprints und Persistenz in Firestore arbeiten... was auch immer.

Da für GA4 ohnehin Cookies (und Consent) erforderlich sind, genügen client-seitig gesetzte und getrennte Cookies. Das Verwalten der RollUp-Session im Client hat den Vorteil, dass alle Hits diese bereits im Request mitbringen, wenn sie beim Endpunkt eintreffen. Wird sie dort erzeugt, bedeutet dies nicht nur etwas Aufwand in Form von Variablen und Triggern, sondern man ist zusätzlich mit Batching-Problemen konfrontiert (siehe unten: "Alternativ: Session im ssGTM erzeugen"). Ich habe es dennoch versucht und war mit dem Ergebnis zufrieden, aber die client-seitige Session passt schon deshalb für die RollUp-Property, weil die Einzel-Properties ebenfalls mit im Browser generierten Cookies arbeiten.

Session Helper-Tag für GA4 im Browser

Das Rezept für die RollUp Session ist relativ überschaubar: Alle Container der beteiligten Einzel-Properties (wenn es mehrere sind) benötigen ein HTML Tag, das sich per JavaScript um die Cookies kümmert.

Darin wird zunächst bestimmt, ob es schon ein Cookie für die Session ID gibt. Falls nicht, wird es erstellt, der Cookie-Wert mit der Sitzungsnummer (wenn existent) ausgelesen, die Sitzungsnummer erhöht und wieder in einem Cookie gespeichert. Hier der Code für eine entsprechende Lösung, die ohne eine weitere Cookie-Variable für die Sitzungsnummer auskommt, sondern den Cookie Wert der Einfachheit halber direkt im Code ausliest:

Session Management im Client

Es sind also zwei Cookies im Spiel: Eine Session ID in einem Sitzungscookie und eine laufende Sitzungsnummer in einem langlebigeren Cookie. Wie oben schon erwähnt ist das nicht die einzige Lösung, aber sie ist praktikabel und macht die Arbeit am ssGTM Endpunkt leichter. Man spart sich so die Mühe, die ID und Nummer in einem einzelnen (dann langlebigen) Cookie voneinander zu trennen und „zu alte“ Sessions manuell zu erneuern.

Das HTML Tag wird als Setup-Tag des GA4-Konfigurationstags eingesetzt, so dass es vor dem Senden von Hits eine faire Chance hatte, eine ggf. noch nicht bestehende RollUp Session zu erkennen und zu initialisieren. Die Cookie-Werte wandern dann zusammen mit den Hits zum Tracking-Endpunkt.

Alternativ: Session im ssGTM erzeugen

Wer sich die Arbeit sparen will, in den Containern der Einzel-Properties jeweils das o. a. Helper-Tag einzusetzen, kann das Ganze mit etwas Mehrarbeit am Server regeln. Da zum Zeitpunkt des Eintreffens des ersten Hits die Sitzungsnummer und ID in diesem Fall erst serverseitig bestimmt, beim Event verwendet und dann (per Cookie Monster) in der Antwort gesendet werden muss, sind mehrere Variablen auf Basis von (vorhandenen) Custom Templates wie „Number & String Operations“ und „Timestamp“ erforderlich, mit denen eine „Next Session Number“ und „New Session ID“ für den Start einer neuen RollUp Session erzeugt werden. Diese verwendet ein eigenes Tag, welches nur für den „ersten Hit“ genutzt wird. Alle folgenden Hits nutzen dann die ID und Nummer aus den zuvor serverseitig gesetzten Cookies in einem weiteren Tag.

Neben dem Vorteil, dass in diesem Fall keine Anpassungen im Client erforderlich sind, kann zudem komplett mit „härteren“ Cookies (sogar httpOnly) gearbeitet werden. Es besteht durch Batching ein gewisses Risiko für ein „Henne-Ei-Problem“ (von dem ich in Tests nichts gesehen habe). Theoretisch ist dies also die robustere Variante… wobei man zumindest einer ITP-Anfälligkeit durch einfaches Erneuern des aus dem Client stammenden Cookies für die Sitzungsnummer begegnen kann.

Setup am Tracking-Server

Im ssGTM werden die eingehenden Session-Informationen in Cookie-Variablen entgegengenommen. Hier z. B. die Session-Nummer.

Rollup Session Cookie lesen

Ebenso erstellt man eine Cookie-Variable für die Session ID. Beide werden dann in einem GA4 Tag, das bei allen Requests feuert, die im GA4 Format ankommen, zum Überschreiben der Session ID und Nummer (ga_session_number und ga_session_id) genutzt:

Rollup GA4 Tag

Blockiert man dieses Tag bei allen Domain-Wechseln (siehe oben), ist der Zustand von Option 2a erreicht – aber mit einer schlüssigen Session und Nummerierung.

Lücke beim Property-Wechsel schließen

Bleibt das Loch der fehlenden Events beim Property-/Domainwechsel. Ein normales GA4 Tag ist deshalb keine Lösung, weil (wie in Option 1 erprobt) kein Überschreiben der System Properties möglich ist. Stattdessen kann (neben einigen anderen Dingen, die selbst erstellten Code in Form von eigenen Tag Templates erfordern) einfach das Measurement Protocol genutzt werden.

Dazu im Rahmen der bestehenden Session einfach beim Wechsel das Event per Measurement Protocol senden, so dass keine Session Start oder First Visit Marker dabei sind (können sie in diesem Fall auch gar nicht). Unter Verwendung der eigenen Session ID (die Nummer kann man weglassen, wenngleich sie als session_number gesendet werden kann) landet der Hit im Kontext der Web-Session, die aus den einzelnen Sessions der Teil-Properties durch die gemeinsame Session ID zusammengesetzt wird. Solche Events sind mehr oder weniger gleichwertig zum normalen ausgelassenen Hit, der i. d. R. ein Seitenaufruf sein sollte... aber nicht muss. Ich habe in den Daten im Rahmen dieses Tests auch faktisch alle anderen Events gefunden, die ggf. vor dem Seitenaufruf abgesendet wurden.

Rollup Property Change Tag

Wichtiger Hinweis: Die hier dargestellte Gestaltung des Events zeigt nur den absoluten Minimalzustand (abgesehen von der "serverside_route", die ich nur zu Debugging-Zwecken in diesem Experiment hinzugefügt habe). Um alle Parameter abzudecken - und z. B. auch User Properties weiterzugeben -, ist entweder ein Custom Tag Template erforderlich, das alle erforderlichen Felder abdeckt (so habe ich es gelöst) oder das obige Beispiel muss um alle relevanten Event-Parameter ergänzt werden. Da es z. B. auch E-Commerce Events treffen kann, würden sonst zwar die Events ankommen, aber nicht ihren eigentlichen Zweck im Sinne des Reportings erfüllen können. Mit dem o. a. Setup hatte ich z. B. Lücken in Conversions und Unterschiede in der aufgezeichneten Engagement-Gesamtzeit wegen fehlender Parameter.

Das Tag wird ausgelöst, wenn ein Property-Wechsel stattfindet. Der gleiche Trigger wird beim „normalen“ RollUp GA4-Tag als Ausnahme definiert, so dass es bei diesen Ereignissen blockiert wird.

Rollup Property Change Trigger

Auf diese Weise hat man die bestmögliche Annäherung an eine RollUp Property für die einzelnen Teile der Website erstellt. Je nachdem, aus welchem Grund verschiedene Properties existieren, mögen Property-Wechsel innerhalb einer Sitzung so irrelevant sein, dass man sich den Aufwand des Auffüllens per Measurement Protocol ggf. einfach sparen kann. Eine Markierung in Form einer Event-Eigenschaft ermöglicht eine Selektion aller so entstandenen Events in GA4 (meistens sollten es page_view Ereignisse sein).

Option 3: Measurement Protocol "All In"

Ein ganz anderer Ansatz wäre die durchgehende und alleinige Nutzung eines HTTP Request Tags zum Senden der Hits via Measurement Protocol. Werden damit die – zwangsweise reduzierten - Daten aller eingehenden Hits der einzelnen Properties einfach an GA4 weitergegeben, hat man einige Probleme eliminiert. Dadurch, dass hierbei recht einfach eine (serverseitig erzeugte und in einem Cookie per Cookie Monster gespeicherte) Session ID generiert und als gemeinsame Klammer um alle Hits verwendet werden kann, bietet sich das Measurement Protocol theoretisch sogar als erste Wahl an. Eine Sitzungsnummer wird dabei nicht benötigt, um die Vermessung einer gemeinsamen Sitzung zu erzielen,. Ich habe es tatsächlich versucht, wobei ich mich dann auf die Events beschränkt habe, die wesentlich sind und damit z. B. das Engagement geopfert, weil es ohnehin beim GA4MP beim Hit selbst angegeben werden muss. Sicher: Man kann sich was zurechtbasteln und Engagement-Timings von A nach B bekommen, aber für einen Test war es mir die Mühe nicht wert und so habe ich mit einem konstanten Standardwert gearbeitet:

GA4MP Test Tag

Die so entstehenden Reports sind nicht komplett unbrauchbar... aber wie ich in meinem separaten Post zu GA4 Website-Vermessung via Measurement Protocol bereits beschrieben habe, fehlt es eben an vielen Ecken und Enden. Es mag sein, dass dieser Weg sich in Zukunft besser eignet, wenn Google sich entschließt, mehr aus den Daten zu machen, die auf diesem Weg ankommen. Nach akt. Stand ist Attribution nur manuell und in Big Query bzw. auf Rohdatenbasis generell sinnvoll durchführbar. Trotzdem: Wer gar keinen eingehenden GA4 Datenstrom hat, aber dennoch aus verschiedenen eingehenden Requests für unterschiedliche Zwecke eine "Gesamtproperty" in GA4 herstellen will, kann diesen Weg durchaus gehen.

Option 4: Eigener Client

Wenn man davon ausgeht, dass eingehende GA4 Requests nur an GA4 weitergeleitet werden sollen, dann hat man dennoch normalerweise einen Client, der alles in das Eventmodell übersetzt und ein Tag, das den gleichen Request wieder zusammenbaut. Das ist in den meisten Setups sinnvoll, denn dort wartet auf der anderen Seite mehr als ein Tag auf ein Event. Zumindest im Experiment wäre es denkbar, dass man sich das alles komplett spart. Wann immer ein GA4 Request ankommt, würde in diesem Fall ein eigener Client darauf reagieren.

Dieser kann den eingehenden Request inkl. aller ggf. als Batch gesendeten weiteren Events in einem Rutsch an die GA4 RollUp Property (in Form von google-analytics.com inkl. (fast) aller Parameter und POST Nutzlast) weiterleiten und dann ganz normal verarbeiten und die Events den Tags zur Verfügung stellen. Die Mehrarbeit des Clients besteht dann daraus, den Vermessungszustand des Sitzungsstarts zu verwalten; also das o. a. Cookie zurückzusenden und auszuwerten, wann immer ein _ss-Marker bei einem Event vorhanden ist. Im Ergebnis sollte in GA4 eigentlich das gleiche ankommen, wenn man zudem ein paar Header in die Verarbeitung einschließt und so ggf. (gekürzte) IP und User Agent kontrolliert weitergibt.

Das Ziel wäre es, sich den ganzen Overhead der Event-Verarbeitung in Client und Tag zu sparen. Hierbei sollte weniger Last am Endpunkt entstehen, was sich idealerweise in den erforderlichen Instanzen und / oder Kosten wiederfindet. Vor allem, da man hierbei für Batches keine mehreren Aufrufe hat, sondern alles in einem Request verarbeiten und „rausjagen“ kann. Wenn jemand Bock auf dieses Experiment hat – sprich mich an! 😉

Hinweis: Wer versucht ist, als Variante der obigen Idee einfach eine Art „Request Repeater“ als Tag im ssGTM zu nutzen, alle eingehenden Parameter der Requests an GA4 weiterzugeben, wird schnell ein Problem feststellen: Pageviews oder andere Events sind entweder höher oder niedriger als die Summe aus den Teil-Properties. Das liegt am Batching, bei dem ein eingehender Request mehrere Events enthalten kann. Bei der Weiterleitung in einem Tag statt Client werden die ggf. im Request Body enthaltenen Ereignisse je nach Setup entweder fehlen... oder mehrfach verarbeitet. Da gleichfalls Conversions betroffen wären, ist es keine wirkliche Lösung (ich habe es tatsächlich versucht 😐).

Ergebnisse

Ich habe alle Tests anhand eines GDS Reports kontrolliert, in dem ich via Data Blending ausgesuchte Metriken der am Test beteiligten vier Einzel-Properties zusammengeführt und mit den Daten der RollUp Property verglichen habe. Da bis zu fünf Datenquellen zusammengeführt werden können, sind Differenzen zwischen Summen und RollUp direkt darstellbar. Die Zeile waren die Hauptwebsite, ein Blog, ein B2B und ein B2C Shop.

Die folgende Abbildung zeigt (fast) das erwartete Ergebnis bei Nutzung der Option 2b (egal, ob mit client- oder serverseitiger Verwaltung der RollUp Session):

  • Nutzer und Sitzungen sollten niedriger sein, da es hier durchaus wahrscheinlich ist, dass zwischen den einzelnen Teilen gewechselt wird
  • Seitenaufrufe sollten übereinstimmen
  • Umsatz und Transaktionen sollten ebenso gleich sein
  • Summierte Conversions müssten dem RollUp Wert entsprechen
  • Event-Anzahl sollte niedriger sein, weil First Visit und Session Start Events fehlen
  • Die Verteilung der Nutzer auf einzelne Quellen / Medien ist unabhängig von den Daten der Einzel-Properties (nicht im Bild zu sehen)

Ergebnisse im Vergleich

Man sieht vernachlässigbare Unterschiede bei Seitenaufrufen ("Views"), Conversions und Umsatz, aber generell geht die Sache offenbar sehr gut auf.

Woher kommen die Differenzen?

Zu erwarten / begrüßen ist eine gewisse Differenz bei den Events, denn es muss ein "Loch" bestehen, wenn Session Start und First Visit aus den Einzel-Properties nicht mehr im RollUp erscheinen, wenn es schon eine RollUp Session gestartet wurde. Die Kontrolle bei einzelnen Eventtypen über entsprechende Filter zeigen ein gewisses Muster: Es fehlen neben ein paar view_item und anderen vor allem user_engagement Events, so dass auch die Messung der Engagement-Zeit etwas daneben liegt. Die Folgende Ansicht zeigt, dass von den 9.681 Events Differenz satte 9.509 auf die erwarteten Sitzungsstarts und neu erkannten Nutzer - und eben Engagement-Events - entfallen.

RollUp Events im Vergleich

Die Erklärung liegt (glaube ich jedenfalls) da, wo Events entstehen, bei denen es noch eine existierende GA4 Sitzung der Einzel-Property gibt, aber die RollUp Session des Browsers nicht mehr.  Das passiert z. B. nach dem Schließen, was das Leben des dazu verwendeten Session Cookies beendet. Werden dann Events im Rahmen eines Batches (=mehrere GA4 Events in einem Request) gesendet, entstehen mitunter solche Lücken. Auch der umgekehrte Fall kann diesen Effekt haben.  Daher gibt es - sehr geringe - Differenzen. Aber: Ist das tragisch? Sicher nicht. Wer die Event-Lücke weiter schließen will, kann Lösungen bei der Verwaltung der RollUp Session finden; z. B. über ein gemeinsames Cookie mit einer von der Session unabhängigen Lebensdauer; ggf. per Server gehärtet oder direkt dort erzeugt (siehe oben).

Verbleibt die Differenz in der Transaktionssumme. Ich kann die "knapp 50 Cent" nicht wirklich erklären, aber es gab stets eine gewisse Abweichung im Cent Bereich über den Testzeitraum, in dem die Anzahl der Teilnehmer in Form von Einzel-Properties für ein übersichtliches Test-Setup mit einfacher Auswertung in Google Data Studio begrenzt war - und danach freilich ebenso. Es erscheint auch müßig, hier weiter zu forschen.

Wie man sieht, sind die Unterschiede marginal oder erklärbar und zu verschmerzen. Die RollUp Property macht ihren Job. Eine Vermessung übergreifender Sitzungen, in der Conversions und Umsatz unabhängig vom „Website-Bereich“, in dem sie stattfinden, auf die jeweilige Quelle zurückgeführt werden können.

Achtung: Conversions via Measurement Protocol

Da nicht nur Seitenaufrufe, sondern auch andere Events betroffen sein können, wenn ein Property-Wechsel stattfindet und eine Sonderbehandlung nötig wird, muss in der Rollup-Property im Konfigurationsbereich eine Markierung bzw. ein Eintragen aller in Frage kommenden Conversions sein. Denn während die Information, dass ein Ereignis eine Conversion ist, bei Nutzung des Standard GA4 Tags korrekt in der GA4 Rollup Property ankommt, ist dies beim Measurement Protocol nicht der Fall. Damit in der Rollup Property solche per GA4MP gesendete Events dennoch korrekt als Conversion erkannt werden, muss die Conversion-Konfiguration also auch dort vorgenommen werden. Ja genau: Darauf bin ich (wie auf viele Stolperfallen, die sich hier nicht mehr im Beitrag erkennen lassen) hereingefallen. Hier sieht man die verschiedenen Events, welche beim Property-Wechsel mit einem abweichenden Tag und nicht dem normalen "GA4 RollUp Tag" übertragen wurden.

RollUp Events nach Tag Typ

Wie man sieht, besteht zwar der Löwenanteil an Events, die beim Property-Wechsel entstehen, aus page_view Ereignissen, aber auch alles andere kann dabei sein. Sind es wie hier zu sehen auch Conversions wie generate_lead, werden diese ohne passende Konfiguration in Conversion-Reports der RollUp Property fehlen.

Einschränkungen

Mit Option 2 sind die Ergebnisse m. E. durchaus brauchbar – sowohl in GA4 selbst als auch in Big Query. Einige Einschränkungen bestehen bei dieser Methode, denen man nur schwierig begegnen kann, wenn sie sich zeigen. Zum Glück sind nicht alle Probleme gleich relevant für jedes Setup.

  • Es wird ggf. zu Inkonsistenzen in der Bestückung von Event Properties… und – viel schlimmer – User Properties kommen. Sobald es einen Session Scope gibt, wird es nicht besser.
  • Innerhalb einer Sitzung kann der Status von einer „Engaged“ Session beim Property-Wechsel wieder auf „Not Engaged“ zurück wechseln
  • Das Ergebnis in der Sammel-Property ist großteilig abhängig vom Setup der Einzel-Properties. Meint: Alle Teil-Properties sollten idealerweise vergleichbar aufgesetzt sein und synchron gehalten werden
  • Es kommt zu fehlenden First Visit Infos wie „First Session Source“, wenn Altlasten existieren, also Client IDs nicht neu sind. Der erste auf diese Weise vermessene Einstieg wird so ggf. nicht als First Visit aus Sicht der Teil-Property gemeldet. So fehlt dann schlichtweg für diesen neuen User aus Sicht der Sammel-Property ein Marker für den ersten Besuch und damit sind ebenso die entsprechenden Dimensionen nicht belegt.
  • Spätestens bei Cross Domain Tracking ist die Grenze (außer bei Option 1) erreicht, denn die eigene Session ist (ohne weitere Arbeit im Client und Verzicht auf httpOnly bei serverseitigem Session-Cookie-Handling) nicht zwischen den Domains zu transportieren

Womit anfangen?

Generell ist die Einrichtung der Option 2 ungeachtet der langen Herleitung in diesem Beitrag mit ein paar Variablen und Tags zu erledigen, wenn bereits ein ssGTM im Einsatz ist. Und nach ähnlichem Vorbild können andere First Party Endpunkte genutzt werden, um eine ähnliche Mehrfachverwendung eingehender Daten-Streams unterschiedlicher Properties zu konsolidieren. Selbst dann, wenn die Einrichtung eines ssGTM mit Kosten und Pflegeaufwand verbunden ist: Je nachdem, wie wichtig eine parallele Datenauswertung in GA4 (ohne paralleles Tagging im Browser) ist, sind diese im Vergleich zu den Kosten der 360 Variante zu vernachlässigen. Allein dafür muss man sich die große Version also nicht zwingend zulegen, wenn die anderen Vorteile keine Rolle spielen.

Für einfache Ansprüche oder getrennte Zielgruppen ist Option 1 zumindest für den Start die beste Wahl und erfordert nur ein weiteres Tag am Server – fertig. "All-In Measurement Protocol" hingegen ist nur in Ausnahmefällen sinnvoll. Wenn z. B. der eingehende Datenstrom nicht im GA4 Format daherkommt und ohnehin nur begrenzte Event-Eigenschaften vorhanden sind, mag sich das GA4MP als Option anbieten. Der eigene Client hingegen ist zwar unerprobt, könnte sich bei größeren Datenmengen rentieren und hat theoretisch die beste Abdeckung in der RollUp Property bei minimalem Rechenaufwand am Server.

Welche Option für die eigenen Anforderungen die beste ist, kann im Zweifelsfall anhand mehrerer Optionen oder Varianten (serverside vs. clientside Session Management zum Beispiel) erprobt werden. Zumindest ich habe dadurch meine bevorzugte Lösung gefunden. Wenn Du es auch angehen willst: Viel Erfolg!

Hat Dir der Beitrag geholfen?

Dann freue ich mich, wenn Du ihn mit anderen teilst! Wenn Du magst, gib einen aus ;)

© 2001 - 2024 Markus Baersch