Contents (21 sections)
- 1. The banner is the penalty for a technical choice
- 2. A five-question self-audit
- 3. Four technical choices that remove the need for a banner
- Replacing Google Fonts with local fonts
- Hardening HTTP headers to block parasitic tracking
- 4. The “one-click” banner is not compliant
- 5. “But how do I know how many visitors I have?”
- 6. Self-hosted Matomo, the only set-up I recommend
- Docker Compose for Matomo + MariaDB
- 7. The GDPR setting that removes the banner, step by step
- Anonymisation and retention settings in config.ini.php
- Site-side tracker (with a noscript fallback)
- 8. Matomo / Plausible / Umami / GoatCounter compared
- Matomo (the most complete)
- Plausible (the simplest)
- Umami (the balance)
- GoatCounter (the no-frills option)
- 9. What the GDPR still asks of you
- 10. What not tracking really costs
- Conclusion
- Sources and references
When you visit a French website in 2026, you are greeted by a pop-up. Three columns, pre-ticked boxes, an “Accept all” button given pride of place and a “Customise” link tucked away at the bottom in light grey. It has become so commonplace that people accept it mechanically, which is exactly the point. But this friction is not a legal obligation, it is the direct result of a technical choice: setting trackers.
On the websites I build for my clients, I do not use one. Not out of regulatory laziness, not out of carelessness: quite the opposite, out of maximum compliance. Here is the legal reasoning, the five-question self-audit to check your own site, and the complete stack that lets you stay strictly GDPR compliant without ever bothering visitors with a consent request.
1. The banner is the penalty for a technical choice #
Article 82 of the French Data Protection Act (loi Informatique et Libertés), which transposes the ePrivacy Directive 2002/58/EC, says two simple things: (1) any storage or reading of information on the user's device (cookie, localStorage, fingerprint) requires prior, free and informed consent; (2) unless there is an explicit exception: cookies strictly necessary for the service to work, and audience measurement exempted by the CNIL, the French data protection authority.
The mechanical conclusion: if you set no cookie that requires consent, you have nothing to ask for. No banner, no debate over the wording of “reject all”, no Cookiebot billed at €9 a month. Compliance is achieved upstream, in the code, not as a layer added on top in a widget.

