# Does Matomo need a consent banner? Cookieless tracking, fingerprinting, and making 'Refuse' actually work

> Matomo's cookieless config_id isn't a classic fingerprint, ePrivacy and GDPR are two separate questions, and the reason 'Refuse' doesn't stop your tracking is almost always a double-injected tracker. Here's the config behind all three. Not legal advice, just the mechanics.

Published: 2026-07-29
Categories: Matomo Tracking
Canonical: https://martez.io/blog/matomo-consent-cookieless-tracking

---

Two questions come up constantly in the Matomo forums, and they turn out to be the same question wearing different clothes. Does Matomo's cookieless tracking, the `config_id` that people keep calling a "fingerprint," need consent at all? And once you bolt a consent manager like tarteaucitron onto the site, why does Matomo keep recording visits from people who clicked Refuse?

The part that matters before anything else: this is configuration guidance, not legal advice. Whether you need a banner depends on your jurisdiction, the data you collect, and how your install is configured, and that call belongs to your DPO or legal counsel, not a blog post and not Matomo's defaults. What we can do is explain how Matomo's consent model works and how to wire the config so it matches whatever decision they hand you. Everything below is Matomo 5.x.

<Callout type="tip" title="TL;DR">

Cookieless Matomo drops the consent banner only where your jurisdiction grants a narrow analytics exemption and you meet every condition; France, via the CNIL, is the clearest case. Everywhere else, gate Matomo behind consent. If people who clicked Refuse still show up in your reports, the cause is almost always two trackers loading at once: one auto-injected by your CMS or plugin, one by your consent manager. Disable the auto-injected copy so your consent manager is the only thing loading Matomo.

</Callout>

## What Matomo actually collects (and why the config_id isn't a classic fingerprint)

Start here, because the legal question is downstream of the technical one. Out of the box, Matomo tracks immediately. Consent is something you opt into. It's not the default state, and if you do nothing the tracker fires.

When cookies are disabled, Matomo stops storing an identifier on the device and derives a server-side `config_id` for each visit instead. The `config_id` is a hash of a limited set of attributes (browser, operating system, plugins, IP address, language) mixed with a random salt that rotates every 24 hours and is then deleted. The IP goes in after your anonymisation setting is applied, which by default masks it; an install configured to skip IP anonymisation feeds the full address into the hash, so confirm that setting is on. Three things fall out of the design:

- The same visitor gets a completely different `config_id` the next day, so no person or device can be recognised across days. The salt that would let you reconnect them is already gone.
- The hash is scoped per website ID, so the same visitor browsing two of your sites gets two unrelated values.
- With no cookie, the default look-back window for stitching actions into one visit is only about 30 minutes.

That's the real difference between this and the kind of fingerprinting regulators worry about. A classic fingerprint is built to be stable, to recognise you next week. Matomo's is built to forget. It's a session-grouping hash with a 24-hour shelf life, not a persistent identifier. (Matomo documents this in its [config_id FAQ](https://matomo.org/faq/general/how-is-the-visitor-config_id-processed/), worth a read if you ever need to defend the choice internally.)

## ePrivacy and GDPR are two different questions

Most of the confusion in those forum threads comes from collapsing two legal layers into one. They're separate, and clearing one does not clear the other:

- ePrivacy (Article 5(3), as transposed into your national law) governs access to the device: reading or writing information on the user's terminal. That's the "do you need a cookie banner" question.
- GDPR governs what you do with the data once you have it: your lawful basis, retention, the rights you owe the visitor.

Cookieless Matomo removes the cookie-storage trigger, but it doesn't automatically put you outside ePrivacy. In most European countries the rules can still reach client-side analytics even when no cookie is written; a few jurisdictions, France among them, recognise a narrow exemption for audience measurement if you meet every condition. So going cookieless drops the banner question in some places and not others, and either way you still carry GDPR obligations on the data you collect. The reverse also happens: you can be fully GDPR-documented and still owe a banner because you're setting a cookie. Don't treat them as one switch.

## Route A: configure for exemption (no banner)

In France, the CNIL lists Matomo among the audience-measurement tools that can be exempt from prior consent when you configure it to their guidance. Broadly, exemption asks you to:

- Anonymise IP addresses (mask at least the last two bytes).
- Not cross-reference the data with other processing or share it with third parties.
- Disable cross-visit profiling (visitor profiles, Heatmaps & Session Recording) and avoid User ID and personal data.
- Cap the cookie lifespan (CNIL: 13 months maximum) and data retention (25 months maximum).
- Offer a visible opt-out and still inform visitors through your privacy policy.

