Storage and counting
One key-value namespace and four kinds of key. Knowing the shape is useful when reading the report page or working out why a number looks wrong.
What is written
<slug>clicks:*meta:*rate:*The clicks:, meta: and rate: families are filtered out of /api/links, /api/stats, /api/export and the sweeper. Only real links appear anywhere a human reads, which is why the listing endpoints return a bare array of links and nothing else.
Two things about the TTL worth knowing
- Writing a key without a TTL makes it permanent. That is the single easiest way to turn a seven-day link into a forever link by accident, so every write path here sets one deliberately rather than by default.
- The store refuses a TTL below sixty seconds. Anything shorter is rounded up, which matters if you are experimenting with short-lived links.
What a click records
A visit is recorded just before the redirect is sent, and only for a link that resolves.
- A protected link records nothing until the password has been accepted. Attempts at the gate are not counted, so the count is of people who got through, not people who arrived.
- The referrer is the
Refererheader as sent. Plenty of clients do not send one, so a link shared in an app often shows no referrer rather than the app's name. - Device and country come from Cloudflare's request headers. They are a classification, not an identification.
- Repeat clicks from the same browser all count. There is no de-duplication and no notion of a unique visitor.
Why the numbers agree
Every figure that depends on a link's age — days remaining, whether it is expired — is computed on the server from when it expires. Nothing is counted down in the browser.
The only arithmetic done client-side is on the rows in your own links table, and those are yours alone, in your browser, from what the server returned. Two people looking at the service-wide numbers cannot see different answers; two people looking at their own list might, if one of them is looking at a stale copy.