Every WordPress analytics plugin says "GDPR compliant" on its page. Most of them still leave a cookie. Some leave nothing in the cookie jar and hide a note in localStorage instead. A few build a fingerprint of your device.
This post explains the one design that really needs no consent banner, and shows you how to test any plugin yourself in one minute.
The cookie is the problem, not the counting
Europe's privacy rule (ePrivacy, Art. 5(3)) is simple: if you write or read something on the visitor's device, you must ask first. Counting pageviews is not the problem. Leaving a note in the browser is.
Three ways to leave a note:
- a cookie (
document.cookie) - other browser storage:
localStorage,sessionStorage, IndexedDB - a fingerprint: nothing is written, but the script reads your screen size, fonts and browser details and mixes them into a secret ID. Privacy authorities treat this as worse than a cookie, because you can't see it or delete it.
A plugin that does none of the three can count visitors without a banner. France's privacy authority (CNIL) already allows this kind of audience measurement without consent, under conditions.
How session-based tracking works
The idea: the visitor's ID lives only in the page's memory, while the tab is open. It is never saved anywhere.
// Simplified. Runs once per page load.
const sessionId = crypto.randomUUID(); // exists only in this variable
function track(event, data = {}) {
navigator.sendBeacon('/wp-json/analytics/v1/event', JSON.stringify({
sid: sessionId,
event,
url: location.pathname,
ref: document.referrer,
...data,
}));
}
track('pageview');
addEventListener('click', e => track('click', { x: e.pageX, y: e.pageY }));
Close the tab, the ID disappears. There is nothing left to ask permission for.
On the server, WordPress writes the data into its own database. Before saving, it cuts the visitor's internet address (IP) short, so nobody can be identified:
// Simplified. IPv4: zero the last number. IPv6: keep the first 48 bits.
function ob_anonymize_ip( string $ip ): string {
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
return preg_replace( '/\.\d+$/', '.0', $ip );
}
$bin = inet_pton( $ip );
return inet_ntop( substr( $bin, 0, 6 ) . str_repeat( "\0", 10 ) );
}
You still know which country the visitor is from. You can't find the person.
What you lose: the plugin can't be sure that today's visitor is the same person as yesterday. It makes a good guess. For traffic, funnels and heatmaps, that's enough. For following one person over months, it isn't, and you shouldn't do that without asking anyway.
What you gain: the 35–45% of European visitors who click "Reject" are now counted. And they're not just anyone: Firefox and Brave users, people with ad blockers, developers. If your visitors are technical, cookie-based analytics is measuring the wrong crowd.
Test any plugin in 60 seconds
Open your site in a private window, press F12, and paste this in the console:
// Run before and after the analytics script loads
console.table({
cookies: document.cookie.split(';').filter(Boolean),
localStorage: Object.keys(localStorage),
sessionStorage: Object.keys(sessionStorage),
});
indexedDB.databases().then(dbs => console.log('IndexedDB:', dbs.map(d => d.name)));
Then open the Network tab and look at what the plugin's script sends out. If you see scrambled navigator or canvas data leaving, that's a fingerprint.
Try it on Google Analytics, Hotjar or Clarity: you'll see _ga, _hjSession*, _clck. Try it on a real cookieless plugin: every list is empty.
Where I land
I built Opti-Behavior) on exactly this model: ID in memory only, no localStorage, no fingerprint, IP cut short before saving, everything stored in your WordPress database with no outside server, a ~15 KB script that never slows the page, robot filtering. Heatmaps and funnels are free. Session recordings (replaying one visitor) are Pro and run on a separate track, because replaying a person does need a "yes", cookies or not.
Full write-up, including what the CNIL says and why fingerprinting is a trap: How to Track WordPress Visitors Without Cookies (GDPR Compliant).
Run the 60-second test on your current setup and post what comes back. I'm collecting examples of "cookieless" plugins that aren't.

Top comments (0)