<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stevan Andric</title>
    <description>The latest articles on DEV Community by Stevan Andric (@stevandric).</description>
    <link>https://dev.to/stevandric</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3889689%2F499b3b3c-d074-4956-9c6e-349799380ef8.jpg</url>
      <title>DEV Community: Stevan Andric</title>
      <link>https://dev.to/stevandric</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stevandric"/>
    <language>en</language>
    <item>
      <title>How to Track Website Visitors Without Cookies in 2026</title>
      <dc:creator>Stevan Andric</dc:creator>
      <pubDate>Thu, 28 May 2026 15:05:17 +0000</pubDate>
      <link>https://dev.to/stevandric/how-to-track-website-visitors-without-cookies-in-2026-3k32</link>
      <guid>https://dev.to/stevandric/how-to-track-website-visitors-without-cookies-in-2026-3k32</guid>
      <description>&lt;p&gt;For most of the web's history, "analytics" meant "cookies." You dropped a script on your site, it set a cookie, and that cookie followed the visitor around so you could tell a returning user from a new one. That model is quietly falling apart, and if you maintain a website in 2026 you've probably already felt it.&lt;/p&gt;

&lt;p&gt;This is a practical look at what cookieless visitor tracking actually involves today — the techniques, what they're good at, and the trade-offs that don't usually make it into the marketing copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cookies stopped working
&lt;/h2&gt;

&lt;p&gt;Three things happened at roughly the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browsers got aggressive.&lt;/strong&gt; Safari's Intelligent Tracking Prevention caps script-set cookies at seven days, often 24 hours. Firefox isolates third-party storage. Third-party cookies are effectively gone across the board. The result: a returning visitor frequently looks brand new because their cookie expired or got partitioned away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Users delete and block.&lt;/strong&gt; Ad blockers and privacy extensions are mainstream now, not a niche concern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consent fatigue is real.&lt;/strong&gt; Even when cookies technically work, you need a banner — and a large share of users dismiss or reject it, so you never get the data anyway.&lt;/p&gt;

&lt;p&gt;The net effect is that cookie-based "unique visitor" counts have drifted from "roughly accurate" toward "roughly fiction."&lt;/p&gt;

&lt;h2&gt;
  
  
  The cookieless options
&lt;/h2&gt;

&lt;p&gt;There is no single drop-in replacement. A few approaches, roughly from least to most precise:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-side / aggregate counting.&lt;/strong&gt; Count requests and hash IP + User-Agent into a daily rotating identifier, then report aggregate numbers. This is what privacy-focused tools like Plausible do. It's genuinely low-risk, and in some jurisdictions it can run without a consent banner. The downside: you lose cross-session identity. A visitor who comes back tomorrow is just a new row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First-party storage tricks.&lt;/strong&gt; localStorage, IndexedDB, ETag caching. These can survive a little longer than cookies in some browsers, but they're subject to the same privacy clampdowns — and the same consent rules. Storage is storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser fingerprinting.&lt;/strong&gt; Instead of storing an ID on the device, you derive one from the device: screen dimensions, installed fonts, canvas and WebGL rendering quirks, the audio stack, timezone, language. Combine enough signals and you get an identifier stable enough to recognize the same browser across sessions — with nothing stored on the device at all.&lt;/p&gt;

&lt;p&gt;Fingerprinting is the only cookieless approach that genuinely recovers cross-session identity. That's why it's having a moment. It's also the option with the biggest asterisk, so let's be honest about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest part: cookieless is not consent-free
&lt;/h2&gt;

&lt;p&gt;It's tempting to read "no cookies" as "no consent banner." It isn't that simple.&lt;/p&gt;

&lt;p&gt;In the EU, the legal trigger isn't the cookie itself — it's accessing or storing information on the user's device. The ePrivacy rules, and regulators including the EDPB and the UK's ICO, have been explicit that fingerprinting falls under the same requirement as cookies. The identifier you derive is also personal data under GDPR. So fingerprinting-based analytics that recognizes returning visitors generally still needs prior consent for EU traffic.&lt;/p&gt;

