lytics

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.

Checked against the lytics source as of 2026-11-05: the visitor hash, the collector, the tracking script and the job that deletes salts. It describes lytics only; it is not a review of other tools.

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 cookielytics
Stored on the visitor’s deviceA 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 identifiedThe 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 lastsUntil 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 dayRecognised for as long as the cookie survives.Not recognised. They are a new visitor each day.
Query strings and fragmentsDepends on the tool and how it is configured.Never stored. Only the path of each page is kept.
Joining one person across appsPossible 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

  1. A page on your app sends an event to /api/collect with navigator.sendBeacon, or with fetch and credentials: '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 called identify, your own id for the signed-in user.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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 metric definitions in the docs say the same thing next to each number.

What is never collected

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.

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>
Replace 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.

Create an account

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.

Count visitors without cookies