✅ BenefitsDigital MarketingIntermediate✨ AI-assisted

Benefits of Consent Logs for AI-Driven Marketing Campaigns

WittyTech Daily··5 min read
#gdpr#consent-logs#marketing-compliance#postgresql

A boolean column called opted_in can't answer the question a regulator will ask: show me. Marketing consent logs can. Below are five benefits of keeping one, plus a minimal schema and an audience query. It's written for teams whose AI tools build audiences and personalize sends faster than anyone can review them.

What marketing consent logs record

GDPR Article 7(1) says the controller must be able to demonstrate that the person consented. The ICO's guidance on recording consent spells out what to keep: who consented, when, what they were told, and how. A consent log is an append-only table holding exactly that, one row per grant or withdrawal.

CREATE TABLE consent_events (
  event_id       uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  subject_id     text        NOT NULL,   -- your customer or contact ID
  purpose        text        NOT NULL,   -- e.g. email_marketing, ai_personalization
  action         text        NOT NULL CHECK (action IN ('granted', 'withdrawn')),
  occurred_at    timestamptz NOT NULL DEFAULT now(),
  channel        text        NOT NULL,   -- web_form, unsubscribe_link, preference_centre, support_ticket
  notice_version text        NOT NULL,   -- ID of the exact consent wording shown
  evidence       jsonb                   -- form ID, submission ID, session ID
);

CREATE INDEX consent_events_latest
  ON consent_events (subject_id, purpose, occurred_at DESC);

Never update or delete rows. A withdrawal is a new row, so the history survives. notice_version points at a stored copy of the wording the person saw, which covers the "what they were told" part. gen_random_uuid() is built in from PostgreSQL 13.

Benefit 1: Proof of consent in an audit

A complaint lands about a personalized offer. With a log, one query returns the evidence:

SELECT action, purpose, occurred_at, channel, notice_version
FROM consent_events
WHERE subject_id = 'cust_48213'
  AND purpose = 'email_marketing'
ORDER BY occurred_at;

With a flag, you have a shrug. The burden sits on you under Article 7(1), so a missing record means you cannot demonstrate consent. The ICO says to keep records for as long as you are still processing based on that consent.

Benefit 2: Consent withdrawal automation before the next send

Article 7(3) says withdrawing must be as easy as giving consent, and the ICO expects you to stop consent-based processing promptly. AI workflows make that hard. An audience is built overnight, copy is generated, and sends are queued for the morning. Someone who unsubscribes at breakfast is already inside the 10:00 batch.

The fix is to write a withdrawn row from every channel (unsubscribe link, preference centre, support ticket) and re-check consent at send time, not at audience-build time.

import psycopg

def still_consented(conn: psycopg.Connection, subject_ids: list[str], purpose: str) -> set[str]:
    rows = conn.execute(
        'SELECT subject_id FROM current_consent '
        'WHERE purpose = %s AND action = %s AND subject_id = ANY(%s)',
        (purpose, 'granted', subject_ids),
    ).fetchall()
    return {r[0] for r in rows}

def send_batch(conn, batch, purpose='email_marketing'):
    ok = still_consented(conn, [m['subject_id'] for m in batch], purpose)
    for message in batch:
        if message['subject_id'] in ok:
            deliver(message)  # your ESP call

The gate reads the same log the unsubscribe link writes, so the gap between "no" and "stop" is one query. The current_consent view is defined in the next section.

Benefit 3: Audience filtering in code with an audience suppression list

A view reduces the log to each person's latest decision per purpose. The audience query then joins against it.

CREATE VIEW current_consent AS
SELECT DISTINCT ON (subject_id, purpose)
       subject_id, purpose, action, occurred_at
FROM consent_events
ORDER BY subject_id, purpose, occurred_at DESC;

SELECT a.subject_id, a.segment
FROM campaign_audience a
JOIN current_consent c
  ON c.subject_id = a.subject_id
 AND c.purpose = 'email_marketing'
WHERE c.action = 'granted';

The inner join drops people who withdrew and people who never consented, so a missing row fails safe. Consent is tied to a purpose, so a grant for email_marketing doesn't cover ai_personalization. Log them as separate purposes.

The withdrawn rows double as your suppression list. The ICO advises keeping people who opted out on a suppression list rather than deleting them, holding only the minimum needed to respect their preference.

Benefit 4: Faster answers from your GDPR consent records

Access requests have a clock. Article 12(3) gives one month, extendable by two further months for complex or numerous requests. Without a log, rebuilding someone's consent history means digging through CRM exports, ESP dashboards and form-builder archives. With one, the consent half of the answer is a query:

SELECT json_agg(e ORDER BY e.occurred_at)
FROM consent_events e
WHERE e.subject_id = 'cust_48213';

You get every grant and withdrawal, with channel and notice version, as JSON you can hand to whoever assembles the response.

Benefit 5: Less spend on people who said no

Every message to someone who withdrew costs a delivery fee and risks a spam complaint. It may also feed a personalization model an audience that should not contain them. I found no trustworthy industry benchmark for the saving, so measure your own:

SELECT count(*) AS withdrawn_in_audience
FROM audience_export e
JOIN current_consent c
  ON c.subject_id = e.subject_id
 AND c.purpose = 'email_marketing'
WHERE c.action = 'withdrawn';

If the count is above zero, you have found the leak.

When a full consent log is overkill

Purely transactional messages (receipts, password resets, shipping updates) don't depend on marketing consent, so a full grant-and-withdraw history buys you little there. Even then, keep a suppression list, because people can object to direct marketing at any time under Article 21. Before dropping the log for marketing, check with your DPO or counsel. Email and SMS marketing rules often require consent regardless of your GDPR lawful basis.

In production, a consent log turns a guess that someone opted in into a row you can show, which is what lets an AI campaign pipeline run unattended without messaging a person who already said no.

← More in Digital Marketing