TL;DR, Kurzantwort
8 Min. LesezeitEine Single-Page-Application lädt ein einziges HTML-Dokument und wechselt Screens per JavaScript, also erfasst ein Tag, der nur beim Seitenladen feuert, einen einzigen Pageview für den ganzen Besuch. SPA-Tracking behebt das mit einem virtuellen Pageview bei jedem Routenwechsel, entweder über Events der History API (die GA4-Einstellung "Page changes based on browser history events" hört auf pushState, popState und replaceState) oder über manuelle page_view-Aufrufe. Doppelte Zählungen entstehen, wenn zwei dieser Wege gleichzeitig laufen. Fehlende Pageviews entstehen durch Router, die die URL nicht anfassen, oder durch Pageviews, die vor dem URL-Update gesendet werden.
Was ist SPA-Tracking?
In einer Single-Page-Application bedeutet SPA-Tracking, bei jedem Screenwechsel per JavaScript einen virtuellen Pageview zu erfassen, weil der Browser das HTML-Dokument nur einmal lädt und bei späteren Routenwechseln nie eine neue Seite lädt. Google beschreibt SPAs als "websites that load an HTML document once and fetch any additional content using JavaScript APIs," und formuliert das Ziel klar: "The key to measuring page views from SPAs correctly is to count page views for each screen a user interacts with and get the page referrer right, so you can correctly trace the user journey."
Ein virtueller Pageview ist ein Pageview-Event, das Ihr Analytics-Tool ohne echtes Laden einer Seite sendet. Der Browser fordert nie ein neues Dokument an, aber der Report zeigt eine neue Seite mit eigener URL und eigenem Referrer, genau so, als hätte er es getan.
Warum verpasst ein Standard-Analytics-Tag SPA-Pageviews?
Ein Standard-Analytics-Tag verpasst SPA-Pageviews, weil er seinen Pageview sendet, wenn das Skript zum ersten Mal läuft, und in einer SPA läuft das Skript einmal pro Besuch. Ein Besucher, der auf / landet und dann über In-App-Links /pricing und /signup öffnet, hat Entscheidungen auf drei Screens getroffen, während ein Tag, der nur beim Laden feuert, einen Pageview für / erfasst.
Der Schaden reicht über die Pageview-Zahl hinaus. Google schreibt, dass ohne virtuelle Pageviews "Google Analytics treats the SPA as a single page, leading to skewed metrics," und dass "all engagement time is attributed to the initial page load, making it impossible to analyze time spent on individual screens." Auch Klicks und Scrolls landen unter der Einstiegs-URL. Der Leitfaden zu Pageviews, Sessions und Nutzern erklärt, warum wenige Pageviews pro Session in einer SPA zuerst ein Tracking-Signal sind und erst dann ein Verhaltenssignal.
![]()
Wie signalisiert die History API einen Routenwechsel?
Die History API signalisiert einen Routenwechsel über Methoden, die Ihr Router aufruft, und Events, die der Browser auslöst, und beide passen nicht eins zu eins zusammen. Wegen dieser Lücke müssen Tracker an mehr als einer Stelle lauschen.
| Änderung | Was sie auslöst | Ausgelöstes Browser-Event |
|---|---|---|
history.pushState() | Ihr Router, bei einem In-App-Link | Keines |
history.replaceState() | Ihr Router, wenn er die aktuelle URL umschreibt | Keines |
| Zurück- oder Vorwärts-Button | Der Besucher | popstate |
history.back(), forward(), go() | Ihr Code | popstate |
Hash-Änderung (#section) | Ein Link oder Code, der das Fragment ändert | hashchange |
MDN ist bei den ersten beiden Zeilen eindeutig: "just calling history.pushState() or history.replaceState() won't trigger a popstate event." Ein Tracker, der nur auf popstate hört, sieht Klicks auf Zurück und Vorwärts und verpasst jede Vorwärtsnavigation über Ihre eigenen Links. Tracker lösen das, indem sie pushState und replaceState direkt umhüllen oder beobachten.
Wie trackt GA4 Single-Page-Applications?
GA4 trackt Single-Page-Applications über eine Einstellung der erweiterten Analyse, die einen page_view sendet, wenn sich die Browser-History ändert. Googles Hilfecenter beschreibt den Trigger für page_view als "each time the page loads or the browser history state is changed by the active site," und sagt, die erweiterte Einstellung "listens for pushState, popState, and replaceState." Google empfiehlt diesen Weg "If your SPA uses the History API, specifically the pushState() and replaceState() method to update screens."
So schalten Sie sie ein:
- Öffnen Sie in Google Analytics Admin.
- Klicken Sie unter Data collection and modification auf Data streams und dann auf Ihren Web-Stream.
- Schalten Sie unter Enhanced measurement den Schalter ein.
- Klicken Sie auf das Einstellungssymbol und unter Page views auf Show advanced settings.
- Aktivieren Sie sowohl Page loads als auch Page changes based on browser history events.
- Speichern Sie.
Der andere Weg ist manuell. Google nennt "Custom events" für Websites, auf denen Screens ohne URL-Änderung gerendert werden, etwa eine App, die DocumentFragment-Objekte nutzt. In diesem Fall senden Sie gtag('event', 'page_view', { page_title: '...', page_location: '...' }) selbst aus Ihrem Router.
Was verursacht doppelte Zählungen beim SPA-Tracking?
Doppelte Zählungen beim SPA-Tracking entstehen, wenn zwei Mechanismen für denselben Routenwechsel jeweils einen Pageview senden. Die üblichen Setups, die das verursachen:
- Google Tag Manager plus GA4-History-Events. Googles Warnung: "If you configure your tags using Google Tag Manager, don't enable automatic history tracking in Google Analytics, as this can lead to double-counting page views." Ein History-Change-Trigger in GTM feuert bereits, "when the URL fragment changes or when a site uses the HTML5 pushstate API."
- Manuelle page_view-Aufrufe plus die History-Einstellung.
send_page_view: falsestoppt History-basierte Pageviews nicht. Google schreibt: "If Enhanced Measurement is enabled, Google Analytics will sendpage_viewevents based on browser history changes even if you setsend_page_view: false." Schalten Sie Page changes based on browser history events ab, wenn Ihr Router eigene Pageviews sendet. - replaceState für Filter oder Tabs. GA4 zählt replaceState zu den History-Änderungen, auf die es hört. Eine Produktliste, die
?sort=priceperreplaceStatein die URL schreibt, kann also bei jeder Filteränderung Pageviews erzeugen. Testen Sie das in DebugView, bevor Sie den Seitenzahlen auf filterlastigen Screens trauen. - Zwei Google-Tags mit derselben ID. Ein fest eingebautes gtag-Snippet und ein Google-Tag in GTM, die auf dieselbe Mess-ID zeigen, senden jeweils eigene Events.
Was verursacht fehlende Pageviews beim SPA-Tracking?
Fehlende Pageviews beim SPA-Tracking entstehen durch Routenwechsel, die nie bei der History API ankommen, und durch Pageviews, die zum falschen Zeitpunkt gesendet werden.
- Router, die die URL nie ändern. Eine App, die Komponenten im Speicher austauscht, gibt einem History-Listener nichts zu hören. Nutzen Sie den Weg über eigene Events.
- Hash-Routing mit einem reinen History-Tracker. Eine Änderung von
#/pricinglösthashchangeaus. Prüfen Sie, ob Ihr Tool Fragment-Änderungen zählt, und konfigurieren Sie es, falls nicht. - Pageviews, die vor dem URL-Update gesendet werden. Ein
page_view, der vorpushStatefeuert, erfasst die altepage_location. Für DebugView rät Google, jedenpage_view"with the precedingpage_viewevent to check if the page referrer and page location have been updated correctly" zu vergleichen. - Veraltete Referrer. Googles Beispiel für eigene Events speichert die alte URL und übergibt sie als
page_referrer, weil das browsereigenedocument.referrerfür den ganzen Besuch auf dem ursprünglichen Einstiegs-Referrer stehen bleibt.
Eine verwandte Falle liegt außerhalb des Routers. web.dev schreibt, dass der Back/Forward-Cache "doesn't work for 'soft navigations' within a single-page app." Ein Klick auf Zurück innerhalb Ihrer App ist also ein History-Event, während ein Klick auf Zurück, der von einer anderen Website in Ihre App zurückführt, die ganze Seite aus dem Speicher wiederherstellen kann und überhaupt kein History-Event auslöst.
![]()
Wie prüfen Sie, ob SPA-Tracking funktioniert?
Sie prüfen SPA-Tracking, indem Sie sich mit aktivem Debug-Modus durch die App klicken und kontrollieren, dass jeder neue Screen genau einen Pageview mit richtigem Ort und Referrer erzeugt. Googles eigene Prüfung lautet, den Debug-Modus zu aktivieren, "click through your single-page application," und für jeden virtuellen Screen "a new page_view event in DebugView" zu bestätigen. Wiederholen Sie das danach mit den Buttons Zurück und Vorwärts, einer Filteränderung und einem Hash-Link, denn genau diese Fälle zählen doppelt oder fallen weg. Die Checkliste zur Analytics-Prüfung wendet dieselbe Idee auf jeden Tracker an, und der Leitfaden zur durchschnittlichen Sitzungsdauer zeigt, was kaputtes SPA-Tracking mit den Zahlen zur Verweildauer macht.
Flowsery
Jetzt 14 Tage kostenlos testen
Echtzeit-Dashboard
Zielverfolgung
Cookie-freies Tracking
Zwei kleinere Korrekturen machen die Zahlen belastbarer. Setzen Sie die Scrollposition bei jedem Routenwechsel mit window.scrollTo(0, 0) zurück, damit die Scrolltiefe für den neuen Screen gilt und nicht für den alten, und senden Sie den Pageview erst, nachdem der Router URL und Titel aktualisiert hat.
Wie geht Flowsery mit SPA-Navigation um?
Flowsery trackt SPA-Navigation automatisch, ein Routenwechsel in React Router oder Next.js erscheint also ohne zusätzlichen Code als eigener Pageview. Die Dokumentation des npm-SDK von Flowsery nennt "pageviews, including SPA navigation" unter dem automatischen Tracking, und die Preis-FAQ sagt, dass Flowsery "counts a pageview each time a visitor loads a page on your site, including single-page app navigations." Für Apps, die mit URL-Fragmenten routen, hat das npm-SDK eine Option hashMode, und die Skript-Dokumentation beschreibt eine Hash-Routing-Version des Trackers für SPAs mit Hash-Routing. Wenn Ihre App Screens wechselt, ohne die URL zu ändern, stellt das SDK trackPageview() bereit, damit Sie einen Pageview aus Ihrem eigenen Code senden können. Die Seite zu React-Analytics erklärt, wie Flowsery clientseitige Routen, eigene Events, Funnels und Umsatz in React-Apps misst.
Häufig gestellte Fragen
Was ist ein virtueller Pageview?
Ein virtueller Pageview ist ein Pageview-Event, das ohne echtes Laden einer Seite gesendet wird, wenn eine SPA Screens per JavaScript wechselt. Es trägt einen eigenen Seitenort und einen eigenen Referrer, sodass Reports jeden Screen als eigene Seite behandeln. Ohne ihn erscheint ein SPA-Besuch als ein langer Aufruf der Einstiegsseite.
Trackt GA4 SPA-Routenwechsel automatisch?
Ja, wenn die erweiterte Analyse eingeschaltet und Page changes based on browser history events in den erweiterten Einstellungen unter Page views aktiviert ist. Diese Einstellung hört auf pushState, popState und replaceState. Bei Apps, die Screens wechseln, ohne die URL zu ändern, hilft sie nicht.
Warum zählt GA4 jeden SPA-Pageview doppelt?
Zwei Mechanismen senden Pageviews für dieselbe Änderung. Die üblichen Paare sind History-Trigger in GTM mit GA4-History-Events oder manuelle page_view-Aufrufe mit GA4-History-Events. Schalten Sie einen davon ab. Google schreibt, dass send_page_view: false History-basierte Pageviews nicht stoppt.
Löst pushState popstate aus?
Nein. MDN schreibt, dass ein Aufruf von history.pushState() oder history.replaceState() kein popstate-Event auslöst. Nur Browser-Aktionen wie die Buttons Zurück und Vorwärts oder Aufrufe wie history.back() lösen es aus.
Wie sollte page_referrer in einer SPA funktionieren?
Jeder virtuelle Pageview sollte die URL des vorherigen Screens als Referrer tragen. Speichern Sie die alte URL vor dem Routenwechsel und übergeben Sie sie als page_referrer zusammen mit der neuen page_location. Sonst meldet jeder Screen den ursprünglichen Einstiegs-Referrer.
Beeinflusst der Back/Forward-Cache das SPA-Tracking?
Nicht bei Navigationen innerhalb der App. web.dev schreibt, dass der bfcache bei Soft Navigations innerhalb einer SPA nicht greift. Er greift aber, wenn ein Besucher Ihre App verlässt und mit dem Zurück-Button zurückkommt, wodurch die ganze Seite ohne neues Laden aus dem Speicher wiederhergestellt werden kann, sofern die Seite dafür infrage kommt.
Wie aktiviere ich SPA-Tracking in GA4?
Öffnen Sie Admin, klicken Sie auf Data streams, wählen Sie Ihren Web-Stream und schalten Sie Enhanced measurement ein. Klicken Sie dann auf das Einstellungssymbol, öffnen Sie unter Page views Show advanced settings und aktivieren Sie sowohl Page loads als auch Page changes based on browser history events. Speichern Sie. Diese Variante funktioniert, wenn Ihr Router pushState und replaceState nutzt.
Sollte ich das GA4-Verlaufstracking aktivieren, wenn ich Google Tag Manager nutze?
Lassen Sie es aus. Google warnt, dass die Kombination beider zu doppelt gezählten Seitenaufrufen führen kann. Ein GTM-History-Change-Trigger löst bereits aus, wenn sich das URL-Fragment ändert oder wenn eine Seite die HTML5-pushstate-API nutzt.
Wie tracke ich Hash-Routen wie #/pricing in einer SPA?
Eine Änderung des Fragments löst hashchange aus. Ein Tracker, der nur die History API beobachtet, kann sie deshalb verpassen. Prüfen Sie, ob Ihr Tool Fragmentänderungen zählt, und konfigurieren Sie es, falls nicht. Das npm-SDK von Flowsery hat eine Option hashMode, und die Script-Doku beschreibt eine Tracker-Version für Hash-Routing.
Wie prüfe ich, ob meine SPA pro Screen einen Pageview sendet?
Schalten Sie den Debug-Modus ein, klicken Sie durch die App und suchen Sie im DebugView für jeden Screen nach einem neuen page_view-Ereignis. Vergleichen Sie jedes mit dem vorherigen page_view, um zu sehen, ob Seitenort und Referrer aktualisiert wurden. Wiederholen Sie das mit Zurück- und Vorwärts-Button, einem Filterwechsel und einem Hash-Link.
War dieser Artikel hilfreich?
Teilen Sie uns Ihre Meinung mit!
Sehen Sie uns öfter bei Google
Ein Klick macht Flowsery zu einer bevorzugten Quelle. Unsere Artikel stehen dann weiter oben in Ihren Top-Meldungen, im KI-Modus und in den KI-Übersichten.
Bevor Sie gehen...
Flowsery
Umsatzorientierte Analysen für Ihre Website
Verfolgen Sie jeden Besucher, jede Quelle und jede Conversion in Echtzeit. Einfach, leistungsstark und komplett ohne Cookies.
Echtzeit-Dashboard
Zielverfolgung
Cookie-freies Tracking
Verwandte Glossarbegriffe


Warum Ihre GA4-Absprungrate nur die umgedrehte Engagement-Rate ist
Ihre GA4-Absprungrate ist der Anteil nicht engagierter Sitzungen. Wie Google sie definiert, was anders ist als in Universal Analytics und wo Sie sie ergänzen.


Was der GA4-Landing-Page-Bericht zählt und wo er leer bleibt
Googles GA4-Landing-Page-Bericht listet die erste Seite jeder Session. Wo er liegt, Standardkennzahlen, Zeilen mit (not set) und wie Sie die Quelle ergänzen.


Wie die GA4-Website-Suche erfasst, was Besucher eintippen
So richten Sie die GA4-Website-Suche über Enhanced Measurement ein, ergänzen eigene Parameter, finden die Dimension Search term und messen Suchen ohne URL.


So setzen Sie Nutzereigenschaften in GA4 und werten sie in Reports aus
So setzen Sie Nutzereigenschaften in GA4 per gtag oder Tag Manager, registrieren sie als nutzerbezogene Dimensionen und bleiben unter dem Limit von 25.


Wie Sie die Search Console mit GA4 verknüpfen und ihre Reports veröffentlichen
So lässt sich die Search Console mit GA4 verknüpfen: nötige Rollen, die zwei Reports in der Library veröffentlichen und was sich nicht verbinden lässt.


Was der bfcache mit Zurück-Navigationen und Ihren Pageview-Zahlen macht
Der bfcache, also der Back/Forward-Cache, stellt Seiten beim Zurückklicken aus dem Speicher wieder her. Welche Seiten infrage kommen und wo Analytics sich irrt.
Verwandte Artikel


Wie Sie berechnete Messwerte in GA4 mit nur fünf Plätzen erstellen
Google erlaubt nur 5 berechnete Messwerte in GA4 pro Standard-Property. Hier stehen Formelsyntax, Einheiten, Fundorte und was keine Formel nutzen darf.


So richten Sie die Content-Gruppierung in GA4 mit einem Parameter ein
So richten Sie die Content-Gruppierung in GA4 mit content_group per gtag oder Tag Manager ein, lesen die Dimension Content group und vermeiden (not set).


So fügen Sie Google-Analytics-Annotationen in GA4 hinzu und führen ein Änderungsprotokoll
In GA4 heften Google-Analytics-Annotationen eine datierte Notiz an Liniendiagramme. Wer sie anlegt, Limits von 60 und 150 Zeichen, 1,000 je Property.