2. A five-question self-audit #
Before rewriting anything, here is the one-minute audit grid that tells you exactly what justifies your current banner, and what can be removed without breaking anything.
- Open the browser DevTools on your home page → Application tab → Cookies. How many are there before any click on the banner? If the answer is “more than 0”, Article 82 applies.
- Network tab: how many requests go out to third-party domains (google-analytics.com, googletagmanager.com, fonts.googleapis.com, facebook.net, doubleclick.net, hotjar.com)? Each one is a tracker supplier to remove or justify.
- On your contact page: do you use Google reCAPTCHA? Cloudflare Turnstile in managed mode without cookies? hCaptcha? Cloudflare and hCaptcha without cookies are exempt. reCAPTCHA is not.
- Fonts: are they served from fonts.googleapis.com (Google receives every visitor's IP address, CJEU penalty in 2022) or self-hosted from your own domain?
- Embedded maps and videos: standard Google Maps and classic YouTube set cookies as soon as the page loads (even before a click). In the nocookie embed version with lazy-loading on click, they are exempt.
On 90% of small business and SME websites audited in 2026, the three real culprits are Google Analytics, Google Fonts served externally, and a third-party chat widget (Tawk.to, Crisp in its default configuration). Remove or replace them and no banner is required.
3. Four technical choices that remove the need for a banner #
On a brochure website or a light e-commerce site for a small business or SME, you can reach zero cookies requiring consent with four key decisions:
- No Google Analytics, no GTM, no Meta Pixel, no TikTok Pixel, no LinkedIn Insight, no Hotjar. All these tools set profiling cookies that require consent, full stop.
- No Google Fonts served by fonts.googleapis.com (which leaks the visitor's IP address to Google, a practice condemned by a German court in 2022): the fonts are downloaded at build time and served from the site's own domain. Next.js does this natively with
next/font. - No Google Maps in an iframe or in a script loaded on the home page: replace it with OpenRouteService or MapLibre plus MapTiler or IGN tiles if a map is really needed.
- No standard YouTube embeds (which set cookies as soon as the visitor lands on the page): use
youtube-nocookie.comwith lazy-loading on click, or switch to a self-hosted video with thenext/videocomponent.
Replacing Google Fonts with local fonts #
The next/font API downloads Google fonts at build time, optimises them, serves them from your own domain and generates the @font-face CSS automatically. No request to fonts.googleapis.com at runtime.
// app/layout.tsx - self-hosted fonts via next/font
import { Inter } from "next/font/google";
// Next.js downloads the fonts at build time and serves them from your domain
const inter = Inter({
subsets: ["latin"],
display: "swap",
variable: "--font-inter",
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="fr" className={inter.variable}>
<body>{children}</body>
</html>
);
}Hardening HTTP headers to block parasitic tracking #
Even without deliberately adding a tracker, some browser extensions or third-party libraries may try to activate modern advertising APIs (Chrome's Topics API, attribution-reporting). An explicit Permissions-Policy disables them, and a strict Content-Security-Policy forbids loading external scripts that are not listed.
// next.config.ts - HTTP hardening headers against tracking
async headers() {
return [
{
source: "/(.*)",
headers: [
// Blocks Topics API, FLoC, attribution-reporting, advertising FedCM
{
key: "Permissions-Policy",
value: "browsing-topics=(), interest-cohort=(), join-ad-interest-group=(), attribution-reporting=()",
},
// Strict CSP: only scripts from the domain are allowed
{
key: "Content-Security-Policy",
value: "default-src 'self'; script-src 'self'; img-src 'self' data:; connect-src 'self' https://stats.client.fr; font-src 'self'",
},
],
},
];
}At this point, there may still be one strictly necessary technical cookie: the Cloudflare Turnstile cookie for the duration of an anti-spam challenge, or a session cookie if you really need e-commerce baskets. These cookies are exempt from consent according to the CNIL (decision 2020-091). No banner required.
4. The “one-click” banner is not compliant #
A very widespread variant: the pop-up with a single “OK” or “Accept” box, with no visible “Reject” button at the same level. This has been legally non-compliant since CNIL decision no. 2020-091, as confirmed by the high-profile fines of 2022-2025.
- Google LLC + Google Ireland: €150m CNIL fine (December 2021), upheld in 2022. Grounds: refusing was less accessible than accepting on google.fr and youtube.com.
- Meta Platforms Ireland: €60m CNIL fine (January 2022). Same grounds on facebook.com.
- Microsoft Ireland: €60m CNIL fine (December 2022). Grounds: no “reject” button on bing.com.
- Criteo SA: €40m CNIL fine (June 2023). Grounds: invalid consent for retargeting.
The CNIL rule has become crystal clear: if you ask for consent, the “Reject all” button must be presented with the same level of accessibility, in the same typeface and with the same colour weight as “Accept all”. Any dark pattern that makes refusing harder exposes you to a penalty. One more reason not to need the banner at all: being compliant costs less than becoming compliant.
5. “But how do I know how many visitors I have?” #
That is the real question. For 70% of the small businesses I come across, the honest answer is: “you do not need to know it to the nearest visitor”. You already know how many leads come through the contact form (e-mail). You can see your Search Console positions. You have your sales figures. The vanity metric “1,247 unique visitors this week” changes nothing for your business, especially if half of them are bots.
For the remaining 30% (e-commerce sites, sites with a conversion funnel to optimise, editorial sites that track their best-performing articles), we install self-hosted Matomo. And we configure it so that it stays exempt from the banner.
6. Self-hosted Matomo, the only set-up I recommend #
Matomo is the open source alternative to Google Analytics, under the GPLv3 licence. Two versions exist side by side: Matomo Cloud (SaaS, hosted by Matomo) and self-hosted Matomo (you install it on your own server). Only the second allows maximum compliance and full sovereignty over the data: that is what I install for my clients.

Docker Compose for Matomo + MariaDB #
The typical deployment fits in a single docker-compose.yml file on the same VPS as the website, behind a stats.client.fr subdomain with a Let's Encrypt TLS certificate.
# docker-compose.yml - minimal self-hosted Matomo
services:
matomo-db:
image: mariadb:11
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: ${DB_PASSWORD}
volumes:
- ./data/db:/var/lib/mysql
networks: [matomo]
matomo:
image: matomo:5-apache
restart: unless-stopped
environment:
MATOMO_DATABASE_HOST: matomo-db
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: ${DB_PASSWORD}
MATOMO_DATABASE_DBNAME: matomo
volumes:
- ./data/matomo:/var/www/html
ports:
- "127.0.0.1:8080:80"
depends_on: [matomo-db]
networks: [matomo]
networks:
matomo:Automatic encrypted backups via PBS or borgbackup to a second site, monthly updates via docker compose pull && docker compose up -d. Marginal hosting cost: a few euros a month on a VPS that already hosts other things.
7. The GDPR setting that removes the banner, step by step #
To stay within the CNIL exemption for “strictly necessary audience measurement” (decision 2020-091), Matomo must be configured according to five strict rules. Most of them can be enabled in config/config.ini.php.
- IP anonymisation: truncate the last 2 bytes (IPv4) or the last 80 bits (IPv6) before any processing.
- Cookieless mode: disable the creation of tracking cookies. Matomo rebuilds the session through a server-side fingerprint based on the anonymised IP + User-Agent.
- Limit the retention of detailed data to 13 months maximum, with aggregation beyond that.
- Disable User ID, cross-site tracking and enrichment by third parties (geo, social media).
- No export to BigQuery, Google Ads or Meta Ads. If you want advertising retargeting, it requires consent and therefore a banner: you have left the exemption.
Anonymisation and retention settings in config.ini.php #
; /var/www/html/config/config.ini.php
[General]
; Truncate the last 2 IP bytes before any processing
anonymize_ip_mask_length = 2
anonymize_ip_mask_length_ipv6 = 80
[Tracker]
; Cookieless mode: no tracking cookies
ignore_visits_cookie = 1
enable_fingerprinting_across_websites = 0
[Deletelogs]
; 13-month retention (395 days), automatic purge afterwards
delete_logs_enable = 1
delete_logs_schedule_lowest_interval = 7
delete_logs_older_than = 395Site-side tracker (with a noscript fallback) #
The snippet to insert in the <head> or the main layout. The disableCookies directive is essential: it is what prevents the _pk_id cookie from being set on the visitor's device.
<!-- Matomo tracker, cookieless mode with noscript fallback -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']); // No cookie set
_paq.push(['setDoNotTrack', true]); // Respect the DNT header
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u = "https://stats.client.fr/";
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '1']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true; g.src = u + 'matomo.js';
s.parentNode.insertBefore(g, s);
})();
</script>
<noscript>
<img referrerpolicy="no-referrer-when-downgrade"
src="https://stats.client.fr/matomo.php?idsite=1&rec=1"
style="border:0" alt="">
</noscript>Once configured this way, Matomo falls fully within the CNIL exemption. You measure page views, sessions, traffic sources, user journeys and conversions, all with no banner, no tracking cookie and no transfer to a third party.
8. Matomo / Plausible / Umami / GoatCounter compared #
Four tools dominate the market for “compliant cookieless” analytics. The choice depends on the trade-off between functional richness, front-end performance and hosting complexity.
Matomo (the most complete) #
- Model: self-hosted (free, GPLv3) or paid Cloud SaaS.
- Stack: PHP + MariaDB / PostgreSQL. Official Docker container.
- Tracker weight: ~28 KB gzipped. Heavier than the alternatives.
- Features: heatmaps, A/B testing, funnels, e-commerce, media, customer journey, A/B tests, a full Google Analytics level.
- CNIL exemption: yes, after configuration (anonymisation + cookieless + 13-month retention).
- Ideal for: e-commerce sites, editorial sites that need funnels and cohorts.
Plausible (the simplest) #
- Model: paid Cloud SaaS (~€9/month) hosted in Germany (Hetzner Helsinki), or free self-hosted (CE).
- Stack: Elixir + PostgreSQL + ClickHouse. Official Docker image.
- Tracker weight: < 1 KB gzipped. Unbeatable for Lighthouse.
- Features: pages, sources, devices, countries, goals, but no advanced funnels and no heatmaps.
- CNIL exemption: yes, natively (cookieless by design).
- Ideal for: brochure websites, blogs, SaaS, when you just want to know what works.
Umami (the balance) #
- Model: free self-hosted (MIT) or paid Cloud.
- Stack: Next.js + PostgreSQL / MySQL. Very well integrated with the Vercel ecosystem.
- Tracker weight: ~2 KB gzipped.
- Features: equivalent to Plausible with a more modern UI, native multi-site support.
- CNIL exemption: yes, natively (cookieless).
- Ideal for: JS developers who want a light, self-hosted set-up without managing PHP.
GoatCounter (the no-frills option) #
- Model: free SaaS for small sites (< 100k page views/month) hosted by the author, or free self-hosted.
- Stack: monolithic Go with a SQLite or PostgreSQL database.
- Tracker weight: ~3 KB gzipped.
- Features: basic statistics only. No funnel, no e-commerce.
- CNIL exemption: yes, natively (cookieless, no fingerprinting).
- Ideal for: personal blogs, association websites, open source projects that want an honest counter.
Selection criterion in two questions: do you need funnels, heatmaps or advanced e-commerce? → Matomo. Otherwise → Plausible or Umami. Self-hosted whenever possible, European SaaS otherwise. Never Google Analytics.
9. What the GDPR still asks of you #
Removing the banner does not exempt you from the remaining GDPR obligations. Whatever happens, you must keep three things visible on your website.
- A privacy policy accessible from every page (GDPR Art. 13): it details the data collected, however minimal (server logs, contact form, exempted audience measurement).
- A compliant legal notice (LCEN, the French e-commerce law, Art. 6): identity of the publisher, the host and the publication director.
- Respect for the right to object (GDPR Art. 21): even if you measure your audience without consent, a visitor can ask to be excluded. Matomo and Plausible offer a one-line opt-out.
For the contact form, the GDPR requires a notice on what happens to the data (retention period, purpose, legal basis: legitimate interest or explicit consent). One sentence is enough, but it has to be there.
10. What not tracking really costs #
On a site with no banner and no tracker, you save: the Cookiebot or Axeptio licence (€200 to €600 a year), the time spent debugging consent variations between Chrome, Safari and Firefox, and the conversions lost to visitors who click “reject” and never come back. You gain: a Lighthouse score of 95+ without effort, a privacy policy that fits on one page, and visitors who do not take you for an advertising agency.
The cost of adding self-hosted Matomo: ~30 minutes of provisioning on existing infrastructure (the docker-compose.yml above deployed on a VPS), plus monthly maintenance (security updates). On the sites I manage, it is included in the managed hosting service. For a client who hosts elsewhere, I bill it separately.
Conclusion #
A cookie banner is not an obligation: it is the result of a tracking choice. If you remove the trackers, you remove the banner. And if you really need to measure, a well-configured self-hosted Matomo (IP anonymisation, cookieless, 13-month retention) covers 95% of cases, while staying strictly compliant with CNIL doctrine and the GDPR, without ever disturbing a visitor or risking a fine.
If you want to audit your current site to find out what justifies your banner and see what can be removed without harming SEO or conversions, that is usually the first step of a compliance service: allow two to four hours for the full pass, with actionable recommendations at the end.
Sources and references #
The legal and technical references in this article are based on CNIL doctrine, the official texts on Légifrance and EUR-Lex, and the documentation of the tools mentioned, up to date as of May 2026.
- CNIL, Decision no. 2020-091 of 17 September 2020 (guidelines on cookies and trackers, in French): https://www.cnil.fr/fr/cookies-et-autres-traceurs-la-cnil-publie-des-lignes-directrices-modificatives-et-sa-recommandation
- CNIL, Decision no. 2020-092 of 17 September 2020 (recommendations on banners, in French): https://www.cnil.fr/fr/cookies-et-autres-traceurs-la-cnil-publie-des-lignes-directrices-modificatives-et-sa-recommandation
- Légifrance, Article 82 of Law no. 78-17 (French Data Protection Act, in French): https://www.legifrance.gouv.fr/loda/article_lc/LEGIARTI000037813978
- EUR-Lex, ePrivacy Directive 2002/58/EC: https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:32002L0058
- EUR-Lex, Regulation (EU) 2016/679, GDPR (Article 13, information): https://eur-lex.europa.eu/eli/reg/2016/679/oj
- CNIL, Cookies and trackers: what does the law say? (in French): https://www.cnil.fr/fr/cookies-et-traceurs-que-dit-la-loi
- CNIL, Audience measurement exempt from consent (in French): https://www.cnil.fr/fr/la-mesure-daudience-exemptee-de-consentement
- CNIL, €150m fine for Google LLC + €90m for Google Ireland (in French): https://www.cnil.fr/fr/cookies-sanction-de-150-millions-deuros-lencontre-de-google-llc-et-90-millions-deuros-lencontre-de
- CNIL, €60m fine for Meta Platforms Ireland (Facebook) (in French): https://www.cnil.fr/fr/cookies-sanction-de-60-millions-deuros-lencontre-de-facebook-ireland-limited
- CNIL, €60m fine for Microsoft Ireland (Bing) (in French): https://www.cnil.fr/fr/cookies-sanction-de-60-millions-deuros-lencontre-de-microsoft-ireland-operations-limited
- CNIL, €40m fine for Criteo (in French): https://www.cnil.fr/fr/sanction-de-40-millions-deuros-lencontre-de-la-societe-criteo
- CJEU, Google Fonts decision (LG München, January 2022): https://noyb.eu/en/google-fonts-german-court-confirms-100-fine
- Matomo, official documentation (anonymisation, GDPR): https://matomo.org/faq/general/faq_146/
- Matomo, Privacy Compliance Tools: https://matomo.org/privacy/
- Plausible Analytics, official documentation: https://plausible.io/docs
- Umami, official documentation: https://umami.is/docs
- GoatCounter, official website: https://www.goatcounter.com/
- Next.js, next/font (self-hosting Google fonts): https://nextjs.org/docs/app/api-reference/components/font
- MDN, Permissions-Policy HTTP header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy
- MDN, Content-Security-Policy HTTP header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy




