Cookieless Analytics: The Complete Practical Guide
A practical guide to cookieless analytics and click tracking: how it works, what it can measure, the legal questions to review, and a reference implementation.
The phrase "cookieless analytics" has become a marketing term. Every tool now claims to be cookieless. Most of them are not — they have replaced third-party cookies with first-party cookies or local storage and called that "cookieless." A few are genuinely cookieless. This guide explains the difference, why it matters, and what a real cookieless analytics implementation looks like from the inside.
By the end you will understand:
- What makes analytics truly cookieless.
- What cookieless analytics changes about data collection and consent analysis.
- The three main technical approaches, with their trade-offs.
- How server-side click tracking works end to end, and why it is often more accurate than cookie-based alternatives.
- How to implement the simplest approach yourself, or choose a tool that does it right.
On this page
- What cookies actually do in analytics
- The three cookieless approaches
- How tracking works without cookies
- Why cookieless can be more accurate than cookie-based
- The GDPR legal basis
- Implement daily-rotating hash analytics (the DIY path)
- Choose an off-the-shelf tool
- Apply it to different use cases
- Scope: hashed emails, first-party cookies, ad attribution
- What cookieless analytics cannot do
- Related reading
Step 1: Understand what cookies actually do in analytics
Traditional analytics tools use cookies for two purposes:
1. Session stitching. A visitor lands on page A, then navigates to page B, then page C. The cookie ties those three page views together into a single "session." Without a cookie, each request looks like a new anonymous visitor.
2. Return visitor identification. A visitor comes back tomorrow. The cookie persists across the browser close, so the analytics tool recognises them as the same person who visited yesterday.
Both require a persistent browser identifier. Whether that identifier needs consent depends on its purpose, the technology, the site configuration, and the law that applies. Removing analytics cookies reduces data collection, but it does not settle the legal analysis by itself.
Step 2: Understand the three cookieless approaches
There are three main ways to do cookieless analytics. They differ in how they estimate unique visitors and sessions without a persistent browser identifier.
Approach A: Fingerprinting
Browser fingerprinting derives an identifier from a combination of browser characteristics: screen resolution, installed fonts, timezone, canvas rendering, WebGL renderer, language settings, and dozens of other signals. The combination is often unique enough to identify a device across sessions.
Privacy verdict: not cookieless in spirit. Fingerprinting is the approach that regulators and privacy advocates object to most strongly. France's CNIL and Germany's DSK have both issued guidance that fingerprinting is subject to the same consent requirements as cookies because it achieves the same outcome — persistent cross-site tracking — through a different mechanism. Tools claiming "cookieless" that rely on fingerprinting are misleading you.
Approach B: IP-based daily hashing
This approach combines the visitor's IP address with a cryptographic salt that changes daily. The hash is computed server-side and never stored on the client. Because the salt rotates every 24 hours, the same visitor produces a different hash tomorrow — making cross-day re-identification computationally infeasible.
This is the approach used by several privacy-focused analytics products and by 1URL.at's analytics pipeline. 1URL.at computes the identifier in memory, rotates the salt daily, and does not retain the raw IP address or user-agent string.
Privacy characteristics: the visitor's browser receives no analytics identifier and raw IP addresses are not retained. A daily hash is still pseudonymised data rather than automatically anonymous data, so it must be assessed in context.
Approach C: Session-only identification
This approach generates a random session identifier when a visitor first hits the site and discards it when the session ends (browser close or inactivity timeout). No persistent identifier is set. Session-level stitching is possible; cross-session identification is not.
Used by some server-side analytics implementations and tools like GoatCounter. Works well for page view counting and session-level analysis. Does not support "returning visitor" metrics at all, but for many use cases that metric is not meaningful anyway (most of your "returning visitors" count is inflated by your own team).
Privacy verdict: genuinely cookieless. Even simpler than approach B in terms of data minimisation, at the cost of no cross-day visitor estimation.
How tracking works without cookies
The daily-rotating hash approach is worth walking through because its mechanics determine what is collected, retained, and measurable.
When a visitor hits a short link or a page that uses cookieless analytics, several pieces of information arrive in the HTTP request:
- The visitor's IP address.
- The user-agent string (browser and operating system fingerprint).
- HTTP headers like
Accept-LanguageandReferer. - A server timestamp.
Individually, some of these are personal data — an IP address in particular has been treated as personal data by the Court of Justice of the European Union since Breyer v Germany (2016). A cookieless implementation never stores these raw values. It uses them for one operation only — hashing — and the inputs are immediately discarded.
The daily-rotating salt mechanism
- Each UTC day, the server generates a fresh random 32-byte salt and caches it (typically in an edge KV store) with a TTL of about 25 hours. The extra hour prevents a race at the day boundary where the old salt has expired but the new one has not yet been generated.
- When a click or page view arrives, the server computes
SHA-256(salt + ip + user_agent)in memory. - Only the resulting hex digest is written to storage. The raw IP and user-agent never touch the database.
- The next day, the salt rotates. Yesterday's digest is no longer reproducible from today's inputs, which makes cross-day re-identification computationally infeasible.
This is the architecture 1URL.at uses. It reduces stored data, but it does not create a universal compliance guarantee.
What you can measure this way
- Total clicks or page views — each request is counted.
- Unique visitors within a day (approximate) — the hash deduplicates repeat requests from the same visitor inside a 24-hour window.
- Country — derived from the IP at request time (via the edge geolocation header), not the IP itself.
- Device type — derived from the user-agent (mobile, tablet, desktop), then the raw string is discarded.
- Day-over-day trends — the aggregate counts are persisted; the per-request signals are not.
What you cannot measure without adding a persistent identifier
- Cross-day return visitors — by design, the salt rotates.
- Session paths across pages — would require a session token, which is a cookie or equivalent.
- Cross-device attribution — requires a login or an explicit persistent identifier.
For the "how many people clicked this link, from which countries, on which devices, on which days" class of question, those constraints rarely matter. For pure click counting on short links in particular, this approach is arguably the ground truth, for reasons covered in the next section.
Why cookieless can be more accurate than cookie-based
This sounds backwards on first read, but it is well documented by practitioners who have compared both approaches side by side. Cookie-based analytics systematically undercounts in at least four scenarios:
Browser privacy features. Safari's Intelligent Tracking Prevention (ITP) aggressively expires first-party cookies set via JavaScript to seven days (and under some heuristics, one day). Firefox's Enhanced Tracking Protection blocks many tracker-classified analytics scripts outright. A meaningful share of sessions silently fall out of cookie-based dashboards.
Ad blockers and privacy extensions. uBlock Origin, Privacy Badger, and similar tools block common analytics scripts (google-analytics.com, GA4 collect endpoints) at the network level. They typically do not block server-side redirects or first-party event endpoints, so cookieless server-side analytics keep counting when the JavaScript layer never loaded.
Consent-gated analytics. When a site waits for consent before loading analytics, declined or dismissed prompts leave those visits out of the dataset. A server-side cookieless pipeline avoids that client-side dependency, but its lawful basis and consent requirements still need a jurisdiction-specific assessment.
JavaScript failures. Cookie-based analytics depends on a script tag loading and executing. Server-side cookieless tracking fires before any JavaScript runs, so it is immune to slow connections, strict CSP settings, and client-side errors.
For short link click counting specifically, the server sees every HTTP request to the short URL regardless of browser settings, extensions, or consent status. That is as close to a ground-truth click count as you will get.
Step 3: Review the legal basis
GDPR Article 6 lists several possible lawful bases for processing personal data. Some analytics operators rely on legitimate interests under Article 6(1)(f), which requires a documented purpose, necessity assessment, and balancing test. That conclusion is not automatic simply because analytics are cookieless.
The EDPB states that pseudonymised data can remain personal data. CNIL also treats analytics exemptions as conditional and tied to specific technical and operational limits. For 1URL.at, the reliable technical facts are narrower: the analytics pipeline sets no analytics cookies and retains neither raw IP addresses nor user-agent strings.
Consent requirements vary by jurisdiction, site configuration, purpose, and any other technology running on the destination site. Consult qualified counsel for a decision about your deployment.
Step 4: Implement daily-rotating hash analytics (the DIY path)
If you want to build this yourself — for example, you run a Cloudflare Worker, a Fastly Edge function, or a Node.js server and want to add cookieless analytics to your own infrastructure — here is the pattern.
Generate and cache a daily salt
async function getDailySalt(kv: KVNamespace): Promise<string> {
const today = new Date().toISOString().slice(0, 10); // "YYYY-MM-DD"
const key = `analytics:daily-salt:${today}`;
const cached = await kv.get(key);
if (cached) return cached;
// Generate 32 bytes of random data, encode as hex
const saltBytes = crypto.getRandomValues(new Uint8Array(32));
const salt = Array.from(saltBytes).map(b => b.toString(16).padStart(2, '0')).join('');
// Store with 25-hour TTL to ensure today's salt is always available
await kv.put(key, salt, { expirationTtl: 25 * 60 * 60 });
return salt;
}
The 25-hour TTL (rather than exactly 24) prevents a race condition at the UTC day boundary where the old salt has expired but the new one has not yet been generated.
Hash the visitor
async function hashVisitor(salt: string, ip: string, userAgent: string): Promise<string> {
const encoder = new TextEncoder();
const data = encoder.encode(`${salt}:${ip}:${userAgent}`);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
This runs server-side (or at the edge). The ip and userAgent values come from the incoming request headers and are used only for hashing. They are never written to storage. Only the hash is stored.
Record the analytics event
async function recordClick(db: D1Database, event: {
entityType: 'url' | 'link_page' | 'link_item';
entityId: string;
userId: string;
country: string;
hashedVisitor: string;
day: number; // Math.floor(Date.now() / 86400000)
}): Promise<void> {
await db.prepare(`
INSERT INTO clicks_daily (user_id, entity_type, entity_id, day, country, clicks)
VALUES (?, ?, ?, ?, ?, 1)
ON CONFLICT (user_id, entity_type, entity_id, day, country)
DO UPDATE SET clicks = clicks_daily.clicks + 1
`).bind(
event.userId,
event.entityType,
event.entityId,
event.day,
event.country
).run();
}
The ON CONFLICT DO UPDATE pattern is an atomic upsert — it increments the click counter without a separate read-then-write cycle, which prevents race conditions under concurrent traffic.
Query the results
async function getClicksByDay(db: D1Database, entityId: string, daysBack: number) {
const minDay = Math.floor(Date.now() / 86400000) - daysBack;
return db.prepare(`
SELECT day, SUM(clicks) AS total
FROM clicks_daily
WHERE entity_id = ? AND day >= ?
GROUP BY day
ORDER BY day ASC
`).bind(entityId, minDay).all();
}
This query returns one row per day with total click count. Zero-click days are not present in the results — fill them in the application layer if you need a continuous chart.
Step 5: Choose an off-the-shelf cookieless analytics tool
If you do not want to build this yourself, here are the main genuinely cookieless tools at the 24 August 2026 source check:
| Tool | Published approach | Self-host option | What to verify |
|---|---|---|---|
| Plausible | Cookieless aggregate analytics | Yes | Current privacy and data policy |
| Fathom | Cookieless aggregate analytics | No | Current privacy and data policy |
| GoatCounter | Lightweight aggregate analytics | Yes | Deployment configuration |
| 1URL.at | Daily rotating visitor hash | No | Documented storage boundaries |
| Umami | Deployment-dependent | Yes | Cookie and collection settings |
Provider behavior and terms change. Check each provider's current technical and legal documentation before choosing one.
Step 6: Apply cookieless analytics to different use cases
Blog or content site
Install Plausible or Fathom. Point the domain. You get page view counts, referrer data, UTM attribution, country breakdown, and device split — consent requirements depend on the site, other technologies, and jurisdiction. Complement it with short links from 1URL.at for any off-site links you want to track independently.
Link-in-bio or micro-landing page
Use 1URL.at's link pages, which have cookieless analytics built in. Every page view and every item click is recorded using the daily-rotating hash approach. You get item-level click tracking — which button on your link page got clicked — without any setup. See the link-in-bio builder.
URL shortener
1URL.at's URL analytics use the same pipeline. Every redirect records a click event. Country is available in the dashboard; device reports are on the roadmap. Read the 60-second setup guide.
Marketing attribution
For multi-channel campaign attribution, combine short links (one per campaign channel) with UTM parameters on the destination URL. See the UTM tracking guide for the full pattern.
Scope: hashed emails, first-party cookies, ad attribution
A quick note on what this guide is not about. Hashed emails (passing a hashed email address to an ad platform so it can be matched against a user graph) and first-party cookies set by your own domain are both evolving techniques in the identity-resolution and ad-attribution space. They are different from the server-side cookieless click counting described here, and they come with their own legal considerations.
If your question is "did the person who clicked my ad eventually buy something," you are in advertising attribution territory, which is outside this guide's scope. This guide is about understanding click volume and geographic distribution without retaining raw IP addresses or user-agent strings. For a closer look at cookies, DPAs, third-party pixels, and provider questions, see privacy-focused URL shorteners: what to look for.
What cookieless analytics cannot do
It is worth being honest about the trade-offs:
No cross-session user journeys. Because there is no persistent identifier, you cannot see that visitor X visited your site on Monday, came back on Thursday, and converted on Friday. You see three separate sessions.
No funnel analysis across multiple days. Multi-day conversion funnels require some form of persistent identifier. If that matters for your business, you need either cookies (with consent) or a login system where the user's account ID serves as the persistent identifier.
Unique visitor counts are estimates. The daily-rotating hash means "unique visitors today" is a reasonable approximation. "Unique visitors this month" is less accurate — the same person will produce a different hash each day, so the monthly unique count will be inflated by return visitors. Most tools display this as "estimated unique visitors" and document the limitation.
Referrer data is partial. Same-site navigation does not pass referrer headers. HTTPS-to-HTTP navigation strips the referrer. Some privacy-focused browsers suppress the referrer entirely. Referrer-based attribution should be treated as directional, not forensically accurate.
For the use cases that most small teams and creators care about — "how many people clicked this?", "where are they coming from?", "which channel performed?" — cookieless analytics answers those questions accurately enough. For enterprise-grade funnel analysis and cross-day user journeys, you need a different architecture.
Summary
Cookieless analytics is genuinely viable for the majority of analytics use cases. The key points:
- True cookieless analytics uses daily-rotating IP hashing, not fingerprinting.
- Cookieless does not decide the legal basis; consent requirements depend on the site, purpose, technology, and jurisdiction.
- You can build it yourself with a handful of crypto functions and a SQL upsert pattern.
- Off-the-shelf options include Plausible, Fathom, GoatCounter, and 1URL.at's built-in analytics.
- The trade-off is no cross-session user journeys or exact unique visitor counts.
If you want to go deeper on the technical implementation, read how we built 1URL.at on Cloudflare Workers — the analytics pipeline architecture is covered in detail there.
Related reading
Two companion guides dig into specific parts of the cookieless picture:
- How to set up UTM tracking without Google Analytics. Cookieless click counting answers "how many and from where." UTM parameters answer "which campaign sent this visit." They are complementary, and this guide walks through three practical stacks for attributing campaign traffic without touching GA4 — including how to layer per-channel short links on top of UTM parameters so you get attribution even when the destination page has no analytics of its own.
- Privacy-focused URL shorteners: what to look for. The legal and compliance counterpart to the technical architecture above. It covers cookies, third-party pixels, IP handling, DPA availability, and the questions to ask before choosing a provider.