Skip to content
MethodInsights

GDPR on your website: cookies, consent, and data flows

The banner is UI. The data flow is what you have to defend.

A cookie banner is not GDPR. What counts is what the browser actually sends, who receives it, and whether consent was a choice.

Stylised CI pipeline with checks and gates — the process that decides which scripts may run before anything reaches production.

Method & compliance

If you are searching for GDPR on a website, cookie consent, or tracking rules, you typically already have a banner. That is rarely the problem. The problem is that the banner says one thing and the network panel says another: analytics runs before anyone has clicked, a pixel sits in GTM "because marketing asked", and the chat widget sends page content to a vendor you never put on the processor list.

We meet two kinds of site. One has a banner that can only be accepted — reject is hidden, or pre-ticked. The other has a tidy CMP and still twelve third-party calls on first load. Both fail the same test: can you point at every data flow, say what lawful basis it has, and turn it off when the basis is consent and consent is missing? If not, you have a website problem. Not a legal problem you can outsource to a footer paragraph.

TL;DR

The main points

  • GDPR on a website is three layers: what you write, which cookies you set, and which calls the browser actually makes.
  • A banner is only honest if reject is as easy as accept, and if scripts actually wait.
  • Necessary cookies are few. Analytics, pixels, session replay, and most chat widgets are not.
  • GTM is not a lawful basis. It is a pipe. If something sits in the pipe without consent, that is your call.
  • The privacy policy must mirror the network panel — not a template from 2018.
  • Map the data flows before you buy a new CMP. Otherwise you are decorating a leak.

Why this matters in the first place

A website is one of the places you process personal data without thinking of it as a system. An IP, a cookie id, a form, a chat window, a video that calls home. GDPR asks about purpose, lawful basis, minimisation, and the rights of the people you identify. Cookie rules — ePrivacy, as implemented in Denmark — also ask whether you may set or read something in the browser before there is valid consent, unless it is strictly necessary for the service the user asked for.

The two rules get mashed into "we need a banner". The banner is UI. It solves nothing if Tag Manager fires Facebook, LinkedIn, and a heat map before anyone has chosen. It also solves nothing if you claim legitimate interest for all analytics while the tool sets third-party cookies and builds a profile across sites.

This is a different problem from where the server lives. Hosting and cloud subprocessors are a residency and DPA conversation. Website GDPR is what leaves the browser for a foreign machine: who gets the URL, the user-agent, the form fields, the session recording. You can keep data in an EU region and still leak a browsing pattern to five US pixels. You must be able to explain both. They do not replace each other.

We write this because agencies love to sell a CMP as finished work. The CMP is a tool. The work is knowing your calls, gating them, and letting the policy describe reality. Without that you are compliant in Figma and in breach in production.

The three layers: policy, cookies, and what the browser actually sends

The first layer is the text. The privacy policy and cookie declaration must say who you are, what you collect, why, for how long, and who the processors are. It is boring, and it is necessary. It is also the layer people update last. A policy that still names a tool you turned off, or misses the chat product you turned on last week, is a signal that you do not have an inventory.

The second layer is cookies and similar techniques — localStorage, pixels, fingerprint-like signals. Necessary are those without which the service the user asked for does not work: cart, login session, load balancing, a consent choice you must remember. Anything that measures, retargets, personalises across properties, or records the session typically needs consent. "We use it to improve the site" is a purpose. It is not automatically a lawful basis.

The third layer is the network. Open DevTools. Reload. See what goes out before you click. That is your real data map. A call to an analytics domain, a double-click id, a CNAME that looks first-party but points at a vendor — that is processing. If the banner still says "awaiting choice" and the call already happened, the banner is decoration.

The three layers have to line up. Policy without calls is fiction. Calls without policy are what a supervisory case points at. Cookies without calls can be leftovers. Calls without cookies can still be personal data. Think in flows, not in "did we remember the cookie banner".

Necessary is what makes the action the user asked for work. A cart. A session after login. A load-balancer cookie. A consent cookie that remembers "no thanks". A security token. That is a short list. It does not get longer because marketing calls a tool "essential". If the site works without the call, the call was not necessary.

Analytics is the most common self-deception. First-party, cookieless, aggregated measurement can in some designs be defended without consent — that is a legal call, and it requires that you actually turned identifiers and sharing off. Classic pageviews with a client id that follows the user, mixed with ads, is not that design. Do not assume "statistics are legitimate interest" and leave GTM open. Build the measurement so you can explain it, or ask permission.

Marketing pixels, profiling A/B tools, session replay, most heatmaps, embedded social feeds, and "smart" chat that sends the URL and a snippet to a model are consent-land. Chat can be functional if it is yours, opens only after a click, and does not leak the page to a third party early. The chat that injects a script on every page and starts listening immediately is not.

Embeds are what people forget. YouTube, maps, a booking iframe, a review widget. They often set cookies you have not listed. An honest solution is a placeholder that loads the embed only after a yes — or after a deliberate "show map" click. That is more work than pasting an iframe. It is also what makes the policy true.

Functional first-party vs. what the banner must be able to turn off

Typically functional

Without it, the action the user asked for does not work.

  • Login session, cart, CSRF, load balancing
  • The consent choice itself, so you can remember a no
  • Content you host yourselves, without a third-party id
  • A chat that loads only after a deliberate open click and your DPA

Typically consent — or skip it

What measures, retargets, records, or shares.

  • Ad pixels, CAPI, linked audiences
  • Session replay and most heatmaps
  • Classic analytics with a durable client id
  • Embeds and GTM tags you cannot point at a lawful basis for

How to map the data flows in an afternoon

