The privacy promise your analytics quietly broke

I caught my own site lying to visitors, in a line I had written myself. The boot copy on the terminal, the little wake-up greeting, told anyone who landed that there were no fingerprints here. I believed it when I wrote it. Then I actually looked at what the page loaded on every single visit, and the analytics script sitting in there was deriving a visitor id by hashing the IP address, the user agent, and a daily salt. That is a fingerprint. My site had been promising one thing and doing the opposite, quietly, on every page load, for longer than I want to admit.

So here is the honest answer to whether the analytics on your vibe coded site is actually private: probably not, and not because the tool is shady, but because a privacy claim you wrote once and never rechecked against what your site actually loads has almost certainly drifted. Most drop-in analytics count "unique" visitors by deriving an id from request attributes, which is a fingerprint no matter what the marketing page calls it. The claim and the code are two separate statements about the same thing, and nothing keeps them in sync unless you do it on purpose.

why does a "no tracking" claim drift from the truth?

Because you write the two halves at different times, in different moods, and never put them in the same room again. The privacy copy gets written early, when the site is mostly intention and you mean every word. The analytics gets added later, on an afternoon when you just want to see whether anyone is actually visiting, so you paste in the script the whole category uses and move on. Nobody reopens the privacy page after that. Why would you. It already says the nice thing.

This is the trap I keep pointing vibe coders back to, because it is the same shape every time. The confident copy is a surface signal. It reads clean, it sounds principled, and it is completely disconnected from what the machine does. What the site actually collects is the semantic reality, and it is the only one of the two that is true. A green surface, whether it is a passing test or a reassuring privacy line, proposes that things are fine. Only measuring the real behavior underneath disposes of the question. If you have never opened the network tab and read what your own site loads, you do not actually know what your privacy page is promising on your behalf.

what I found when I measured instead of trusting

The receipt is boring, which is the point. It was not an exotic tracker or a data broker. It was a mainstream, well-regarded analytics tool that everyone uses, doing exactly what that whole product category does: to count a unique visitor without a login, it takes the things every request carries, the IP and the user agent, mixes in a rotating daily salt, and hashes them into a stable-enough id. No cookie banner required, which is exactly why people reach for it. But an id derived from who you are and what you are using is a fingerprint under any honest reading of the word, and my boot copy had promised there were none.

The part that stung was that I had built the honest disclosure everywhere else. The chatbot announces what it stores before it stores anything. The visitor record only gets written when someone actually engages, never on a passive page load. I had been careful about the collection I designed myself, and completely blind to the collection I imported in one line and never audited. The thing you wrote gets your attention. The thing you pasted in gets a pass.

pull it, or rewrite the claim?

Those are the only two honest moves, and you have to pick one on purpose. My first move was to pull the analytics entirely, same day, so the promise was true again while I thought. I want to name the move I did not make, because it is the tempting one: switching vendors fixes nothing. Deriving identity from request attributes is not one bad tool, it is how the entire cookieless-analytics category counts uniques, so a different logo doing the same hash leaves you in exactly the same lie with a cleaner conscience.

Then I made the real call. I actually did want an anonymous view count, so I brought analytics back deliberately and rewrote the copy to match precisely what it now does: it counts an anonymous page view on load, it sees and keeps no IP here, and it builds no profile of you. I also moved the date on the privacy page, because a privacy page dated before the collection it describes is its own small dishonesty. The claim now matches the mechanism, line for line. That is the whole discipline. Decide what you are willing to collect, then make the words on the page say exactly that and nothing more generous.

how do I check my own site?

Open your deployed site, not localhost, and watch what it loads. List every third-party script and ask one question of each: what signal about the visitor does this derive. Anything that turns an IP, a user agent, a device, or a canvas into a stable id is fingerprinting, whatever the dashboard calls it. Then read your privacy copy one line at a time against that list, and treat every mismatch as a bug, because it is one. You are not auditing for lawyers. You are checking that the site a real person meets tells them the truth.

If you are shipping a vibe coded site with a privacy page you wrote before the site was finished, and you want a second set of eyes on the gap between what it claims and what it actually loads, work with VibeKoded. A privacy claim is a small promise, and small broken promises are the ones that quietly decide whether people trust the rest of your work.

questions that keep coming up

Isn't anonymous analytics fine? Analytics that is anonymous by design is completely fine, and I run some. The problem is never the counting. It is a claim that says no tracking while the script underneath derives an id from who the visitor is. Match the words to the mechanism and the honesty problem disappears, whichever mechanism you keep.

Do I have to rip analytics out to be honest? No. You have two honest options and one dishonest default. You can collect less, or you can claim accurately. The dishonest default is leaving a warm privacy line up while a script quietly does more than it says. Pick one of the two real options deliberately, and write the page to match the one you picked.

It is just a small personal site, does this even matter? The smaller the site, the more likely the privacy copy is boilerplate you never actually read, which means it is more likely to be wrong, not less. A promise you did not mean is still a promise you made. And the fix costs an afternoon once, which is cheaper than being the vibe coder whose own site contradicts them.

// part of the ai websites topic

// grab the free starter kit that makes your AI stop forgetting and stop guessing: get it →

// building with AI? the field manual has the structured lessons.

// hitting this on a real build? this is what I fix →