Consent & preference infrastructure

The consent layer your product plugs into.

Capture, version, prove and revoke consent and preferences — cookies included — through one API. An append-only vault, signed offline-verifiable receipts, and every event kept in the EU.

EU data residency IAB TCF v2.2 Google Consent Mode v2 Ed25519 signed receipts ISO/IEC 29184
Why not build it in-house

Consent is a data problem that never stops moving.

Proof, not just a boolean

A regulator asks what exactly did the user see, and when? That means an immutable record with the statement version, IP, timestamp — and a signature anyone can verify offline.

The framework keeps changing

GDPR, ePrivacy, LOPDGDD, CCPA, TCF revisions. Hard-coding any of it means a migration every time. Rules belong in data, evaluated at request time.

Cookies are their own project

Scanning a site, classifying every tracker, keeping it current. Cookiebot spent a decade on the classification database alone.

The vault

Append-only, with a signed receipt for every decision.

ConsentRecord rows are never updated — a change is a new row that supersedes the last. A materialized projection serves the hot read; the log is the truth.

  • Ed25519 detached signatures, public JWKS, verify offline
  • IP encrypted at rest, statement-hash in the proof
  • Full timeline + one-click subject export
POST /v1/consent → 201
state GRANTED
purposeVersion 3
supersedesId rec_8a1…
receiptId rcpt_9f2c…
proof.statementHash b7e4…
Definitions

Versioned statements and a configurable preference center.

Publish a purpose version as DISPLAY_ONLY (notify) or RECONSENT_REQUIRED (treat prior consent as stale). Channels × topics, typed fields, JSON-logic dependency rules.

  • Multi-locale legal text, frozen per version
  • Your banner renders from GET /v1/purposes
  • Expiry windows & bulk reconsent campaigns
purpose · marketing_email
v1 superseded
v2 superseded
v3 · published RECONSENT_REQUIRED
v4 draft
Cookie scanner

Cascade classification: reference DB → heuristics → AI.

The first confident tier wins. Unknowns go to a per-site review queue; a confirmed classification promoted across tenants becomes a tier-1 hit for everyone.

  • Human override is authoritative for that site
  • Shared definition set grows with every review
  • GET /v1/cookies for the banner table
_ga DB · analytics
_fbp heuristic · marketing
__stripe_mid DB · necessary
xq7_pref AI 44% → review
Signals

TCF v2.2 and Consent Mode v2 — derived, not implemented.

Ask for a TC string or a gtag('consent','update', …) object built from the subject's current state. The SDK's tag gate loads your scripts on grant and re-evaluates on change.

  • GET /v1/consent/tcstring
  • GET /v1/consent/google-consent-mode
  • Signed webhooks on every change, with retry + replay
google-consent-mode
ad_storage granted
analytics_storage denied
ad_user_data granted
security_storage granted
How we compare

OneTrust's power, an API's simplicity.

OneTrust · CookiebotTripticonsent
ModelA suite your team runsAn API you plug into
Proof of consentA record in their systemAppend-only vault + Ed25519 signed receipt
Regulatory frameworkTemplate configurationRuleSet in data (JSON-logic), no migrations
CookiesScanner + proprietary DBCascade DB → heuristics → AI + shared DB
TCF / Consent ModeA separate moduleDerived from the subject's state, one endpoint
ResidencyPlan-dependentAlways EU (Vercel fra1 · Neon eu-central)
IntegrationTags + portalnpm i @tripticonsent/sdk

Indicative comparison. Not affiliated with OneTrust or Cookiebot.

Built for developers

Ten lines, then it's just an API.

  • Browser + Node SDK, or plain REST
  • In-memory cache with ETag revalidation
  • Idempotency-Key on every mutation
  • Offline receipt verification built in
import { TripticonsentClient } from '@tripticonsent/sdk';

const tc = new TripticonsentClient({ baseUrl: API_URL, apiKey: 'pk_live_…' });

await tc.recordConsent(
  { subject: 'email:user@example.com', purpose: 'marketing_email', state: 'GRANTED' },
  { idempotencyKey: crypto.randomUUID() },
);

// load analytics only after consent
await tc.gate('email:user@example.com', ['analytics'], () => loadAnalytics());

Plug in the consent layer.

One vault, one source of truth, in the EU. Wire up your banner in an afternoon.