Without this inventory every CMP is guesswork. You cannot control what you have not seen.

  1. 01

    Open a clean window and reload the homepage

    Incognito, no adblocker. Network panel, cookies, localStorage. Write down every third-party domain. What you cannot name is risk — not "probably something from the theme".

  2. 02

    Repeat after reject, after accept, and on a thank-you page

    The three states often lie differently. Reject should look like a site without marketing calls. Accept may turn on what you described. A receipt page is where pixels love to hide.

  3. 03

    Review Tag Manager as if it were production

    Each tag: name, trigger, whether it waits for consent, which fields it sends. Remove what you cannot explain. GTM is a deploy pipe. It is not a free zone.

  4. 04

    Pair each flow with a lawful basis and a processor

    For each flow: purpose, basis, vendor, DPA, where the data lands. Empty cells are tasks. "We have always had that pixel" is not a basis.

  5. 05

    Only then: fix the banner, the gates, and the policy

    Make reject visible. Gate scripts so they do not load before a yes. Update the policy to what you actually do. Then you can change CMP later without starting over.

A cookie banner is honest when the network panel after "no thanks" is boring. Otherwise it is graphics.

How to gate scripts — so the banner is not theatre

The technical requirement is simple to say and easy to fail: no consent-requiring script may evaluate before the choice is yes. Not "must not set a cookie". Evaluate. A script that runs and then "chooses not to set" has often already sent IP and URL. Server-side tagging moves the call. It does not delete it. If you still send the same events to the same vendor, you still have processing — you just made it harder to see in the browser.

On a Next.js site that means: third parties in a loader that reads consent state, not in the root layout as a default. Chat, analytics, pixels, embeds. Consent Mode and similar signals are useful once you already have an honest inventory. They are not a licence to load the tag anyway. A default-on tag with "consent unknown" is the pattern we see most — and it is the wrong default.

On WordPress that means: the theme and the plugins that inject in head, not only the CMP plugin. An SEO plugin, a chat plugin, and a pixel plugin can all ignore the banner. One place that decides what may load beats five plugins that each "support GDPR".

Withdrawal is what you forget afterwards. The user must be able to say no tomorrow. Then you must turn those tags off, delete the cookies you can, and let the policy say how. If "manage cookies" links to a dead anchor, you built a museum. Put it in the footer, and test that a no actually removes the call on the next load.

What you should typically do in the situation you are in

The left is what you typically have. The right is the next step we typically recommend.

  • Situation

    The banner exists, but the calls run before a choice

    Next step

    Gate the tags. A CMP without a gate is UI — fix load order first

  • Situation

    You cannot list third-party domains on one page

    Next step

    The incognito inventory. Do not buy a new banner until you have the list

  • Situation

    Marketing insists every pixel is "essential"

    Next step

    Turn them off for a week. If the site works, they were not essential

  • Situation

    You have a customer portal with login behind the site

    Next step

    Separate the marketing site from the app session. Portal cookies are not an alibi for ads

  • Situation

    The policy names tools you no longer use

    Next step

    Update the text to the network panel. An old template is a breach in slow motion

Checklist before you call the site GDPR-ready

If you are missing several of these, the banner is ahead of the cause — not the other way around.

  • Reject is visible on the first screen and does not cost more clicks than accept
  • A clean reject load shows no marketing or replay calls
  • Every third-party domain has a purpose, a basis, and a processor you can point at
  • GTM and theme plugins do not fire default-on tags when consent is unknown
  • The privacy policy and cookie list match what you actually load after a yes
  • The user can change the choice later, and it turns the call off on the next load

Questions we get again and again

  • May we use Google Analytics without consent?

    Not as it is most often set up. A client id that follows a browser, mixed with ads or shared with other products, is rarely what you can call strictly necessary — and legitimate interest is not a free pass you can claim without having thought about minimisation and objection. Cookieless, first-party, aggregated measurement can be a different design. It requires that you actually turned the other things off. Ask a lawyer about your concrete setup. Do not assume a GA snippet in head is harmless.

  • Is a cookie banner enough to comply with GDPR?

    No. The banner is consent UI for what needs consent. GDPR is also purpose, processors, deletion, access, minimisation, and not collecting "because the field was on the form". A site with no banner and no tracking can be more honest than a site with a banner and twelve pixels. Start with the inventory. Then you know whether you need a CMP at all.

  • What about chat widgets and AI assistants on the site?

    If the script loads on every page and sends the URL, a snippet, or form fields to a vendor, that is processing — often before anyone asked for help. Gate it behind consent or behind a deliberate click, have a DPA, and write it in the policy. An assistant that only wakes after "open chat", and that does not leak the page in the background, is a different product from a tracker with a speech bubble on it.

  • Does server-side tagging count as "not tracking in the browser"?

    No. You moved the pipe. The purpose and the recipient are the same if you still send the same events. It can be sensible for performance and control. It does not remove the duty to have a lawful basis, and it does not remove the duty to turn off what needs consent. A CNAME that looks like you but belongs to a vendor is still their processing — just harder to spot.

  • What should we demand from an agency that "sets up GDPR"?

    An inventory of calls, a banner where reject is honest, gates tested in three states, and a policy that matches. If they can only deliver a plugin and a stock text, they set up UI. Ask for a screenshot of the network panel after reject. If it is not boring, the job is not done — whatever the quote called it.

If the banner says one thing and the network panel another

Let us map the calls the site actually makes.

An afternoon of inventory, gates, and an honest reject path is often enough to separate real consent from a banner you installed to get peace.

Why we wrote this

This is how we think — and it's what we build.

Our insights are about the work we actually do. If this hit something you're working on, there's a concrete service that lines up.