As of Matomo 5.9.0 (and on Matomo Cloud), you don't have to hand-check those any more. Administration → Privacy → Compliance runs your config against the CNIL requirements per site and flags each setting as compliant, non-compliant, or unknown. Tick "enforce compliance where possible" and it applies the supported ones in one go: the two-byte IP mask, disabling visitor profiles and heatmaps, stripping campaign parameters, and dropping data retention to 180 days. It won't set up your opt-out or make the legal call for you, but it clears most of the manual fiddling.

<Callout type="tip" title="Before you tick 'enforce compliance'">
Run the assessment first and read what it will change. Enforcing CNIL mode does more than mask IPs: depending on your setup it can switch off the Visits Log, real-time reports, raw-data exports, User ID, cross-domain tracking and ad-conversion exports, and restrict Ecommerce. Enabling it also permanently deletes any A/B Testing experiments. On a live shop or experimentation setup, confirm those losses are acceptable before you enforce, not after.
</Callout>

Two cautions on the route itself. This is a France-specific interpretation of how French law transposes ePrivacy, and another DPA may take a stricter line. And "exempt" means exempt from the prior-consent banner; it does not remove your transparency and opt-out duties. Decide with legal before you lean on it.

## Route B: gate Matomo behind consent

If you (or your regulator) want prior consent, you wire Matomo to wait for it. Matomo gives you two distinct modes, and picking the wrong one (or mixing the two APIs in one callback) is behind a lot of "this isn't behaving how I expected" threads. The difference is what each one gates:

| | `requireConsent` (strict) | `requireCookieConsent` (cookie-only) |
|---|---|---|
| Tracking request before consent | none | fires, cookieless |
| `_pk_*` cookies before consent | none | none |
| What it holds back | the whole tracking request | only the persistent cookies |
| Grant on Accept | `rememberConsentGiven` | `rememberCookieConsentGiven` |
| Revoke on Refuse | `forgetConsentGiven` | `forgetCookieConsentGiven` |
| Use it when | tracking itself needs a lawful basis | cookieless-by-default, only the cookie needs opt-in |

The two APIs are parallel but separate: the consent calls govern whether anything is sent at all, the cookie-consent calls govern only the `_pk_*` cookies. Keep a callback to one column and don't reach across.

### Strict: nothing fires until consent

```js
var _paq = window._paq = window._paq || [];

// No request and no cookie until the visitor consents.
_paq.push(['requireConsent']);
_paq.push(['trackPageView']);
```

Grant and revoke from your banner's callbacks:

```js
// On Accept
_paq.push(['rememberConsentGiven', 720]); // persist ~30 days; omit the number to remember until cleared

// On Refuse, or a later withdrawal
_paq.push(['forgetConsentGiven']);
_paq.push(['deleteCookies']);             // clears any _pk_* cookies left from a previous Accept
```

### Hybrid: measure cookielessly first, cookies only after consent

This is the setup for "count visits before consent, set the persistent cookie after." It's the right answer when you want cookieless measurement up front rather than fully blocking Matomo.

```js
var _paq = window._paq = window._paq || [];

// Requests fire cookielessly right away; only the _pk_* cookies wait for consent.
_paq.push(['requireCookieConsent']);
_paq.push(['trackPageView']);
```

```js
// On Accept
_paq.push(['rememberCookieConsentGiven', 720]);

// On Refuse, or a later withdrawal
_paq.push(['forgetCookieConsentGiven']);
_paq.push(['deleteCookies']);
```

Two things that catch people out. The `remember*` calls persist the decision so Matomo re-applies it on the next page; the matching `setConsentGiven` / `setCookieConsentGiven` grant for the current pageview only, so use those only if your consent manager stores the choice itself and re-calls them on every load. And `requireConsent` / `requireCookieConsent` has to be pushed *before* `trackPageView` in the queue, or the gate arrives after the hit has already gone out.

## Why "Refuse" doesn't stop Matomo

Here's the one that fills the forums: you installed a consent manager, the banner shows up, you click Refuse, and Matomo records the visit anyway. More often than not the consent API isn't the problem at all. The Matomo tracking code is loading twice. Your CMS or plugin auto-adds it, and your consent manager adds it too, and the auto-injected copy runs no matter what the visitor clicks. The banner faithfully controls its own copy of the tracker while a second, ungated copy fires underneath it.

<FlowLanes
  caption="Two loaders, one endpoint. The consent manager gates its own copy, but the auto-injected copy ignores the banner, so Refuse still produces a hit."
  start={{ title: "Visitor clicks Refuse" }}
  lanes={[
    {
      title: "Consent manager",
      tone: "ok",
      steps: [
        {
          title: "Its tracker copy stays gated",
          detail: "no request leaves the page",
          tone: "ok",
        },
      ],
    },
    {
      title: "CMS or plugin auto-inject",
      tone: "fail",
      steps: [
        {
          title: "Second copy fires anyway",
          detail: "the banner never gated it",
          tone: "fail",
        },
      ],
    },
  ]}
  end={{ title: "matomo.php", detail: "still receives the ungated hit" }}
