What happens when someone withdraws cookie consent

Collection stops for the categories they revoked, and the cookies already on their device mostly stay where they are. Three things should follow: the record gains a withdrawal event rather than losing the original grant, a denied signal goes out to every tool that takes one, and each tool resets identity before capture is switched off.
The answer everyone gives is about cookie files
Search this question and you get a narrower one answered: does withdrawal delete the cookies already on the device. The answer is no, and the reasoning is sound. A script can only touch cookies on its own domain, so nothing on your site can reach into a cookie another company set on theirs. That is a browser security rule, not a gap in your consent tool. A consent platform blocks the scripts that read and write those cookies instead.
That answer is correct, and it is the smallest part of the transition. Deleting a file afterwards protects very little: the moment that matters is when data moves, which is when a cookie is set and when it is read. Blocking stops both. Clearing files does not.
There is one real exception. With ads_data_redaction enabled and ad_storage denied, Google redacts the click identifiers in the pings it still sends. That is the only deletion lever in the stack that does anything, and it is a Google setting rather than something your banner performs.
What almost nobody writes down is what your measurement stack should do at that moment. That is where withdrawal goes wrong, and it goes wrong quietly: the banner closes and looks fine.
What should happen, in order
Withdrawal is a sequence, and the order matters more than any single call.
-
Record the withdrawal as a new event, not an edit
A withdrawal is not a correction of the original grant. It is a second fact: this visitor consented at one moment and revoked at another, and both are true. Store it as a new row pointing back to the grant it supersedes, on a table that cannot be updated or deleted. Overwrite the original and you have destroyed the only evidence that the earlier collection was lawful. Velo writes a withdrawal as a new event referencing the prior one, kept indefinitely even where ordinary grant records age out.
-
Send a denied signal, do not go silent
The instinct is to make everything stop firing. Under Consent Mode that is wrong. The tag should stay in place and receive an update setting
analytics_storageand the two advertising signals todenied. It then sends a cookieless ping carrying no identifiers, and that ping keeps modelling and basic reporting alive. Removing the tag entirely sends nothing, and nothing is not the same as a recorded refusal. One is a visitor who said no; the other is a visitor who does not exist. -
Tell each tool in the dialect it listens for
There is no single consent API. Google's tags read a
gtag('consent', 'update', …)call, Microsoft's a push touetq, Meta's anfbqcall. And Google Tag Manager's triggers cannot see a browser CustomEvent, so a withdrawal that only dispatches one leaves every custom event trigger unfired. Push a named event into the data layer too. Our own SDK funnels every path that changes consent, a banner click, a stored decision replayed, a Global Privacy Control signal forcing categories off, through one function emitting all four, so a withdrawal cannot leave by a different route than a grant. -
Reset the identity before you stop capturing, never after
Most analytics libraries expose two calls: one clears who the visitor is, one turns capture off. Almost everyone writes them in that order in their head, stop capturing then forget them, and almost everyone is writing a bug. In many libraries the consent flag and the identity share the same storage, so the reset clears the opt out you just set. Reset first, capture switch last.
-
Apply the gate again, then reload the page
Blocking governs what has not run yet. A script that already loaded is still in memory, holding its own timers, and can write its cookie again on the next interaction no matter what your banner now says. Applying the gate again stops the next thing; a reload is the only clean guarantee that nothing from the previous consent state is still running. It also replays the stored decision from the top, the path a returning visitor takes, so that case gets tested for free.
The step that bites
We found step four in our own stack, not a client's. Our banner denies analytics; the deny branch called the opt out first and the identity reset second. That reads correctly: stop capturing, then forget them.
In the data it produced two people: one identified, one anonymous, sharing a single device identifier minutes apart. The cause was in the library rather than the banner. In posthog-js 1.424.1 the reset call also resets the stored consent state, so running it after the opt out cleared the opt out, and capture resumed under a fresh anonymous identifier and a new session. Every visitor who withdrew was silently counted twice.
Reversing the two calls fixed it, verified in a fresh browser rather than in code review. Accept, and one identifier appears. Reject, and the opt out flag reads true with zero requests leaving for a forced event. Accept again later, and the same identifier comes back rather than a third one.
What the visitor should be able to see
Withdrawal has to be as easy as granting was: a control that reopens the preferences panel from every page, not a link buried in a policy document, and a decision that takes effect on the page they are standing on.
It also means a receipt they can point at later, the same mechanism that answers how you prove a visitor gave consent. A withdrawal is a consent record like any other.
The last thing to settle is when you ask again. A withdrawal is not permission to prompt on the next page view, and treating it as one is how a banner becomes an annoyance: how long cookie consent lasts and when the banner should ask again.
Test it like you test the first visit
Almost every banner has been tested on arrival. Almost none has been tested on the way out, which is why withdrawal bugs live for months while the accept path stays perfect. Accept, browse two pages, then withdraw, and watch three things: what leaves the browser, whether the opt out is still set a minute later, and how many people your analytics thinks that one browser was.
Velo routes every consent change, grant or withdrawal, through one path that records the event, updates Consent Mode, pushes the data layer event your container triggers on, and calls each vendor's consent API. That removes the divergence between the two directions. It does not remove the test: the order your own tools want their calls in is still yours to get right.
Common questions
What people ask about this topic.
What happens when someone withdraws cookie consent?
Collection stops for the categories the visitor revoked, and the cookies already on their device are mostly not deleted. Three things should follow: the consent record gains a withdrawal event referencing the original grant rather than overwriting it, a denied signal goes out to every tool that takes one so Consent Mode keeps sending a cookieless ping instead of going silent, and each analytics tool resets the identity before capture stops.
Do cookies get deleted when consent is withdrawn?
Usually not, and that is not a defect. A script can only touch cookies on its own domain, so nothing running on your site can remove a cookie another company set on theirs. A consent platform blocks the scripts that read and write them instead, which is what actually stops data moving.
Should the page reload after a visitor withdraws consent?
Yes, if you want a clean guarantee. Blocking governs what has not run yet, and a script that already loaded stays in memory with its own timers, so it can write its cookie again on the next interaction. A reload is the only reliable way to be sure nothing from the previous consent state is still running.
Why does withdrawing consent sometimes create a duplicate user in analytics?
Because the identity reset and the opt out were called in the wrong order. In many client libraries the consent flag and the identity live in the same storage, so a reset called after the opt out clears it, and capture resumes under a fresh anonymous identifier. One device then reads as two people. Reset first, opt out last.
Your banner, your consent,
your data, all in one place.



