Safeguard
Security Guides•

Consent logging: which fields to store as proof of consent

What a consent log should store to prove consent under GDPR: who, when, the exact text and version, how, and any withdrawal. Includes a sample schema.

Safeguard Security Team
3 min read

To prove consent, log who consented, when, the exact wording and version they saw, how they gave it, the purposes covered, and any later withdrawal. GDPR Article 7 says a controller must be able to demonstrate that consent was given, so a boolean column on the user table is not enough.

What the regulator expects to see

Article 7(1) says "the controller shall be able to demonstrate that the data subject has consented." The UK Information Commissioner's guidance spells out the practical records: who consented, when, what they were told, how they consented, and whether and when they withdrew. It also says records should be as granular as the consent itself.

That points to an append-only event log, not a mutable flag.

A workable schema

One row per consent event:

  • event_id, a unique ID.
  • subject_id, the account or pseudonymous visitor ID.
  • purpose, one value per purpose, such as product_email or analytics.
  • action, either granted or withdrawn.
  • occurred_at, a UTC timestamp from the server.
  • text_version, a reference to the exact consent wording and linked privacy notice version.
  • channel, such as web form, mobile app or support agent entry.
  • ui_context, the form or screen identifier, so you can reproduce what the person saw.

Do not store more personal data than needed. The log itself is personal data, so avoid raw IP addresses and full user agent strings unless you have a clear reason.

Keep the wording versioned

If you cannot show what the person was told, a timestamp proves very little. Store each consent text and privacy notice version in version control or a table, with an effective date, and reference it from the event. When copy changes, create a new version. Never edit a published version in place.

Current state is derived

Compute the current state by reading the latest event per subject and purpose. Expose it through one function that every system calls. Do not copy the flag into five services, or withdrawal will reach only some of them.

Granularity and defaults

Record separate events for separate purposes. A single "I agree" that bundles marketing, analytics and sharing makes it hard to show that consent was specific. Also record unticked boxes by default: no event means no consent.

Retention of the log

Keep consent evidence for as long as you rely on the consent, as the ICO puts it. After that, delete or reduce it, but check whether you need a short suppression record, for example to avoid emailing someone who opted out.

Integrity

The ICO notes that online, a cryptographic hash can support integrity. Hash the event contents and chain or sign batches if you expect disputes. This is optional for small teams, helpful for regulated ones.

Quick check

Can I just store consent_given = true?

That shows a state, not proof of what the person saw or when. Keep dated events and the wording version.

Does consent logging apply when I rely on a contract?

No. It is needed where consent is your lawful basis. Other bases need other records.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.