GDPR Compliance
What Pactorio handles for you
| Requirement | Article | How Pactorio satisfies it |
|---|---|---|
| Consent must be freely given, specific, informed, and unambiguous | Art. 4(11) | Banner requires an active click to accept. Non-essential categories default to unchecked. No dark patterns. |
| No pre-ticked boxes | Art. 4(11), Rec. 32 | The Admin UI enforces defaultValue: false for all non-required categories. |
| Scripts must be blocked until consent | Art. 5(1)(a), Art. 6 | The snippet intercepts document.createElement before the page parses. Matching scripts are held until the user decides. |
| Withdrawal must be as easy as giving consent | Art. 7(3) | A "Cookie Preferences" link re-opens the banner at any time. Withdrawal immediately stops relevant scripts. |
| Proof of consent must be kept | Art. 7(1) | Every consent and withdrawal is recorded as an audit event in the database with a timestamp and decisions snapshot. |
| Right of access to consent record | Art. 15 | GET /v1/consent/history returns the full event log for a user token. |
| Right to erasure | Art. 17 | DELETE /v1/consent/permanent hard-deletes a consent record. Requires DPO API key. |
| Consent records must not include raw IP addresses | Art. 5(1)(c) data minimisation | Only a country code derived from Cloudflare's CF-IPCountry header is stored. The raw IP is never logged. |
Your obligations
Pactorio handles the technical mechanics of consent capture and script blocking. The following remain your responsibility:
- Writing a privacy and cookie policy. You must document what cookies you use, why, how long they last, and which third-party processors receive the data. Link to it from the banner.
- Keeping cookie categories accurate. If you add new analytics or marketing tools, update your categories and script rules accordingly.
- Maintaining a Data Processing Agreement (DPA) with any third-party processors (Google, Meta, etc.).
- Appointing a Data Protection Officer (DPO) if required by your organisation's size or processing activities.
- Handling data subject requests. If a user exercises their Art. 15 or Art. 17 rights by email, you must use the consent service API to fulfil the request.
Consent requirements
Granularity
GDPR requires separate consent for each purpose. Use distinct categories (e.g. "Analytics" and "Marketing") rather than a single "All cookies" toggle. Users must be able to accept analytics but reject marketing.
Essential cookies
Cookies strictly necessary for the site to function (session IDs, CSRF tokens, user preferences) do not require consent under GDPR Rec. 47. Set required: true on the "Essential" category — the toggle will be locked and always on.
Re-consent on config changes
When you save changes in the Admin UI, the config version number increments. Returning visitors whose stored consent is from an older version will be asked to consent again. This ensures re-consent is collected when you add new purposes.
Right to withdraw (Art. 7(3))
Users can withdraw consent at any time by clicking "Cookie Preferences" in your footer (or wherever you surface the link). This re-opens the banner's preferences panel.
When the user withdraws:
- The stored consent state is cleared from
localStorage. - A
DELETE /v1/consentrequest setswithdrawn_aton the consent record. - A
withdrawnevent is appended to the audit log. - The SDK fires a
cc:consentDOM event withdetail: nullso your code can react (e.g. unload analytics).
To re-open the preferences banner from your own code:
window.__cc.showBanner();
Right of access (Art. 15)
If a user requests a copy of their consent data, retrieve it via the consent service API using their cc_token cookie value:
GET /v1/consent/history?customerId=YOUR_ID&token=USER_TOKEN Response: { "events": [ { "event_type": "granted", "decisions": { "essential": true, "analytics": true }, "occurred_at": "2026-01-01T10:00:00Z" }, { "event_type": "withdrawn", "decisions": { ... }, "occurred_at": "2026-01-15T09:30:00Z" } ] }
The user's cc_token is stored in the cc_token first-party cookie on your domain. You can read it server-side to look up their history.
Right to erasure (Art. 17)
To permanently delete a user's consent record, use the DPO endpoint. This requires the X-Dpo-Api-Key header — keep this key secure and only use it in response to verified erasure requests.
DELETE /v1/consent/permanent?customerId=YOUR_ID&token=USER_TOKEN X-Dpo-Api-Key: your-dpo-key Response: { "ok": true, "erased": true }
This hard-deletes the consent record and all associated audit events from the database. The deletion itself is not logged (there is no record to attach a log entry to after deletion).
Audit trail
Every consent action creates an immutable event in the consent_events table:
| Event type | Triggered when |
|---|---|
granted | User accepts (or updates) their consent choices |
withdrawn | User withdraws all consent |
Each event records the full decisions snapshot, the timestamp, and the IP-derived country code. Events are retained for 3 years to satisfy Art. 7(1) accountability requirements, after which they are automatically purged.
Data retention
| Data | Retention period | Basis |
|---|---|---|
| Active consent records | 1 year from consent date | Consent expires; re-consent required annually |
| Withdrawn consent records | Flagged immediately; excluded from all processing | Art. 7(3) |
| Consent audit events | 3 years | Art. 7(1) accountability |
| IP-derived country code | With the consent record | Minimal; country only, not raw IP |