# How we handle visitor data

Tinylytics counts visits without cookies, without fingerprinting, and without keeping a visitor's IP address on the record. We keep what you need in order to read your traffic, and we do not keep a person. This page follows a single page view all the way through so you can check that claim rather than take it.

## The script loads

The embed is a small JavaScript file served from `tinylytics.app`, with Cloudflare in front of it. A visitor to your site receives no Tinylytics cookie of any kind. Whether you still want a banner is your call, but nothing we do requires one.

When the script runs, it sends us:

- the page URL and path
- the referrer, if the browser provided one
- the user agent

The browser also reveals an IP address to our infrastructure, as every HTTP request must. We use it for four things: building a hash, looking up a country, checking what kind of network the request came from, and comparing it with any addresses you have asked us to ignore. The address is held in our job queue only until the next salt rotation, at most 12 hours, and it is never written onto the hit. The list of ignored addresses holds only what you added in your site's settings, and it stays there until you change it. If you use **Add my IP**, your browser asks [ipify](https://www.ipify.org) for your own IPv4 and IPv6 addresses at that moment; your visitors' addresses are never sent to ipify.

## Before anything is stored

Several things get dropped before storage rather than after. Bots, prerender requests, and blank user agents are discarded. Any single source sending more than 25 hits a minute is rate-limited. Recognisable spam is ignored, and repeated bursts from the same hash are suppressed, so a stuck browser tab or an enthusiastic scraper cannot become your traffic. Requests from data-centre networks that we have seen sending automated traffic are dropped as well.

If you have visited your own site with `?tiny_ignore=true`, that browser carries a local storage flag and we never record the request at all. See [ignoring your hits](/docs/analytics/ignore-hits).

## Unique hits, without a person

Total hits count every load. Unique hits try not to count the same browser twice in a day — and we do that without ever storing a visitor ID, because we never create one.

Each request produces a one-way SHA-256 hash of:

1. the visitor's IP address
2. your site's identifier
3. the first 51 characters of the user agent
4. today's date, in UTC
5. a salt that rotates every 12 hours

That is the **visitor hash**. One person reading several pages is one visitor for the day, which is what makes sessions and journeys possible.

The **unique hash** is the same mixture with the path added, and it produces the per-page unique count you see on a path row.

Neither hash can be reversed. The date component changes at midnight UTC, so tomorrow is a new hash for the same person, and the salt changes twice a day, which leaves a very short window in which guessing would even be theoretically useful. Two browsers produce two hashes. A shared office connection can collapse several people into one. That is the trade we have chosen deliberately: approximate unique hits, and no durable record of a reader.

## What a hit looks like

Once the hashes are built, the stored record is roughly this shape:

- the site
- the path and URL
- the referrer, and a UTM-style source when one is present
- the country, as a two-letter code
- a truncated user agent
- the two hashes
- timestamps

No IP address. No name. No cookie. No cross-site identifier. The country came from the IP address, and the address itself is never stored with the hit.

User agents are cleared from hits older than four weeks, because by then they have told you everything they are going to. Application logs are filtered, deleted after 7 days, and do not record client IPs. The proxy in front of the application does write client IPs to its access log, which is rotated by size and holds only a short window of recent requests.

## Country, and only country

Country means country. Not city, not region, not coordinates. The lookup happens, the two-letter code is stored, and the address is gone.

If you send hits through the API with an `ip_address`, we try a local lookup first and only fall back to IPinfo when that cannot resolve. Either way, the address is not stored.

## What you see in the dashboard

Overview, paths, referrers, countries, browsers, and platforms, plus [unique hits](/docs/analytics/unique-hits) if you have enabled them. Sessions and journeys are that day's visitor hash, not a customer you can follow into next week — which is a real limitation, and the correct one for this kind of product.

Optional [Insights](/docs/analytics/insights) send aggregated counts — traffic, paths, referrers — to an AI provider. It is opt-in, it is not used for training, and the payload contains no IP addresses, no hashes, and no user agents.

## Your account

You, being signed in, get one session cookie. That is for you and has nothing to do with your visitors. Export or delete your account whenever you want, without asking us. A deleted account stops collecting straight away, and its data is removed 14 days later unless you restore it first. Accounts that are never confirmed are removed after 7 days.

The application runs in Falkenstein, Germany, on Hetzner — see [hosted in Europe](/docs/trust/hosted-in-europe).

Payments run through Stripe, including Stripe Link, and some longer-standing accounts still go through Paddle or Lemon Squeezy. Application errors go to Sentry with a customer id attached, never a visitor. Uptime checks send your site's URL to Thunder Clap, and nothing about a person.

The [privacy policy](/docs/privacy) has the formal version. If something here is unclear or you need an answer for a client, email hello@tinylytics.app.