Notes
September 30, 2026

The path to privacy looks more like a ladder

You're not wrong to think of privacy-first analytics as an oxymoron.

The moment you capture anything about the time, place, or manner in which a link was followed, you are spending down someone’s privacy. The question then becomes how carefully you spend it. The answer for us was very carefully, and the result was Zebra.

Zebra was built in Europe with European values around data protection. So our first goal was to defend the right of users to privacy and anonymity – every feature we built had to flow downstream from that principle.

Our second goal pulled directly against the first: we wanted the live experience to be extraordinary. You can’t overestimate how compelling it is to watch a traffic event develop live on a map or in a chart. It can be deeply motivating and affirming for independent creators. The ability to share a verified replay of that traffic with an existing or potential partner is also powerful, even visceral – enough to swing a decision.

How could we offer content managers these useful, motivating, real-time insights into the shape and location of their audience in the aggregate, while carefully shielding audiences from surveillance or read-receipt-level tracking? Our answer is the privacy ladder, and this is how it works.

We collect almost nothing

No cookies, of any kind. A redirect is just a redirect — an HTTP 302, the same three-line response the web has used since 1996 — and nothing else: nothing is written to the visitor’s device and nothing is read back. There is no consent banner because there is nothing to consent to. The one exception is a scheduled link before it goes live, which serves a page that runs a clock in the browser so the countdown ticks. It sets nothing, stores nothing, and reports nothing back.

No fingerprinting, and nothing that works around a browser’s defences. Everything we know about a device comes from the User-Agent header the browser volunteers with the request, read on our servers. We never run code in the browser to interrogate canvas, fonts, screen geometry, or anything else it did not offer. A hardened browser, a VPN, or a proxy is a preference we respect rather than an obstacle to route around.

We destroy the IP address before anything is written down. It arrives with the request, we read a rough location from it, and then it is gone. The last part is chopped off first, so what remains describes a whole neighbourhood of connections rather than one home. That remainder is then put through a one-way scramble using a secret key that never leaves our servers. Steal the stored data and you get nothing you can turn back into an address. The original never leaves memory and is never written to a log. (For the technically minded: HMAC-SHA256 over a truncated address.)

We would rather lose the data than store it unsafely. That scramble is only worth something because of the secret key behind it. If the key is ever missing, we do not quietly record the clicks a weaker way. We stop recording them at all, and log every one we skipped. Your links keep working the whole time. Only the counting stops.

We count networks, not people. What survives the hash names a network. Several households behind one mobile carrier can arrive as a single identity, and one person moving from home to office arrives as two. The unique-visitor number in your dashboard is a count of distinct networks, and we label it that way.

Detail waits for a crowd

Nothing identifying appears until at least five separate networks share it. Five is the same floor statisticians use when publishing figures that must not identify anybody. The number we actually use can sit above five. It can never sit below.

The real number is a little higher, and you cannot work out what it is. Every value gets its own threshold between five and eight, set by a secret on our servers. It is stable, so nobody can keep refreshing until a low number comes up. It is unguessable, so anyone trying to force a detail into view with fake traffic has no idea how much faking would be enough.

It counts networks, not clicks. One person opening a link fifty times reveals nothing about themselves.

What waits is short and explicit. The city, region, and country a click came from, the site that referred it, the datacenter that served it, which QR code was scanned, and the signal values attached to that code. Full referrer URLs are stored precisely because this gate exists.

Browser, operating system, and device type do not wait. We judged them facts about the route a click took rather than about the person who made it – that a click came from Safari on a phone points at nobody – and we would rather say so plainly than imply a protection we do not offer.

Counts never wait either. You see every click the moment it happens, because a number with no name attached to it describes no one.

Hidden is not the same as unknown. Unknown means we could not work a detail out, and it appears as an ordinary value. Hidden means we know it and are not showing it yet, and it renders as a placeholder of random width, so even its length gives nothing away.

Location climbs the ladder

Location is the one detail with rungs. If a city has quorum you see the city. If it does not, the click climbs: to its region, then to its country, and if none of those qualify it lands in a plainly labelled row carrying its count and nothing else. Nothing is discarded on the way up – the detail waits at the widest level that is still true, and arrives in full the moment the crowd exists.

Everything else that waits is all or nothing. A referrer has no coarser honest form; there is no halfway between naming the site and not naming it. That is why this is a ladder rather than a switch: geography is the one dimension where we can tell you something true without telling you too much.

One gate, not thirty

None of this lives in the interface. A dashboard that receives a city and then hides it has already given the city away, because the browser’s network tab is part of the product surface.

The rule is applied where analytics leave our servers, which is the one point every reader passes through. The server never sends a value it means to hide. It sends what you are allowed and a label saying which: this one is clear, this one folded up to its country, this one hidden. Rendering is the last step, not the mechanism. Internally the rule lives in one module driven by one registry, so retuning the threshold is a single edit that reaches every card, table, map, export, and API response at once.

Live traffic gets the strictest handling, because it leaves before anything has had time to gather a crowd. A click is split into two events that cannot be rejoined: one carries your link and no geography at all, the other carries a location and no link, no click id, and no latency. Only a timestamp is common to both. Coordinates ride only once the city itself has cleared quorum, and the serving datacenter counts as location, because a datacenter pins a metro area. Both events are built by copying an explicit list of permitted fields, never by copying the payload and deleting from it, so a field added in future cannot reach a browser until somebody puts it on the list.

A shared analytics page reads through the same gate, hidden in exactly the same places. The test behind that is blunt: if a detail is not private enough to hand to a stranger with the link, it is not private enough to show anyone.

The assistant cannot leak what it never sees

Dashboards are not the only thing reading Zebra’s analytics. There is a public API, an MCP server, and an assistant that answers questions about your traffic in plain language – and a language model will happily repeat whatever sits in its context.

This is where checking on the way out, rather than on the way in, pays for everything. Those surfaces all read through the same gate, so a model’s context only ever contains data that has already passed the rule. There is no prompt-side redaction to maintain, no instruction list begging the model not to mention cities, and no way to talk it out of a secret. Where the interface shows a placeholder, a machine answer carries a label saying why, so an agent can be accurate about what it does not know: not “the city was Copenhagen,” and not a mumbled guess, but “location detail is withheld until more people have visited.”

Everything downstream, from a breakdown card to a PDF to an AI answer, inherits the rule without knowing it exists. That is what we mean by a ladder you can trust: not that we promised to look away, but that we built the system so there is nothing to look away from.

First foot on the path. Miles to go.