Hash and hashbang routing gaps
Some single-page apps route via the URL fragment (#/path or the older #! hashbang). The fragment after # is never sent to the server and does not trigger a navigation, so server logs and pageview scripts that rely on full navigations miss these route changes. The result is undercounted views and a landing URL stuck at the entry path. This page explains hash-routing measurement gaps.
Why the fragment is invisible
The part of a URL after the # is the fragment identifier. Browsers do not include it in HTTP requests, and changing it does not cause a navigation — it fires a hashchange event in the page but the server never learns about it. Apps that route with #/path or the legacy #! hashbang therefore change views without any server-visible request.
Pageview scripts keyed to navigations, and server logs, both miss every fragment-only route change.
- Fragment after # is not sent to the server
- Changing it fires hashchange, not a navigation
- Server logs and load-based scripts miss the change
Capturing hash routes
Subscribe to the hashchange event (or the router's own navigation hook) and send a pageview with the full fragment-aware path on each change. Make sure the page path you report includes the fragment route, or every view collapses onto the entry URL. If you control routing, prefer the History API for new work, but for existing hash routers, instrument hashchange explicitly.
This is distinct from the double-counting cases: here the risk is too few views, not too many.
How it appears in analytics and logs
A hash-routed app showing one landing URL for entire sessions means fragment changes are not being tracked, not that users never navigate.
Diagnostic use case
Capture route changes in hash-based single-page apps that fragment-only navigation would otherwise hide from analytics.
What WebmasterID can help detect
WebmasterID can record explicit route events from the app, so hash-only navigation is captured rather than lost to the server.
Common mistakes
- Relying on navigations to detect fragment-only route changes.
- Reporting a path that omits the fragment route.
- Assuming server logs see hash-based navigation.
Privacy and accuracy notes
Tracking fragment routes uses URLs your app controls, not personal data. This page is educational, not legal advice.
Related pages
- Single-page-app tracking gaps
In a single-page application, the browser loads once and the framework swaps views via the History API without a new document load. Analytics that depend on the load event therefore record only the first screen. This page explains the gaps — missing virtual pageviews, stale page paths, and broken referrer chains — and how SPA-aware tracking closes them.
- Duplicate pageviews in SPAs
Single-page apps often send a pageview on initial load and another from a route-change listener, and on the very first view both can fire for the same URL. Strict-mode double renders, mounting effects that run twice, and duplicate listeners add more. The result is inflated pageviews concentrated on entry pages. This page explains duplicate SPA pageviews and how to fire exactly one per route.
- URL parameters splitting page reports
When URLs carry query parameters — campaign tags, ad-click IDs, session tokens, sort and filter state — analytics often treats each variant as a different page. One article scatters across dozens of rows, no single line shows its true total, and cardinality balloons. This page explains how URL parameter noise fragments page reports and how normalising paths fixes it.
- Events documentation
Send fragment-aware route events explicitly.
Sources and verification notes
Last reviewed 2026-06-24. Facts are checked against primary/official sources where available; uncertain specifics are marked “Data not yet verified” rather than guessed.