Right to Erasure ("Right to Be Forgotten")
Almost every consent-related privacy law gives a visitor some form of right to have their data deleted — GDPR calls it the right to erasure (Article 17), CCPA/CPRA calls it the right to delete, LGPD, KVKK, POPIA, and the rest have their own names and article numbers for essentially the same idea. This guide covers how that right is implemented in Consenti end to end: the server-side erasure endpoint, the preference modal's "Forget me" button, and the events both sides fire so you can wire the parts of the flow that are legitimately your responsibility, not the CMP's.
What Consenti erases vs. what's your responsibility
A CMP only ever holds one narrow slice of a visitor's data: their consent record — which cookie/tracking categories they agreed to, when, and under which profile version. Consenti erases thatslice completely, instantly, and without friction, because it's the one thing the CMP can delete with full confidence and no risk of deleting the wrong person's data.
A full erasure request usually reaches further than that, though — into your CRM, analytics warehouse, order history, support tickets, and any third-party processor you pass data to. None of that is something a cookie-consent widget can see or safely touch, and regulators generally expect identity verification and a response window (GDPR gives you a month) before a broader erasure request is fulfilled — not an instant, unverified self-service delete.
So the split is deliberate:
- Consenti erases its own consent record instantly, self-service, no verification.There's nothing to verify — a signed ownership cookie already proves the request came from the same browser that gave the consent in the first place.
- Consenti fires events on both erasure paths (server-side
consent:erasedon the eventBus, client-sideconsenti:forgetMeRequested/consenti:forgottenon the widget) so your own backend and frontend code can hook in and run whatever broader, identity-verified erasure workflow your business actually needs — deleting the visitor from your CRM, DMP, or analytics platform, or kicking off a formal DSAR case if your data footprint requires one.
The compliance mapping
Same right, different name and article number depending on the regulation. Every one of these maps onto the identical DELETE /consent/:visitorId endpoint described below:
| Regulation | Where it's defined | Compliance guide |
|---|---|---|
| GDPR (EU) | Article 17 — Right to erasure | GDPR guide |
| UK GDPR | Art. 17, applies identically to EU GDPR | UK GDPR guide |
| CCPA / CPRA (California) | Right to delete | CCPA guide · CPRA guide |
| LGPD (Brazil) | Art. 18 — Right to erasure | LGPD guide |
| DPDPA (India) | Section 12 — Erasure (Section 6 covers withdrawal) | DPDPA guide |
| KVKK (Turkey) | Article 7 — Right to request deletion | KVKK guide |
| PIPEDA / Law 25 (Canada) | Right to access and erasure | PIPEDA guide |
| PDPA (Thailand) | Erasure | PDPA Thailand guide |
| APPI (Japan) | Erasure | APPI guide |
| POPIA (South Africa) | Section 24 — Erasure and access | POPIA guide |
Server-side: the erasure endpoint
DELETE /consenti/api/v1/consent/:visitorIdThis deletes, for the given visitor ID:
- Every entry in
consent_records - Every entry in
consent_history - The
visitorsrecord (IP hash, UA hash, geolocation)
The visitor ID itself is a random UUID with no PII embedded in it, and the request is ownership-verified — only the browser that originally submitted the consent (proven by a signed consenti_{visitorId} cookie) can erase it. The response also expires that ownership cookie.
Deletion fires a consent:erased event on the server-side eventBus — this is the hook for cascading the erasure into your own systems:
eventBus.on('consent:erased', ({ visitorId }) => {
// Remove the visitor from your own DMP / analytics / CRM
myDmpClient.deleteUser(visitorId)
})audit_logstable is append-only by design — the erasure request itself is logged there and that log entry is retained as compliance evidence (most regulations, including GDPR Art. 17(3)(b), carve out an exception for records you're legally obligated to keep). Only the consent data itself is deleted, never the fact that an erasure happened.Client-side: the preference modal's "Forget me" button
The widget doesn't expose this by default — a host developer has to opt in, because it's a destructive, one-way action that not every profile wants surfaced as a one-click button. There are two authoring steps, both in the dashboard.
1. Enable it on the UI Template
Open the profile's linked UI Template (Banners → UI Templates), go to the Preference Modal step, and check "Show 'Forget me' button" — right next to "Show locale switcher". This is a structural, per-template toggle (preferenceModal.showForgetMe), the same category as showClose or trapFocus — it controls whether the slot exists at all, shared by every profile that uses this template.
2. Author the button's label
Back in the profile editor's content step (Step 4, Preference Modal), a "Forget Me Button"section appears once the template flag above is on — author the button's label per locale, same pattern as the consent-receipt checkbox's label. Falls back to "Forget me" if left blank.
Runtime behavior
- Rendered in the modal body, below the categories — only for visitors who already have a stored consent decision (
widget.hasConsent()). A first-time visitor has nothing to erase yet, so the button doesn't render for them. - Clicking it asks for confirmation (the action is destructive and can't be undone), then calls
widget.forgetMe()— see below. - After erasure, the banner (or age-gate, if the profile has one) re-prompts automatically, the same way
reConsent()already behaves — the visitor is back to a no-consent state, so the compliance banner has to reappear.
Events
forgetMe() dispatches two widget events, mirroring the server's consent:erased:
| Event | Fired | Use it for |
|---|---|---|
consenti:forgetMeRequested | Right before the erasure call goes out | Kick off your own identity-verified erasure workflow in parallel |
consenti:forgotten | After the consent record is erased and the banner/age-gate has re-prompted | Confirm-and-log, analytics, redirect to a "you've been forgotten" page |
import type { ConsentEvent } from '@consenti/ui'
widget.on('forgetMeRequested', (data: ConsentEvent) => {
// e.g. queue your own backend DSAR intake for this visitor
fetch('/api/dsar/erasure-request', {
method: 'POST',
body: JSON.stringify({ visitorId: data.visitorId }),
})
})
widget.on('forgotten', (data: ConsentEvent) => {
console.log('Consent record erased for', data.visitorId, 'at', data.timestamp)
})Other ways to trigger erasure
The preference modal button isn't the only way in — all three methods below are public and can be wired to a custom link anywhere on your site (a footer, an account/privacy-settings page):
| Method | Erases the record | Re-prompts banner/age-gate | Fires forget-me events |
|---|---|---|---|
widget.deleteConsent() | Yes | No | No |
widget.reConsent(resetAgeGate?) | Yes | Yes | No |
widget.forgetMe(resetAgeGate?) | Yes | Yes | Yes |
Use deleteConsent()if you're about to show your own custom UI next and don't want the banner popping up first. Use reConsent()for a plain "change my cookie settings" link that isn't framed as an erasure/rights request. Use forgetMe()whenever the action is user-facing as a right — a "Delete my data" or "Forget me" link — so the events are there for you to hook into.
<a href="#" id="delete-my-data">Delete my data</a>
<script>
document.querySelector('#delete-my-data').addEventListener('click', (e) => {
e.preventDefault()
window.__consenti?.forgetMe()
})
</script>