TL;DR: You tell an AI coding tool to "add analytics" or "add the pixel". It pastes a script tag into the page head. That script runs on page load. It sets cookies and sends data before any banner exists. In the EU that breaks the ePrivacy Directive, which needs consent before non-essential storage on a user's device. Once the script sends an IP address or a cookie ID, GDPR applies too. The fix is not a banner. It is a gate. Nothing non-essential loads until the user says yes. This guide shows you how to check your own site in DevTools. It explains what counts as strictly necessary. And it shows how to gate the scripts an AI tool added.
Here is the usual path. A founder ships a SaaS built in Lovable, Bolt, or Cursor. Signups are slow, so they ask the tool to add Google Analytics. Then a Meta pixel for the ad campaign. Then a recording tool to see where people drop off. Each request takes one prompt. Each one lands in the page head. Weeks later the founder asks the same tool for a cookie banner. It writes a nice React component with an Accept button. The button sets a flag in local storage. It blocks nothing. The three scripts were already running before the banner painted. They still are.
The rule, in plain words
Two laws apply. People mix them up. Keep them apart and the fix gets clearer.
ePrivacy Directive 2002/58/EC, Article 5(3)
This is the cookie rule. It says you may only store data on a user's device if the user has consented. The same goes for reading data already there. Before they consent, they must get clear and complete notice. The article has two exceptions. Storage needed to carry a message across a network. And storage that is strictly necessary to provide a service the user asked for. A login session cookie is strictly necessary. An analytics cookie is not. The user asked for your product. They did not ask to be measured.
Note what the rule protects. It protects the device, not the data. It applies even if you never learn who the user is. The Court of Justice said as much in the Planet49 case in 2019. Pre-ticked boxes were not consent. And the rule applied whether or not the stored information was personal data.
The word "cookie" does not appear in Article 5(3). It says information. The EDPB's Guidelines 2/2023 spell out what that covers. Tracking pixels. Local storage and session storage. Browser fingerprinting. Tracking IDs in links. A pixel that fires a request with your user's data is inside the rule. So is a script that writes a device ID to local storage.
GDPR, once personal data moves
ePrivacy gets you to the point of storage. GDPR takes over the moment the script sends personal data anywhere. That happens fast. A GA4 hit carries the user's IP address and a client ID cookie. Recital 30 of the GDPR names cookie IDs as online identifiers. They can single a person out. So you are processing personal data, and Article 6 asks for a lawful basis.
For tracking, the realistic basis is consent. Article 4(11) defines it. Freely given. Specific. Informed. Unambiguous. Given by a statement or a clear affirmative action. Article 7 adds four conditions. You must be able to show that consent was given. The request must be clear and separate from other matters. Withdrawing must be as easy as giving. And a service should not be made to depend on consent to tracking it does not need. Article 7(4) tells regulators to weigh that heavily. The UK kept the same rule after leaving the EU. It lives in PECR Regulation 6.
One more line to save you a mistake. The EU AI Act has nothing to say about cookies. If your app uses AI, its transparency duty sits in Article 50. It does not change consent for tracking.
What an AI coding tool actually ships
We have audited 700+ AI-built SaaS, websites and apps. The average Launch Readiness Score is 44 out of 100. The consent problem is a side effect of the same root cause behind that number. The tool is asked to make a feature work on the first run. It does. It does not ask what should happen first.
Here is what "add Google Analytics" produces in a typical Next.js or Vite project. The tool puts a <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"> tag in the root layout. Below it, an inline block calls gtag('config', 'G-XXXX'). That call fires a page view on every route. Nothing checks whether the user agreed. The same pattern repeats for the Meta pixel, a recording tag, a chat widget, and an ad-platform conversion pixel. Five prompts, five scripts, zero gates.
Then comes the banner prompt. The tool writes a component that renders a bar at the bottom of the page. Accept sets localStorage.setItem('cookieConsent', 'true'). Decline sets it to false, or just hides the bar. Neither branch touches the scripts. They loaded from the head before React mounted. The banner records a choice that changes nothing.
This is the pattern the four consent checks inside our Compliance Score look for. Whether cookie consent loads before the tracking scripts. Analytics without Consent Mode. Tracking pixels without consent. Session recording without consent. The checks are automated because the failure is mechanical. The script is in the head or it is not. It fires on load or it waits.
| Script the tool adds | What it stores or sends on load | Strictly necessary? | What the law expects |
|---|---|---|---|
| Google Analytics 4 | Sets _ga and _ga_* cookies. Sends IP, client ID, page path. | No | Load only after consent, or run with Consent Mode defaults set to denied. |
| Meta or ad pixel | Sets _fbp. Sends page view, often with matched user data. | No | Consent before load. Ad pixels are the clearest case of non-essential. |
| Session recording | Writes a device ID to storage. Streams mouse moves, clicks, and typed text. | No | Consent before load. Mask input fields even after consent. |
| Chat widget | Sets a user ID cookie. Sends page URL and, if logged in, user email. | Rarely | Consent before load, or a click-to-load button that opens chat on demand. |
| Login session cookie | Stores the session token. | Yes | No consent needed. Still list it in your cookie notice. |
| The consent choice itself | Stores what the user picked. | Yes | No consent needed. This is the one cookie that must exist before the others. |
Audit your own site in ten minutes
You do not need a tool for the first pass. You need a browser and a clean slate.
Step 1: Fresh private window
Open a private or incognito window. Extensions are off, so ad blockers will not hide the problem. Do not log in. Do not click anything yet.
Step 2: Load the homepage and read the Application tab
Open DevTools before you load the page. Go to the Application tab. Expand Cookies, then Local storage. Now load your homepage. Do not touch the banner. Every entry you see was set before consent. Sort them. A session or CSRF cookie is fine. Anything with _ga, _fbp, _gcl, _hj, _clck, or a vendor name is a finding.
Step 3: Read the Network tab
Reload with the Network tab open. Filter by third-party domains. Requests to google-analytics.com, googletagmanager.com, facebook.com/tr, clarity.ms, or hotjar.com that fire before you click anything are the proof. Right-click one and copy the URL. The query string usually holds the client ID and page path being sent.
Step 4: Click Decline and repeat
If there is a banner, click the decline option. If there is no decline option, that is a finding on its own. Reload. Check whether the same cookies and requests still appear. In an AI-built app they usually do. The banner and the scripts never met.
Step 5: Read the source
View the page source. Search for gtag, fbq, clarity, hj(, and <script tags pointing at third-party hosts. Each one in the raw head fires on load. Each one is a line to move behind a gate. While you are there, check for a Content Security Policy header. Missing HTTP security headers show up in 83% of the scans we run. A CSP is your backstop. It stops a script from loading at all if you did not list its host.
What counts as strictly necessary
This is where founders get nervous and over-read the rule. The exception is narrow but it is real. The test is whether the user asked for a service that cannot work without the storage.
Clearly exempt. Session cookies for login. A CSRF token. The shopping cart. A load-balancer cookie. The cookie that stores the consent choice. A language or currency setting the user picked. A cookie that remembers a form they were filling in.
Clearly not exempt. Analytics. Ad pixels. Session recording. Heatmaps. Social sharing widgets that phone home. A/B testing tools that assign a bucket. A chat widget that loads and sets a user ID before anyone opens it.
The grey area is first-party audience measurement. Some regulators, France's CNIL among them, allow a narrow exemption for privacy-friendly analytics. The conditions are strict. First-party only. No cross-site tracking. Short retention. Truncated IP. Aggregate output. A stock GA4 install does not meet those conditions. A self-hosted, cookie-less counter might. If you want to rely on the exemption, read your own regulator's guidance first. Do not assume.
How to gate the scripts
Three approaches work. Pick one and apply it to every non-essential script. Do not mix a gated GA with an ungated pixel.
Option 1: Load nothing until consent
The simplest and the safest. Remove the third-party script tags from the head. Keep a small consent script that runs first. It reads the stored choice. If there is no choice, it shows the banner and loads nothing else. On accept, it creates the script elements and appends them to the document. On decline, it does nothing and remembers that. Every vendor tag becomes a function you call, not a tag that runs.
If an AI tool wrote your banner, this is the change to ask for. Say it plainly. "Remove all analytics and pixel scripts from the layout. Load them only from the consent handler, after the user accepts. Decline must load nothing." Then check the head yourself. Trust the diff, not the summary.
Option 2: Google Consent Mode v2 with defaults set to denied
If you use Google tags, Consent Mode lets the tag load but holds back storage until consent. It only works if the default call comes first. Before the gtag('config') line, add gtag('consent', 'default', {...}) with analytics_storage, ad_storage, ad_user_data, and ad_personalization all set to 'denied'. When the user accepts, call gtag('consent', 'update', {...}) with the categories they picked. Order matters. If the config line runs before the default, the first page view fires with cookies.
Consent Mode covers Google tags only. It does nothing for a Meta pixel or a recording tool. Those still need Option 1 or a consent platform that blocks them.
Option 3: A consent management platform
A CMP does the blocking for you. It scans your tags, sorts them into categories, and holds them until the user chooses. It also logs consent with a timestamp and policy version, which Article 7(1) asks you to be able to show. The trap is the setup. Many CMPs offer an auto-blocking mode and a manual mode. In manual mode you must change each script tag's type so the CMP controls it. If your AI tool added the tags after the CMP was installed, they are probably not under its control. Re-run the DevTools check after every deploy that touches the head.
Server-side and first-party analytics
One trap sits behind the browser. Some AI-built stacks send events from the server as well. A signup handler posts to an analytics API. A webhook forwards the user's email to an ad platform for matching. No script tag, so the DevTools audit will not show it. The consent rule still applies, because the data is still personal data. Pass the user's consent state to your backend. Check it before any event leaves your API layer. If you do not have the state, do not send.
You can measure without tracking. Server logs already tell you which pages were requested. A first-party endpoint that records a page path and nothing else does not read or write on the device. That sits outside Article 5(3). Keep it that way. Do not add a persistent ID. Do not send the raw IP to a third party. Aggregate on your side. You lose funnels that follow one person across sessions. You keep the numbers that matter for a pre-revenue product. Which pages get traffic. Where users leave. What the free scan form converts at.
The banner itself
Once the gate exists, the banner has to be honest. Accept and decline must be equally easy. Same size, same step, same screen. No pre-ticked boxes. Say what each category does in one line. Link to a cookie notice that lists every cookie, its purpose, its lifetime, and who sets it. Give the user a way to change their mind later. A footer link that reopens the banner is enough. And record the choice. Store what was picked, when, and which version of the notice they saw. That record is your Article 7(1) proof.
Fix checklist
Work through this in one sitting. Most items are a ten-minute change.
- Run the five-step DevTools audit above in a private window. Write down every cookie and request that fires before consent.
- Sort each one. Strictly necessary or not. When in doubt, it is not.
- Remove every non-essential script tag from the head and the root layout.
- Move each one into a loader that runs only after an explicit accept.
- If you use Google tags, add the Consent Mode default call before the config line. All four categories denied.
- Make decline as easy as accept. Same button size, same step.
- Store the consent record. Choice, timestamp, notice version.
- Write or update the cookie notice. Every cookie, purpose, lifetime, setter.
- Add a footer link to reopen the banner.
- Add a Content Security Policy that lists only the hosts you allow. Test it with our security headers checker.
- Re-run the DevTools audit. Decline path and accept path both.
- Add the audit to your deploy checklist. Any prompt that says "add tracking" gets checked before it ships.
See what your app exposes before a user consents to anything
Run a free scan on your live URL. You get a Launch Readiness Score out of 100. You also get the missing headers, open data paths, and leaked keys that sit next to the consent problem.
Run a free scanWhere this sits in the wider picture
Consent for tracking is one piece of a larger duty. Article 25 says the shipped defaults must process only the personal data each purpose needs. A tracking script that fires on load is a default nobody set. The same code habit shows up in the database layer. Tables open to anyone with the public key. Full rows returned to the client. It shows up in logs. Full request bodies with emails in them. The consent gate is often the first place a founder sees the pattern. A user can watch it happen in DevTools.
The data you collect through those scripts also lands in your data map. Every vendor that receives a hit is a recipient. Each one needs a processor agreement under Article 28. If a user files an access request, the analytics profile is part of what you owe them. If tracking reaches into health, finance, or children's data, it can be a trigger for a DPIA. None of that is a reason to panic. It is a reason to gate the scripts first, so the rest of the map stays small.
Working through launch readiness for a Lovable app? The production readiness checklist covers the security side of the same head section. The compliance checklist and the wider GDPR guide for AI-built apps put consent next to the other duties. Comparing tools for the compliance side? Our Comp.ai alternative page explains where an automated check ends and a human fix begins. Pricing is on one page. No call needed.
FAQ
Does a cookie banner make my AI-built app compliant?
No. A banner is a way to ask. Compliance is what the code does with the answer. If the analytics and pixel scripts sit in the page head, they run before the banner paints. The user's choice arrives after the cookies are set and the first hit is sent. That is the pattern most AI-built SaaS, websites and apps ship. Open a private window, load your homepage, and look at the Application tab in DevTools before you click anything. If tracking cookies are already there, the banner is not doing its job. Move the scripts behind a gate that loads them only after an explicit accept.
What does ePrivacy Article 5(3) require, in plain words?
You may only store data on a user's device, or read data already stored there, after the user consents. Before that, they must be told clearly what you store and why. Two things are exempt. Storage needed to carry a message across a network. And storage strictly necessary for a service the user asked for, like a login session. Analytics, ad pixels, session recording, and chat widgets are not exempt. The rule protects the device, so it applies even when you do not know who the user is.
Is Google Consent Mode v2 enough on its own?
It is enough for Google tags, and only if the default call runs first. Set analytics_storage, ad_storage, ad_user_data, and ad_personalization to denied before the config line. Then update them after the user accepts. If the order is wrong, the first page view fires with cookies. Consent Mode does nothing for a Meta pixel, a recording tool, or a chat widget. Those still need to be held back until consent. Use your own loader or a consent platform that blocks them.
Why did my AI coding tool not add consent gating?
Because you asked it to add analytics, and it did. The tool is tuned to make the feature work on the first run. Working means the script loads on every page and fires on load. Nobody asked for a gate, so it wrote none. Later, when you ask for a cookie banner, it writes a component that stores a flag and hides itself. It does not go back and change how the scripts load. The fix is to tell it exactly that. Remove the tags from the layout. Load them only from the consent handler. Decline loads nothing. Then read the diff.
Do I need consent for a login session cookie?
No. A session cookie is strictly necessary to provide the service the user asked for. The same goes for a CSRF token, a shopping cart, and a load-balancer cookie. So does the cookie that records the consent choice itself. You still have to list them in your cookie notice with their purpose and lifetime. What you do not have to do is ask permission before setting them. The line is whether the service can work without the cookie. A login cannot. Analytics can.
Can a free security scan find scripts that fire before consent?
The security scan finds the technical gaps around them. Missing security headers, including the Content Security Policy that decides which third-party hosts may load a script at all. Leaked keys in the bundle. Open data paths. The consent timing itself is one of the checks in our Compliance Score. It looks at whether consent loads before the tracking scripts. It checks for Consent Mode. And it checks whether pixels and session recording fire without consent. Neither is legal advice. Both give you the facts about what your code does today.
Research sources
- EUR-Lex — Directive 2002/58/EC (ePrivacy Directive), consolidated text, Article 5(3), reference for the Article 5(3) consent rule and its two exemptions.
- EDPB — Guidelines 2/2023 on Technical Scope of Art. 5(3) of ePrivacy Directive, reference for pixels, local storage, fingerprinting and link tracking falling inside the rule.
- GDPR-info.eu — Art. 7 GDPR - Conditions for consent, reference for demonstrating consent, withdrawal as easy as giving, and the no-bundling condition.
- GDPR-info.eu — Art. 4 GDPR - Definitions, reference for the Article 4(11) definition of consent.
- Google — Consent Mode developer guide, reference for the default and update calls and the four consent types.
- EUR-Lex — Case C-673/17 Planet49, reference for pre-ticked boxes not being valid consent and Article 5(3) applying regardless of personal data.
- Jai Mittal, Founder & CTO, Launch Ready Code — Proprietary data from 700+ AI-built app security audits, 2025–2026. Average Launch Readiness Score: 44/100. Missing HTTP security headers in 83% of scans.