Guide
Cookieless web analytics: how lytics counts visitors without cookies
lytics counts visits and visitors without setting a cookie and without storing anything on the visitor's device. This page shows exactly how — the hash, the daily salt, when it is deleted — and what that method gives up.
What a cookie-based tool stores, and what lytics stores
Many analytics tools recognise a visitor by putting a random client id in a cookie and reading it back on every hit. lytics works the other way round: nothing is put on the device, and the server works out who is who from the request itself, for one day at a time.
| Typical client-id cookie | lytics | |
|---|---|---|
| Stored on the visitor’s device | A cookie holding a random client id, set by the tracking script. | Nothing. No cookies, nothing in localStorage or sessionStorage. The browser caches the tracking script itself for up to five minutes, like any script. |
| How a visitor is identified | The client id in the cookie, sent back with every hit. | A hash of the day’s salt, the app, the IP address and the user agent, worked out on the server for each event. |
| How long the identifier lasts | Until the cookie expires or the visitor clears it. | One UTC day. The next day the same browser produces a different hash, and the salt that made it is deleted soon after. |
| Returning visitors on another day | Recognised for as long as the cookie survives. | Not recognised. They are a new visitor each day. |
| Query strings and fragments | Depends on the tool and how it is configured. | Never stored. Only the path of each page is kept. |
| Joining one person across apps | Possible wherever sites share the cookie or link their ids. | Not possible from the data. The app is part of the hash, so one person on two apps has two unrelated hashes. |
How the daily hash works, step by step
- A page on your app sends an event to
/api/collectwithnavigator.sendBeacon, or withfetchandcredentials: 'omit'when a beacon is not available. It carries the site key, the event name, the page URL and the referrer, and, if your app calledidentify, your own id for the signed-in user. - The collector drops the event if the user agent looks like a crawler or headless browser, if the site key is unknown, or if the page’s host is not one of the app’s allowed domains.
- It takes today’s date in UTC and looks up that day’s salt: 32 random bytes, created by the first event of the day and shared by every request that day so they all agree.
- It hashes the salt, the app’s id, the IP address and the user agent with SHA-256 and keeps the first 32 hex characters. That is the visitor.
- It stores the event with that hash, the page’s path, the referring hostname and a device category (mobile, tablet or desktop). The IP address and the user agent are not stored.
- Every hour a job deletes the salts for days before yesterday. Yesterday’s salt is kept only until midnight has passed everywhere a request could be in flight; after that, the hashes from that day cannot be recomputed from an IP address and a browser by anyone, including whoever holds a copy of the database.
day = today in UTC // "2026-11-05"
salt = visitor_salts[day] // 32 random bytes, created by the first event of the day
visitor = sha256(salt + "|" + app_id + "|" + ip + "|" + user_agent)
.hex()
.slice(0, 32) // 32 hex characters, e.g. "3f9c…e07a"
store(app_id, visitor, event_name, path, referrer_host, device) // no IP, no user agent
every hour:
delete from visitor_salts where day < yesterday (UTC)Why the app is part of the hash. Without it, the same person on two apps would have the same hash on the same day, and anyone holding both apps' events could join them into one profile of that person. With it, one person on two apps is two visitors with unrelated hashes, and the two apps' numbers cannot be joined.
Why a salt, and why delete it. IP addresses and browser versions are few enough to guess. A plain hash of them could be reversed by hashing every likely combination. The random salt stops that while it is secret, and deleting it makes the day's hashes permanently unrecomputable.
The trade-offs, stated plainly
Not storing anything on the device has a price. It shows up in the numbers, and you should know it before you read them:
- The same person on two days is two visitors, and over a range Visitors is the sum of each day’s visitors — not the number of different people.
- Someone whose IP address changes during the day — moving from Wi-Fi to mobile data, say — counts again.
- Two people on the same network with the same browser version can count as one.
- A visit is the first event from a visitor in thirty minutes. Because the hash changes at midnight UTC, a visit that runs across midnight counts as two.
- Signed-in users are counted separately: Users is the number of distinct ids your app sends with
identifyorlogin, and each user’s last login and last activity are listed. That id is held in the open page’s memory and is gone after a full reload.
The metric definitions in the docs say the same thing next to each number.
What is never collected
- Query strings and fragments. Only the path of each page is kept. Query strings are where reset tokens, session ids and email addresses end up, so they are dropped before anything is stored.
- Full referrers. The referrer is kept as a hostname and nothing more, and a referrer from the same site is not a referrer.
- Cookies. The tracking script sets none, and the collector does not read any — it runs before the API’s cookie handling.
- IP addresses and user agents. Both go into the hash and are not written to the events table. The user agent is reduced to mobile, tablet or desktop.
- Bot traffic. Events from crawlers, uptime checkers, headless browsers and HTTP libraries are dropped by their user agent. The list is not exhaustive — none is.
What is stored for each event: the app, the time, the event name, the visitor hash, whether it started a visit, the page's path, the referring hostname, the device category, the event's properties and, if your app sent one, your own user id. Raw events are kept for 400 days.
Consent: what this does and does not change
Cookie rules are mostly about storing or reading information on a visitor's device. lytics does neither: the tracking script sets no cookie and writes nothing to the device's storage, and the collector reads no cookie. That part of the rules is not triggered by lytics.
That is not the whole picture. The IP address and the user agent are still sent with each request and processed to make the hash, and your site may set cookies or run other scripts of its own. Whether you need a consent notice depends on where you operate and on everything else your site does. This is not legal advice — check your own obligations, and do not read this page as a promise that no banner is needed.
Try it
Add an app on Your apps and paste its snippet into the <head> of every page:
<script>window.lytics=window.lytics||function(){(lytics.q=lytics.q||[]).push(arguments)};</script>
<script defer src="https://lytics.lp-data.cloud/api/t/lyt_REPLACE_WITH_YOUR_SITE_KEY.js"></script>lyt_REPLACE_WITH_YOUR_SITE_KEY with your app's key, or copy the whole snippet from the app's Install section. The placeholder cannot collect anything.- Not ready to install? Explore a sample dashboard with illustrative data.
- Add analytics to an Astro website — the snippet in a shared layout, up to the first pageview.
- Add analytics to a Next.js App Router app — install once and track client navigation.
Questions
Can lytics count returning visitors?
Not across days. The hash changes every UTC day, so lytics cannot tell a returning visitor from a new one on another day. Within a day, several visits from the same IP address and browser count as one visitor. If your app has accounts, send your own user id with identify or login: Users and each user’s last login and last activity do carry across days.
Does it work when visitors block or clear cookies?
Cookie settings do not change what lytics counts, because it neither sets nor reads a cookie. A blocker that stops the tracking script or the request to /api/collect is a different matter: if the event never arrives, nothing is counted for that page.
Can a visitor hash be traced back to an IP address?
Not once its day’s salt is deleted: without the 32 random bytes, the hash cannot be recomputed from a guess at the IP address and browser. While today’s and yesterday’s salts exist, someone with access to the database and the salts could test guesses against that day’s hashes. That window is why the salts are deleted.
Does this mean I do not need a cookie banner?
Not necessarily, and this page is not legal advice. lytics stores nothing on the visitor’s device and reads nothing from it, so rules about storing or reading information on a device are not triggered by lytics. The IP address and user agent are still processed to make the hash, and your site may do other things that need consent. Check your own obligations where you operate.