/>

The fix is to make the consent manager the only thing that loads Matomo. In WordPress, which plugin you have decides where that switch lives:

- **Matomo for WordPress** (the all-in-one plugin that runs Matomo inside WordPress): go to Matomo Analytics → Settings and set Tracking mode to Disabled.
- **Connect Matomo** (formerly WP-Matomo, which connects to an external Matomo): go to Settings → Connect Matomo → Enable Tracking and set "Add tracking code" to Disabled.

Save, and the plugin stops auto-injecting the tracker. Now let your consent manager load Matomo instead. With the self-hosted [tarteaucitron.js](https://github.com/AmauriC/tarteaucitron.js), configure the Matomo service and run it in explicit-consent mode so nothing fires until the visitor chooses:

```js
tarteaucitron.user.matomoId   = 1;                          // your Matomo Site ID
tarteaucitron.user.matomoHost = '//analytics.example.com/'; // your Matomo URL, with trailing slash
(tarteaucitron.job = tarteaucitron.job || []).push('matomo');
```

The integration key isn't the same across tarteaucitron versions and products: the self-hosted open-source build documents the `'matomo'` job key shown above, while Matomo's own Tarte au Citron guide defines a custom `MatomoAnalytics` service. Check which one your version expects rather than copying a snippet meant for the other. The same overall pattern (disable the plugin's own tracker, then let the consent manager load Matomo) applies to Complianz, Cookiebot and the rest; only the configuration surface changes.

## Verify it in the Network tab

Don't trust the banner; watch the wire. In a fresh incognito window, open DevTools → Network and filter for `matomo.php`:

- Before choosing, with `requireConsent` and an explicit-consent banner, you should see no request to `matomo.php`.
- Click Refuse: still no `matomo.php` request, and no `_pk_id` or `_pk_ses` cookies in the Application tab.
- Click Accept: the request fires, and the hit shows up in Matomo → Visits Log.
- Accept, then withdraw and reload: confirm the `_pk_*` cookies are gone. That's what `deleteCookies` is for, and it's the test people skip.
- In cookieless mode (`requireCookieConsent`), hits should arrive without any `_pk_*` cookies until consent.

If a `matomo.php` request still slips through on Refuse, double injection is the first suspect but not the only one. Walk the loaders in order:

1. The CMS or plugin auto-tracker (the switch above).
2. A hard-coded snippet in your theme.
3. A Matomo Tag Manager container firing a tag outside its consent rule.
4. A consent-manager snippet queued wrong, e.g. `requireConsent` pushed after `trackPageView`, so the gate lands too late.
5. A server-side tracking endpoint. DevTools won't show a server-to-server hit, so the same consent decision has to gate that call too.
6. A cached `matomo.js` or cached HTML still serving an old snippet.

Item 5 is the one to keep in mind if you're routing hits through a [server-side endpoint or the HTTP Tracking API](/blog/matomo-http-tracking-api-server-side). And because the `config_id` is scoped per site, getting this right matters most when you run [multiple sites or domains in one Matomo](/blog/matomo-multiple-sites-domains-measurables). For the broader privacy posture around all of this, our notes on [hardening a Matomo install](/blog/harden-secure-matomo-installation) cover the settings that sit next to these.

## What we'd actually do

If you're France-based and your data stays inside Matomo, run the 5.9.0 Compliance assessment first and see how close you already are to exemption. It's the lowest-effort honest path, and it's now a few clicks. If you operate under a stricter DPA, or you're not sure, default to `requireConsent`, wire it through one consent manager, and verify Refuse in the Network tab before you call it done. Either way the technical work is small. Deciding which route is legitimate for you is the part to hand to someone qualified to make it.

The thing to hold onto is that Matomo's cookieless mode really is different from surveillance fingerprinting. A 24-hour hash that deletes its own salt is built to forget you, not to follow you. That gives you configuration options most analytics stacks don't have. Use them on purpose.

[Martez](/?utm_source=martez&utm_medium=blog&utm_campaign=matomo-consent-cookieless-tracking) connects Matomo with Meta Ads and Google Ads so ROAS, CLV, and attribution sit next to your web analytics instead of in a separate spreadsheet. It's in private beta. [Join the waitlist](/signup?utm_source=martez&utm_medium=blog&utm_campaign=matomo-consent-cookieless-tracking) if that's relevant to you.

Configure the tracker to match the legal call. Don't let the legal call get made by a tracker you forgot was running twice.
