tanstack-router-ga4: Clean Google Analytics for TanStack Router/Start
Ben Houston • 4 Minutes Read • March 17, 2026
Today I am releasing tanstack-router-ga4: a tiny Google Analytics integration for TanStack Router and TanStack Start that gives you automatic page_view tracking, typed GA4 helpers, and a setup that fits naturally into modern React app shells.
It is available now on npm as tanstack-router-ga4, with a live demo at tanstack-router-ga4.benhouston3d.com.
Usage is intentionally very simple:
import { HeadContent, Scripts } from "@tanstack/react-router"; import { GoogleAnalytics } from "tanstack-router-ga4"; function RootDocument({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> <HeadContent /> </head> <body> <GoogleAnalytics measurementId="G-XXXXXXXXXX" /> {children} <Scripts /> </body> </html> ); }
That gives you route-aware page_view tracking without hand-rolled listeners or custom wrappers scattered across your app.
Motivation
I have been using TanStack Router and TanStack Start more and more over the last year, and I like the explicitness and type safety of that stack a lot. But analytics integration was still annoyingly messy.
The problems I kept running into were pretty consistent:
react-ga4was not working correctly for my Vite 8 setup.- A lot of sample integrations online were too React-generic and did not really understand TanStack Router's lifecycle.
- Hand-rolled route listeners are fragile and easy to get subtly wrong.
- Multi-stream GA4 configuration is easy to misunderstand.
- Many wrappers are either under-typed or not typed at all.
I did not want a giant analytics abstraction. I wanted a very small module that did the boring parts correctly and stayed out of the way.
One of the things that pushed me into packaging this as a reusable library instead of just solving it once inside an app was how often AI coding tools produced buggy integrations here.
Out of the box, ChatGPT Codex, Claude Sonnet, and Gemini Pro would often generate GA4 code that looked plausible but was subtly incorrect:
- hallucinated GA4 API capabilities that do not actually exist
- incorrect initialization order inside React apps
- confusion about
set()vsconfig() - no real understanding of per-stream config
- broken assumptions about automatic page view behavior
- awkward client-only code that did not fit cleanly into TanStack Start root documents
This is exactly the kind of problem area that is annoying in real production apps: not hard enough to justify a massive dependency, but subtle enough that many generated solutions are wrong.
Why This Fits TanStack Router/Start Well
One of the things I like most about TanStack Router and TanStack Start is that they push you toward more explicit application structure. You have a real app shell. You have explicit route transitions. You have a clearer sense of where cross-cutting concerns belong.
Analytics is one of those cross-cutting concerns.
So instead of wiring up ad hoc listeners in random components, tanstack-router-ga4 lets you mount a GoogleAnalytics component near the top of your app and let it track route changes from there. That feels much more natural in a TanStack Router/Start app than the usual copy-pasted snippets.
It is also fully type-safe, which matters to me. If I am using TanStack specifically because I want stronger correctness guarantees, I do not want analytics to be the untyped corner of the codebase.
A Practical Example
Once the component is mounted, you can use the hook anywhere you need to send events or update analytics state:
const ga = useGoogleAnalytics(); ga.set({ user_id: user.id, user_properties: { email: user.email, username: user.username, }, }); ga.event("sign_up", { method: "email", });
And if you need per-stream config, that is supported too:
const ga = useGoogleAnalytics(); ga.config("G-MAINSTREAM", { debug_mode: true, send_page_view: false, }); ga.config("G-MARKETING", { campaign_source: "newsletter", send_page_view: false, });
That distinction matters. GA4's global and per-stream behavior is one of the areas that many example snippets and generated integrations get wrong.
Try It
pnpm add tanstack-router-ga4
- npm: tanstack-router-ga4
- GitHub: bhouston/tanstack-router-ga4
- Demo: tanstack-router-ga4.benhouston3d.com
If you are building on TanStack Router or TanStack Start and want a cleaner GA4 integration, give it a try.