Consenti

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

Key requirements and how Consenti meets them

RequirementImplementation
Freely givenNo content gating; overlay opacity defaults to 0
SpecificPer-cookie granularity — each cookie has its own consent entry in consentJson
InformedhtmlText on categories, legitimateInterest.description for LI basis
UnambiguousNo pre-ticked boxes; all non-mandatory cookies default to 'denied'
Easy to withdrawDELETE /consenti/api/v1/consent/:visitorId (same prominence as granting)
Records keptImmutable consent_history table; audit_logs for admin actions

Right to erasure (Article 17)

http
DELETE /consenti/api/v1/consent/:visitorId

This deletes:

  • All entries in consent_records for the visitor ID
  • All entries in consent_history for the visitor ID
  • The visitors record (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 to
  • created_at / updated_at — exact ISO 8601 timestamps
  • source'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 overlayOpacity above 0 if users can't access site content without consenting
  • Always provide a way to withdraw consent (use CookieTrigger or widget.showModal() from a footer link)
  • Mandatory cookies must be truly necessary — don't mark analytics as mandatory