Home / Blog / The Banner Fires Again on app.yoursite.com: Subdomain Consent, Fixed

The Banner Fires Again on app.yoursite.com: Subdomain Consent, Fixed

Published 2026-11-14

A visitor accepts cookies on the marketing site, then opens the app on a subdomain and gets the banner again. Or worse, the app treats consent as unknown and tracks anyway. The fix is one shared consent record: store it on the root domain, read it the same way everywhere, and propagate changes the moment they happen.

The symptoms are easy to miss in development and embarrassing in production. The banner reappears on every subdomain, visitors who declined get tracked by the marketing site's tags while the app shows a clean record, and the audit log holds conflicting versions of the same visitor's decision.

Why each subdomain drifts on its own

Cookies default to the host that set them, and localStorage is scoped to a single origin, so a consent choice on www.example.com is invisible to app.example.com unless you deliberately share it. The consent platform adds a second cause: most platforms scope their stored record by the domain configured in their console, so two hosts registered as separate properties each maintain their own decision no matter how your cookies are scoped.

The diagnosis takes two minutes. Accept on the main host, open Application then Storage, and find where the decision was written. Read the cookie's Domain column: a value of www.example.com is host-scoped, .example.com is shared. Navigate to the second host and inspect the same storage. If the record is absent, you have a scoping problem. If it is present but the banner still appears, you have a reading problem.

The shared record, done properly

The simplest reliable approach is a single consent cookie set with Domain=.example.com and Path=/, so every subdomain can read it. Mark it Secure and SameSite=Lax, and do not mark it HttpOnly, since your JavaScript needs to read it on each page load. Store a small JSON payload, not just an accept or reject flag: the version of your category schema, a timestamp, and each category the visitor decided on.

Sharing the cookie is only half the job. Each property still has to interpret it the same way, which means one shared reader, not five hand-rolled parsers. Give every codebase the same small consent helper with one job: return the current state, or return unknown when the record is missing or its version is unrecognized. The most common failure mode here is not the cookie. It is the app deciding that an unparseable record means consent granted, while the marketing site treats it as declined.

There is a cost to sharing. A domain-scoped cookie is transmitted to every subdomain on every request, including ones operated by third parties on your behalf, such as a status page or a marketing microsite run by an agency. Keep the payload small and do not put anything in it that you would not want every subdomain to see.

The test that catches it

Open a private window, accept everything on the marketing site, then open the app subdomain. The banner must not appear, the vendors must initialize with the accepted categories, and the Application panel should show one cookie with Domain=example.com rather than two host-scoped records. Then revoke marketing consent in the app tab and switch to the docs tab: the docs tab has to re-read the record on visibility change, because BroadcastChannel is same-origin only and cannot carry the change across subdomains.

Run that test after every CMP config change, not just at launch. Consent platforms get reconfigured per property by different teams, and the shared record is the first thing a per-property edit breaks.

Keep reading: GPC Is Not a Banner Setting: What the Global Privacy Control Signal Actually Does, Global Privacy Control: The Browser Signal Your Banner Cannot Ignore, Consent Mode v2 Meets Server-Side Tagging: Where the Signal Travels cover the nearby cases in this series.

Frequently asked questions

Why does the cookie banner appear again on a subdomain?

Because cookies default to the host that set them and localStorage is scoped to one origin. A choice on www.example.com is invisible to app.example.com unless the record is stored on the root domain with Domain=.example.com.

Can I share consent across completely different domains?

No. A cookie_domain covers one domain and its subdomains only. Browsers never share a cookie between two separate domains, so each domain asks for its own answer. Cross-domain consent needs a platform feature that syncs records, not a cookie setting.

Should the shared consent record live in localStorage?

No. LocalStorage is scoped to an exact origin, so www and shop subdomains have entirely separate stores with no mechanism to share. The record belongs in a domain-scoped cookie that every subdomain can read.

What goes wrong when the record cannot be parsed?

The dangerous default is treating an unparseable record as consent granted. Every host must return unknown for a missing or unrecognized record, and the banner must appear. Test this with a private window and a corrupted cookie, not just with a clean one.