&lt;p&gt;There is a narrow audience-measurement exemption that some regulators (France's CNIL, the ICO) allow — but it's meant for aggregate, non-cross-site statistics, and a persistent fingerprint identity doesn't fit it cleanly.&lt;/p&gt;

&lt;p&gt;So here's the realistic picture: going cookieless can simplify your stack and survive browser clampdowns, but it does not automatically free you from a consent banner or a privacy policy. Treat any tool that promises otherwise with suspicion. For EU traffic, the right setup is still a banner that gates the script until the user agrees, plus a clear privacy policy describing what you collect.&lt;/p&gt;

&lt;p&gt;What you genuinely &lt;em&gt;do&lt;/em&gt; get from going cookieless: data that doesn't silently degrade as browsers tighten storage, no third-party cookie dependency, and a smaller, simpler client footprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where identity-js fits
&lt;/h2&gt;

&lt;p&gt;identity-js is the tool I've been using for this. It's a fingerprint-based analytics script — one tag, no cookies, no dependencies — with a real-time dashboard. Beyond visitor counts it also does bot detection, rage-click and frustration tracking, SEO auditing, and reading-behavior analysis. That's the kind of data that actually helps you understand a site, not just count heads.&lt;/p&gt;

&lt;p&gt;I like it because the fingerprinting solves the returning-visitor problem that cookie-based tools fumble. I'd still pair it with a consent banner for EU visitors: the tool handles the tracking, but compliance is still on you. Used honestly, it's a solid cookieless option — just don't let "no cookies" lull you into skipping the legal groundwork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Installation is a single script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.identity-js.com/tracker/dist/identity.min.js"&lt;/span&gt; &lt;span class="na"&gt;data-api-key=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop that into your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; and — assuming you've got consent handling sorted — the dashboard starts populating. There's a free tier, so you can try it without committing anything.&lt;/p&gt;

&lt;p&gt;If you'd rather see what the data looks like before installing, there's a live demo: &lt;a href="https://www.identity-js.com/demo" rel="noopener noreferrer"&gt;https://www.identity-js.com/demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cookieless tracking in 2026 isn't a magic "no rules" button. But done with eyes open, it's a more durable foundation than the cookie model it's replacing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>analytics</category>
      <category>privacy</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a Cookie-Free Visitor Analytics Platform — Here's What I Learned</title>
      <dc:creator>Stevan Andric</dc:creator>
      <pubDate>Mon, 20 Apr 2026 21:21:37 +0000</pubDate>
      <link>https://dev.to/stevandric/i-built-a-cookie-free-visitor-analytics-platform-heres-what-i-learned-2pme</link>
      <guid>https://dev.to/stevandric/i-built-a-cookie-free-visitor-analytics-platform-heres-what-i-learned-2pme</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Cookie-Free Visitor Analytics Platform — Here's What I Learned
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built &lt;a href="https://www.identity-js.com" rel="noopener noreferrer"&gt;identity-js&lt;/a&gt;, an open-source visitor intelligence platform that uses browser fingerprinting and behavioral analytics to understand how people actually use your site — no cookies, no consent banners. You can &lt;a href="https://www.identity-js.com/demo" rel="noopener noreferrer"&gt;try the live demo&lt;/a&gt; right now.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every analytics tool I tried fell into one of two camps: either it was a bloated, cookie-dependent behemoth that required consent banners across half the page, or it was a privacy-first counter that told me someone visited but nothing about &lt;em&gt;how&lt;/em&gt; they experienced my site.&lt;/p&gt;

&lt;p&gt;I wanted something in between. I wanted to know: are visitors frustrated? Are they rage-clicking on something that looks like a button but isn't? Are they abandoning my signup form halfway through? Are bots inflating my numbers?&lt;/p&gt;

&lt;p&gt;None of the tools I found answered all of these questions without requiring cookies or a 200KB script.&lt;/p&gt;

&lt;p&gt;So I built one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What identity-js Does
&lt;/h2&gt;

&lt;p&gt;At its core, identity-js is a lightweight tracker (29KB gzipped, zero dependencies) that collects 40+ browser signals and watches for 11 behavioral patterns in real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser fingerprinting&lt;/strong&gt; generates a persistent visitor ID from signals like canvas rendering, WebGL parameters, audio context, installed fonts, speech synthesis voices, and math engine quirks. No cookies needed — the ID survives cookie clears and private browsing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavioral tracking&lt;/strong&gt; is where it gets interesting. The tracker automatically detects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rage clicks&lt;/strong&gt; — rapid frustrated clicking on the same spot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dead clicks&lt;/strong&gt; — clicks on elements that do nothing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phantom clicks&lt;/strong&gt; — clicks on things that &lt;em&gt;look&lt;/em&gt; interactive but aren't&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form abandonment&lt;/strong&gt; — forms started but never submitted, including which field they bailed on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input hesitation&lt;/strong&gt; — how long someone stares at a field before typing (a strong signal of confusion)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading behavior&lt;/strong&gt; — whether someone is actually reading, skimming, or just scrolling past&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error tracking&lt;/strong&gt; — JS exceptions and console errors your visitors hit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text copying&lt;/strong&gt; — when users copy text from your pages (great for knowing what content resonates)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these feed into a &lt;strong&gt;frustration score&lt;/strong&gt; — a weighted composite that tells you at a glance which visitors are having a bad time on your site.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack (Zero Dependencies on the Server Too)
&lt;/h2&gt;

&lt;p&gt;The whole server runs on pure Node.js with zero npm dependencies. I used Node 22's built-in &lt;code&gt;node:sqlite&lt;/code&gt; module for the database, &lt;code&gt;node:crypto&lt;/code&gt; for auth (scrypt + HMAC-SHA256 tokens), and built the HTTP routing from scratch.&lt;/p&gt;

&lt;p&gt;The dashboard is a single HTML file — no React, no build step, no framework. Just vanilla JS with a hand-rolled router and CSS custom properties for theming. It includes an interactive map (Leaflet), real-time live visitor view, per-visitor drill-downs with full session timelines, and PDF report exports.&lt;/p&gt;

&lt;p&gt;The tracker builds to UMD, CJS, and ESM via Webpack, so it works everywhere — script tag, npm import, or require.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;IdentityJS&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@identityjs/tracker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;visitor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;IdentityJS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pk_live_YOUR_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// That's it. Fingerprinting + all behavioral tracking starts automatically.&lt;/span&gt;
&lt;span class="c1"&gt;// Want custom events too?&lt;/span&gt;
&lt;span class="nx"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signup_clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bot Detection Without ML
&lt;/h2&gt;

&lt;p&gt;One thing I'm particularly happy with is the bot detection system. Instead of relying on machine learning or third-party services, it scores visitors 0–100 based on observable signals: missing browser APIs, headless browser flags, impossible screen configurations, zero-entropy fingerprints, and behavioral patterns (or lack thereof).&lt;/p&gt;

&lt;p&gt;A real human browsing your site produces a messy, unique fingerprint with varied interactions. A bot produces clean, predictable signals with mechanical timing. The scoring system catches this reliably, and the dashboard surfaces bot visitors separately so they don't pollute your analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Live Demo
&lt;/h2&gt;

&lt;p&gt;Rather than asking you to sign up to see if this is useful, I built a &lt;a href="https://www.identity-js.com/demo" rel="noopener noreferrer"&gt;live demo&lt;/a&gt; that loads the real dashboard with realistic sample data. You can explore visitor profiles, see the frustration scoring in action, browse session timelines, check out the bot detection — everything the real product does, with no account required.&lt;/p&gt;

&lt;p&gt;The demo includes 14 sample visitors with varied profiles: different browsers, devices, locations, and behaviors. There's a frustrated user with rage clicks and form abandons, a detected bot with suspicious signals, and regular visitors with realistic browsing patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Browser fingerprinting is more stable than I expected.&lt;/strong&gt; The combination of canvas, WebGL, audio context, and font enumeration produces remarkably consistent hashes across sessions. The key is using enough signals that any single one changing doesn't break the whole ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavioral signals are more valuable than pageview counts.&lt;/strong&gt; Knowing that 40% of visitors rage-click your pricing toggle, or that the average hesitation time on your email field is 8 seconds, tells you more than knowing you had 10,000 visits last month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero-dependency servers are liberating.&lt;/strong&gt; Not having node_modules means the entire server deploys in seconds, has zero supply chain risk, and is trivial to audit. Node 22's built-in SQLite is surprisingly capable for a single-server analytics product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-file dashboards aren't as crazy as they sound.&lt;/strong&gt; Yes, the dashboard HTML file is large. But it loads instantly (one request, no waterfall), is trivial to cache, and I never have to debug a webpack config. For an internal tool like this, the tradeoff is worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.identity-js.com/demo" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/strong&gt; — explore the full dashboard with sample data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.identity-js.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/strong&gt; — landing page and signup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/@identityjs/tracker" rel="noopener noreferrer"&gt;npm package&lt;/a&gt;&lt;/strong&gt; — &lt;code&gt;npm install @identityjs/tracker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/anthropics/identity-js" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; — full source code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free tier includes 1,000 visitors and 10,000 events/month. If you're building something and want to understand how your visitors actually experience it, give it a shot.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you have questions or feedback, drop a comment — I'd love to hear what you think.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
