Section 25 TDDDG is Germany's implementation of Article 5(3) of the ePrivacy Directive. The wording differs across member states, the mechanism does not, so the reasoning here travels well beyond Germany.
What the court decided
A newspaper publisher sued the data protection authority of Lower Saxony after a user complaint. The cookie banner offered only "Accept all" and "Settings" on its first layer, and Google Tag Manager was running in the background before anyone had clicked anything. The authority objected to both. The court dismissed the claim and found the order lawful.
Two findings, both uncomfortably concrete.
Rejection belongs on the first layer. A banner that hides rejection behind "Settings" is unlawful. Refusing consent has to be as easy as granting it.
Google Tag Manager requires consent in its own right. Not the tags inside it. The container itself.
The authority's test lab had logged that the IP address and device data went to Google servers in the US before any banner interaction. For the court, that satisfied Section 25(1) TDDDG. The exception in subsection 2 no. 2 requires the access to be strictly necessary to provide the service the user explicitly requested. The court denied it: GTM serves the operator's interests rather than the users', gives them no function of their own, and is not without alternatives.
For marketing teams this is an unfamiliar angle. Internally the tag manager counts as infrastructure. Legally it is a third-party service you could do without.
What happens when gtm.js loads
The standard install sits in the <head>, usually right behind the charset tag. Once the parser reaches it, a chain runs whose end state is data that has left the device.
- Connection to
www.googletagmanager.com. DNS lookup, TLS handshake. The handshake carries the target host in cleartext via SNI, the TCP connection carries the visitor's IP address. GET /gtm.js?id=GTM-XXXXXX. The request carries the IP address, User-Agent,Accept-Languageand, depending on your referrer policy, the page URL.- Execution in page context. The container reads the
dataLayer, screen metrics, language, cookies already set. It decides what happens next. - Downstream loads. Typically
gtag/jsfollows, then the first hit to/g/collect.
Steps 1 and 2 are enough on their own. No cookie, no click, no consent, and the IP address and device properties have still arrived at a US provider.
One page load, standard snippet in the `<head>`, banner untouched. Each step shows what leaves the device.
Step 1/7 · 0 ms
Parser reaches the head
no requestLeaves the device
- nothing
Nothing critical yet. The snippet sits in the markup, waiting to execute.
Illustrative sequence. Timings are indicative, requests and headers match the standard snippet.
Why "no cookie" does not mean "no Section 25"
Section 25(1) TDDDG covers two acts: storing information on terminal equipment and gaining access to information already stored there. Cookies are the best-known case, not the only one.
The EDPB worked this through for cookieless techniques in Guidelines 2/2023 on the technical scope of Article 5(3) ePrivacy (version 2.0, adopted 7 October 2024): URL and pixel tracking, local processing in the browser, tracking on IP alone, identifiers in IoT contexts. "Information" is explicitly not limited to personal data.
So the objection that the container sets nothing by itself defends the wrong half of the provision.
The container myth, and why it no longer holds
"GTM is neutral, it only transports." That argument survived audits for years because it is technically half true: an empty container writes no analytics cookies. It just answers a question the law is not asking.
The court anchored its reasoning at two points, both easy for an operator to follow. First, purpose: the tag manager makes script management easier for the operator, and for a visitor who opens a news site to read one article it changes precisely nothing about whether that article arrives. Second, necessity. Tags can be delivered another way, straight in the source or through a European alternative. What can be replaced is not strictly necessary.
What consent mode does not fix
This is where the most expensive assumption lives, and it is common because Google offers two variants whose difference barely shows in the interface.
In basic consent mode, Google tags do not load before the user interacts with the banner. In advanced consent mode they load when the page opens and send cookieless pings while consent is denied. Both statements come from Google's own documentation. Advanced is the more convenient route and supplies the basis for conversion modelling, which is why most implementation guides recommend it.
That state is precisely what the Hannover proceedings were about. Requests before the interaction, IP address and device data transmitted, consent still open. The pings being cookieless changes nothing about Section 25(1): access to the terminal equipment has already happened, and so has the transfer to the US.
Consent mode is a signalling protocol for how tags behave. It does not control when the container loads.
Five myths, held against the law
| Common assumption | How the court and the provision see it |
|---|---|
| "GTM is just a container and processes no data itself." | Fetching gtm.js transmits the IP address and device data. The court treats GTM as requiring consent in its own right. |
| "Without a cookie, Section 25 does not apply." | Section 25(1) covers storage and access. The EDPB counts IP, pixel and URL techniques too. |
| "Consent Mode V2 solves this." | Advanced mode loads the tags before consent. The signal governs their behaviour, not when the container loads. |
| "GTM is technically necessary, our tracking breaks without it." | Necessity is measured by what the user needs for the service. Tags can be delivered another way; per the ruling, GTM is not without alternatives. |
| "A banner with 'Accept all' and 'Settings' is enough." | Rejection has to be possible on the first layer, as easily as acceptance. |
Five questions along the two points the court decided. Answers stay in the browser, nothing is sent.
Still open: 5/5
Orientation for a technical review, not legal advice. Have your case assessed by a lawyer.
Three ways out, and what each costs
There is no variant without a price. Anyone promising otherwise is selling compliance theatre.
Route 1: put the container behind the CMP
GTM loads only once consent exists. Three lines in the CMP callback, an hour's work in any consent platform.
The price is steep. At DACH-typical consent rates of 30 to 40%, two thirds of your traffic disappears entirely, anonymised measurement included. No modelling, no load-time data, no server-error detection. For sites whose reporting is pure marketing attribution, fine. For anything carrying product responsibility, not.
Route 2: CMP gating with an event queue
The container stays the central dispatcher but is instantiated only after the consent signal. So that interactions happening before the answer are not lost, a small queue buffers them in memory and replays them into the dataLayer once consent arrives.
Technically the most honest compromise for pure client-side setups. You keep the GTM interface, you lose no early events from consenting users, and nothing loads from Google beforehand. What remains: without consent there is still no data, and measurement still hangs on browser scripts that Safari, Firefox and ad blockers keep trimming.
Route 3: first-party loader in front of a server container
The loader comes from your own subdomain, say sgtm.yourdomain.com, served from a server container in an EU region. The browser talks to your infrastructure, not to googletagmanager.com. The server then decides what it forwards to which platform, stripped or enriched.
That solves three things at once: the third-party fetch at page load disappears, the IP address terminates on your server instead of Google's, and the consent check moves to a place you control and can log. Plus the side effect most teams actually budget the project for: server-set cookies avoid the 7-day cap Safari ITP applies to cookies set from client-side script.
Same container, three load points. The row under the tabs is the comparison, the code below is the implementation.
- Request before consent
- yes, several
- Host on page load
- googletagmanager.com
- Interactions before the click
- captured
- Cookie lifetime in Safari
- 7 days (ITP)
The state at issue in the Hannover proceedings.
<head>
<meta charset="utf-8">
<!-- Runs the moment the parser gets here. No consent check. -->
<script>(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({'gtm.start': new Date().getTime(), event:'gtm.js'});
var f=d.getElementsByTagName(s)[0], j=d.createElement(s);
j.async=true;
j.src='https://www.googletagmanager.com/gtm.js?id='+i;
f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
</head>Delivery itself is unremarkable. A reverse proxy or an edge worker is enough, mapping /metrics/* onto the server container and returning the response under your own cache policy.
# nginx: loader and transport run under your own domain.
# No request to googletagmanager.com, no third-party context.
location /metrics/ {
proxy_pass https://sgtm-container.internal:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# Forwarding the IP is a deliberate decision, not a default.
# For zero-PII at the edge: drop the header or truncate to /24.
proxy_set_header X-Forwarded-For "";
proxy_hide_header Set-Cookie;
add_header Cache-Control "private, max-age=900" always;
}
// Cloudflare Worker, same job without running your own reverse proxy.
// The container region stays EU, the client only ever sees your domain.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (!url.pathname.startsWith('/metrics/')) return fetch(request);
const upstream = new URL(url.pathname.replace('/metrics', ''), env.SGTM_ORIGIN);
upstream.search = url.search;
const headers = new Headers(request.headers);
headers.delete('cf-connecting-ip');
headers.delete('x-forwarded-for');
headers.set('x-ds-region', 'eu');
return fetch(new Request(upstream, { method: request.method, headers, body: request.body }));
},
};
What server-side does not do
One sentence missing from every second sales deck: server-side tagging does not replace consent.
The first-party loader ends the third-party fetch and the US transfer at page load. It does not turn remarketing into a consent-free activity. Sending conversions to Google Ads or Meta through a server container still processes personal data for advertising and still needs a legal basis. A loader of your own that fires without consent and reads user identifiers also falls under Section 25(1).
What changes is the evidence position. You can show which request went where, which field was stripped first, and which consent state applied. Demonstrating that is the controller's job anyway, not the authority's, per Article 7(1) GDPR.
Five steps before your next release
If the Digital Omnibus lands
A proposal has been on the table in Brussels since November 2025 to move the cookie rules out of the ePrivacy Directive and into the GDPR, partly as a new Article 88a. It foresees single-click rejection and cooling-off periods before the same consent may be requested again. As of August 2026 the Council, Parliament and Commission are still negotiating, with a conclusion expected by the end of 2026.
Two things follow. It is not law, and it is not a planning basis either. And the direction offers no relief to anyone loading before consent today: single-click rejection is exactly the requirement VG Hannover already derived from law in force.
Build it cleanly now and you build in the same direction.
The architecture itself is stack-agnostic. Whether the shop runs on Shopify or Shopware and the front end is Next.js, Astro or TYPO3: the loader sits on your subdomain, the server container in an EU region, and the consent check in one place you can log. What that looks like with a specific CMP is in the Usercentrics guide for server-side GTM; the consent loss calculator puts a number on the economics.
