GDPR Compliance Guide
Consenti is built from the ground up around GDPR requirements. All core design decisions follow the six lawfulness principles in Article 5.
ℹ️Compliance group:
opt-in — covers GDPR (EU / EEA), UK GDPR, PIPEDA (Canada), POPIA (South Africa), PDPA-TH (Thailand), APPI (Japan), and KVKK (Turkey). Use compliance: { type: 'opt-in' } in your ConsentiSetup config to activate the opt-in consent model.Official references
- Regulation (EU) 2016/679 — full text on EUR-Lex
- European Data Protection Board (EDPB) — guidelines, recommendations, binding decisions
- ICO — UK GDPR guidance (post-Brexit UK equivalent)
- EDPB Guidelines 05/2020 on Consent
Key requirements and how Consenti meets them
| Requirement | Implementation |
|---|---|
| Freely given | No content gating; overlay opacity defaults to 0 |
| Specific | Per-cookie granularity — each cookie has its own consent entry in consentJson |
| Informed | htmlText on categories, legitimateInterest.description for LI basis |
| Unambiguous | No pre-ticked boxes; all non-mandatory cookies default to 'denied' |
| Easy to withdraw | DELETE /consenti/api/v1/consent/:visitorId (same prominence as granting) |
| Records kept | Immutable consent_history table; audit_logs for admin actions |
Right to erasure (Article 17)
http
DELETE /consenti/api/v1/consent/:visitorIdThis deletes:
- All entries in
consent_recordsfor the visitor ID - All entries in
consent_historyfor the visitor ID - The
visitorsrecord (IP hash, UA hash, geolocation)
The visitor ID itself is a random UUID and contains no PII.
Data minimisation (Article 5(1)(c))
- IP addresses are stored as SHA-256 hashes only — the raw IP is never persisted
- User agents are stored as SHA-256 hashes only
- Consent records contain only: visitor UUID, profile ID, consent choices, timestamp, source
Consent records as evidence
Every consent record includes:
profile_version— which version of the cookie policy the user consented tocreated_at/updated_at— exact ISO 8601 timestampssource—'banner','api', or'import'consent_history— immutable append-only log of every change
Legitimate Interest (Article 6(1)(f))
Configure categories with type: 'legitimate_interest' in your profile:
json
{
"id": "ad_personalization",
"type": "legitimate_interest",
"legitimateInterest": {
"enabled": true,
"description": "We show relevant ads under legitimate interest."
}
}Status values for LI cookies:
"granted"— user did not object"objected"— user exercised their right to object (GDPR Art. 21)
ℹ️The
'objected' status is only valid for type: 'legitimate_interest' cookies. The server rejects 'objected' for standard consent cookies.Re-consent on profile version bump
When you update a profile (e.g. adding new cookies), the version field increments. The widget's verify endpoint returns { valid: false, reasons: ['profile_version_mismatch'] }for consents given under an older version, triggering the banner to show again.
Banner requirements
⚠️Under GDPR, the "Reject Optional" option must be as prominent as "Accept All". Do not use dark patterns such as grey-out reject buttons or hiding the reject option behind extra clicks. Consenti's default profile is compliant, but custom profiles are your responsibility.
- Do not set
overlayOpacityabove 0 if users can't access site content without consenting - Always provide a way to withdraw consent (use
CookieTriggerorwidget.showModal()from a footer link) - Mandatory cookies must be truly necessary — don't mark analytics as mandatory