Tags
Toggle a gate to see the effect. Blocked tags cannot be gated — there is no consent state that makes them lawful here.
https://www.googletagmanager.com/gtag/jsLoaded in <head> with no gate. This is the source of the pre-consent finding — the tag is the cause, the cookies are only the evidence.
https://analytics.aiventuretech.io/matomo.jsCorrectly gated. Loads only after analytics consent, and the data never leaves India.
https://connect.facebook.net/en_US/fbevents.jsBlocked outright rather than gated. On a surface used by students, no consent state makes this available.
https://www.googleadservices.com/pagead/conversion.jsSame campaign as the Meta pixel. Blocked.
https://static.hotjar.com/c/hotjar-*.jsGated, but gating is not enough — it records form fields as they are typed on a page collecting income and bank details. Referred for removal rather than configuration.
https://www.youtube.com/iframe_apiSwitching the three embeds to youtube-nocookie.com removes the tracking without losing the videos. Cheapest fix on the list.
https://cdn.partner-widget.example/w.jsPerforms canvas fingerprinting. Sets no cookie, so no banner would ever mention it and clearing cookies does not remove it. Blocked.
com.example.analytics:core:4.2Reads the device advertising identifier at app launch, before the in-app consent screen is shown. Initialisation must move behind the consent callback.
Two attributes per tag. The consent layer flips the type once the category is agreed.
<!-- Consent gate. Nothing that is not strictly necessary loads until the
visitor has answered, because consent has to precede the processing. -->
<script src="https://cdn.aiventuretech.io/consent/v3.js" data-notice="ntc-01"></script>
<!-- Gated tag: type="text/plain" means the browser will not execute it.
The consent layer rewrites the type once the category is agreed. -->
<script
type="text/plain"
data-consent-category="analytics"
src="https://analytics.aiventuretech.io/matomo.js"
></script>
<script>
// Anything that must run in response to a choice hooks the event.
window.addEventListener("consent:changed", (e) => {
const { analytics, functional } = e.detail.categories;
if (analytics) initAnalytics(); // never called before this fires
if (!analytics) purgeAnalyticsCookies(); // withdrawal must also clean up
});
</script>No browser to help you, and the same obligation.
// Mobile: the same rule, without a browser to help you.
// Wrong — the SDK reads the advertising identifier in onCreate:
// Analytics.initialize(this) // runs before any consent screen
// Right — initialise from the consent callback:
ConsentManager.onDecision { decision ->
if (decision.analytics) {
Analytics.initialize(context) // first call happens here
}
if (!decision.analytics) {
Analytics.purge() // withdrawal clears what was collected
}
}
// Crash reporting stays outside the gate only if it carries no personal
// data. Most crash reporters attach a device identifier, so most do not.Section 6(6) requires processing to stop within a reasonable time of withdrawal. For cookies that means three things, and most implementations do only the first.
- 1Stop loading the tagImmediate, and the only step most consent layers take.
- 2Delete the cookies already setIncluding those on a third-party domain, which usually means calling the provider's own opt-out rather than clearing them yourself.
- 3Tell the processor to delete what it holdsThe data collected before withdrawal does not become lawful by having been collected earlier. This is the step that needs a contract clause, not code.