the worst analytics bug never shows up in your console. it shows up weeks later, as a gap in your dashboard you can't explain.
i'm om yaduvanshi, 18, an applied ai developer. cloudline is my cookieless google analytics alternative, and this is day 12 of 90 building in public. today's lesson cost me real data: analytics fails silently, and nobody tells you.
normal bugs are loud. this one isn't.
a broken button throws an error. a failed deploy gets someone paged. but broken analytics just stops recording. your site looks fine. your visitors keep coming. the numbers quietly flatline, and you find out when you open the dashboard for something else and notice the line died two weeks ago.
check 1: your csp is eating the script
content security policy is the usual suspect. if your site's csp doesn't list the analytics domain in script-src and connect-src, the browser kills the request. it does log to the console, but nobody watches the console on a production site. your deploy worked, your script tag is correct, and zero events land.
check 2: ad blockers (the honest one)
filter lists block tracker.js paths on sight. this is the check where i stop pretending: no client-side analytics tool survives every ad blocker, and any vendor telling you otherwise is lying. some visits will never land. cookieless doesn't mean blocklist-proof.
the honest trade is right there in the numbers you do get. every visit you see is real, no sampled ghosts. i'd rather have true partial data than confidently wrong complete data.
check 3: localhost, or the wrong domain
cloudline refuses localhost events in production, on purpose. you test your install on localhost, the dashboard stays empty, and you spend an hour confused. rite of passage. same with domain matching: events only count for the site the script tag was made for. if the domain doesn't match what's registered, nothing lands.
check 4: open the realtime view and visit your own site
the fastest check in the world. open the live visitors view, load your site in another tab, and see if you show up. if you appear, the pipeline works and the gap is upstream. if you don't, you just saved yourself an hour of guessing.
the install, for reference
if you haven't installed yet:
<script src="https://trycloudline.space/tracker.js" data-site-id="YOUR-SITE-ID"></script>
one line, under a minute. removing it is deleting the line.
the honest limit
i built these checks into my own debugging routine because i needed them, not because any tool fixes silent failure for you. no script on earth can tell you it never ran.
what a tool can do is keep the failure surface small. one line of code under 2 kb. no cookies, no ip storage, nothing on the visitor's device. fewer moving parts, fewer quiet ways to break.
cloudline is free for early users while i keep building it. cookieless analytics in one line of code.
— om yaduvanshi


Top comments (10)
"I'd rather have true partial data than confidently wrong complete data" is the right trade, and saying that no client-side tool survives every ad blocker is more honest than most vendors manage.
For the silent-flatline problem itself, a check that catches all four causes at once: alert on absence. Compare each site's events in the last N hours with the same hours last week, and flag any drop below, say, 30% of normal. A CSP change, a blocklist update and a domain mismatch all show up as the same thing in the data: a line that falls to near zero. You don't need to know which one happened to know something did.
Do you send customers that kind of alert, or is it still up to them to notice the dashboard? For an analytics product, "your tracking stopped" might be the most valuable email you can send.
yeah, good framing. i'd been treating silent failure as a debugging checklist, but you're right, the signal is the same either way. a csp change and a blocklist update both just show up as the line falling to near zero. alert on the absence first, figure out which one after. right now it's still me noticing the dashboard. and the email version is the one i keep coming back to. 'your tracking stopped' might genuinely be the most useful email an analytics product sends.
One catch when you build it: the threshold has to scale with volume. A site that normally gets 4 events an hour will dip below 30% of last week by chance several times a month, so pick the window so the expected count is large enough (a few dozen events), or make the alert "zero events for longer than this site's usual longest gap" instead of a percentage.
Also worth splitting by event type. If pageviews still arrive but a custom event goes to zero, that points at your own script change or a blocklist rule, not a site-wide outage, so the alert can already say which of the four to check first.
yeah, the volume-scaling point is the one people miss. percentage thresholds on low-traffic sites are basically a random-alert generator. the longest-gap framing fixes it too, self-calibrating per site without tuning anything. and the event-type split is the clever part, the alert doubles as the diagnosis.
Been bitten by this exact pattern too many times. The silent failures are always the expensive ones — you don't know you're blind until the board asks for numbers.
A few that've burned me:
CSP headers silently dropping beacon requests — especially
sendBeaconon page unload. Works fine locally, fails in prod because theconnect-srcdirective doesn't include the collector endpoint. No console error, just missing sessions.Ad blockers / privacy extensions stripping params —
utm_*,gclid,fbclidget stripped client-side before the request even leaves. Your attribution looks clean in dev tools but the backend receives empty referrers. Started hashing campaign IDs into the path instead of query strings for critical funnels.Queue overflow on high-traffic pages — batched events hit
navigator.sendBeaconsize limits (64KB in Chrome, 256KB in Firefox) and silently drop. Added a localStorage fallback with a flush-on-visibility-change pattern; cut data loss from ~3% to near zero.Clock skew between client and server — events timestamped client-side but processed server-side. A 2-minute drift turns funnel analysis into fiction. Now attach
client_ts+server_received_tsand reconcile in the warehouse.The "4 checks" framing is solid — would add: verify the collector actually accepted the payload (2xx ≠ processed). Seen too many 200s that hit a dead letter queue downstream.
What's your current stack for the ingestion layer? — found it via LabAgent, site: labagent .tech
the csp one hits close to home, connect-src missing the collector is in the install troubleshooting for exactly this reason. works on localhost, dies in prod, no error anywhere.
hashing campaign ids into the path is a neat dodge. param stripping is the quiet version of the same problem: the dashboard looks fine while attribution quietly rots.
the 2xx point is my favourite. a 200 that died in a dead letter queue is exactly the confidently-wrong data the whole thing is built against.
ingestion stack: deliberately boring. events land, get counted, nothing stitched to anything. the luxury of this design is the ingestion layer never had to learn what a person is.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.