Google Analytics Showed 22 Users, Then 0. We Spent an Afternoon Proving Nothing Was Wrong.
Free spatial notes
Put this workflow on an infinite canvas instead of another linear doc.
Start in the browser with no account. Create an account only when you want to sync what you made.
The Symptom
Google Analytics realtime was showing periods with a healthy number of active users, then periods with none. The pattern repeated. It looked like something was intermittently breaking.
When your own analytics look broken, everything downstream becomes untrustworthy — you cannot evaluate a marketing change, a deploy, or a funnel experiment. So it was worth an afternoon.
What We Checked
Where the tag comes from. Analytics is not hardcoded anywhere in our application. It is injected by our edge tag manager. That immediately narrows the search: if the tag is not in our bundle, our bundle is unlikely to be breaking it, though it could still block it.
Whether the tag manager is reachable. We fetched the tag manager script directly on both the marketing domain and the app subdomain. Both served correctly, and both returned a valid analytics configuration with the same measurement ID.
Whether our error handling was interfering. This was the most plausible internal suspect. We have global error handlers that suppress console noise from third-party scripts. If one of those were doing more than suppressing logs — cancelling an event, swallowing a rejection that mattered — it could break the tag while looking innocent.
We read them. They suppress logging only. They do not prevent execution and do not cancel anything.
Whether headers were blocking it. No content security policy or header rule in the repository blocks either the tag manager or the analytics endpoint.
Whether the site was intermittently failing. We ran repeated synthetic checks:
- Marketing domain: 20 of 20 requests returned 200
- App domain: 20 of 20 returned 200
- Tag manager script on both domains: 20 of 20 returned 200
- Marketing routes — home, pricing, blog, tools, demo, sitemap, robots: all 200
- App shell, manifest, favicon: 200. The authenticated API endpoint returned the expected 401 when unauthenticated
- Both production builds passed
No intermittent failures.
The Most Likely Explanation
The screenshot may simply be normal, and this is the part worth internalizing.
Realtime analytics reports over different windows. A "last 30 minutes" count of 22 is entirely compatible with a "last 5 minutes" count of 0. Traffic arrived in a burst 6 to 30 minutes ago, and nobody is on the site right now. Both numbers are correct and they describe different things.
For a site with our traffic profile — a few hundred sessions a day, arriving unevenly — realtime is expected to alternate between some users and no users. It is not a smooth line. At low volume, realtime analytics is closer to a stream of individual arrivals than a rate.
Realtime is also the noisiest report available. Ad blockers, privacy-focused browsers, tracking protection, and consent restrictions all suppress events. A meaningful share of visitors never appear in realtime at all, and that share varies with where the traffic came from — technical audiences block far more than general ones.
What We Could Not Verify
Two things, stated plainly because an investigation that reports only what it proved is not an honest investigation.
The tag manager dashboard configuration. Everything we could inspect from code and from the live site was correct, but the configuration itself lives in a dashboard. The things to check there — whether analytics is enabled for both domains, whether the trigger covers single-page-app navigation as well as initial pageview, whether any consent or rule filter intermittently excludes traffic — cannot be verified from a repository.
The single-page-app trigger is the one most likely to cause real problems. If only initial pageviews fire and in-app navigations do not, a visitor who lands and browses registers one event and then vanishes, which produces exactly the sparse realtime pattern we were looking at.
Production error telemetry. We wanted to query our own client error logs. The API token we had was not authorized for that database. So we could not rule out intermittent client-side errors from real user sessions.
That is a gap, and the honest conclusion is that we found no evidence of a problem rather than that we proved there is none. Those are different claims and the difference matters. Reporting "everything is fine" when you could not check one of the most relevant sources would have been wrong.
What We Took Away
Know the shape of your own traffic before diagnosing your analytics. At low volume, realtime alternating between some and none is the expected behavior, not a symptom.
Read the windows on the report. "Last 30 minutes" and "last 5 minutes" disagreeing is not a contradiction.
Rule out your own code first, and read the handler rather than assuming. Our error suppression looked suspicious and was innocent. It took five minutes to confirm.
Fix credential access before you need it. The most valuable check in this investigation was the one we could not run. An expired or under-scoped token is not a problem until it is the thing standing between you and an answer.
Say what you could not verify. An investigation with a stated gap is more useful than a confident all-clear, because the reader knows where to look if the symptom recurs.
Try the product the analytics were arguing about — no account required.
30 days free. No credit card required.
Try the Brainstorm Web template in OmniCanvas
Open a local canvas with the Brainstorm Web layout ready to go — no setup or account needed.
Use the Brainstorm Web TemplateStart locally, then sign up only to sync — or explore the interactive demo first.
Keep reading
Our SEO Audit Said Our JavaScript Was Broken. It Wasn't. The Real Problem Was Worse.
An automated crawl reported broken JavaScript on two pages. We could not reproduce it, so we did not fix it. The same investigation found 192 URLs quietly redirecting.
InsightsOur AI-Written Competitor Comparisons Were Lying About Our Own Product
We generated a cluster of alternatives posts with AI. Then we read them. Eleven posts denied features OmniCanvas actually ships. Here is the failure mode nobody warns you about.
InsightsOne Canvas, Four Modes: How We Added Slides and Design Without Splitting the Product
Notes, Whiteboard, Slides, and Design are four different tools. We built them as four lenses over a single canvas, and the hard part was everything switching modes must not do.