Consenti

Multi-Region Marketing Site — GDPR + CCPA Geo-Routing

One marketing site, visitors from the EU and California, two very different legal defaults — opt-in for the EU, opt-out for CCPA. A single widget snippet ships to every visitor; the backend decides which profile applies.

What this demonstrates

  • compliance: { type: 'auto' } — the widget doesn't hardcode a region
  • Two profiles managed independently in the dashboard, one per compliance group
  • A geo resolver that maps country → compliance group without a network call per request

1. Backend — enable auto-detection

server.ts
ts
import { createConsenti } from '@consenti/api'
import http from 'node:http'

const consenti = createConsenti({
  storage: { driver: 'postgresql', uri: process.env.DATABASE_URL, path: './consenti-data' },
  auth: {
    mode: 'local',
    adminEmail: '[email protected]',
    adminPassword: process.env.CONSENTI_ADMIN_PASSWORD!,
  },
  dashboard: true,
})

http.createServer(consenti.handler).listen(3001)

geoDataProvider defaults to a free timezone + Accept-Language heuristic — no extra install needed to get started. For higher accuracy, install geoip-lite and switch drivers:

ts
// npm install geoip-lite
createConsenti({
  // ...
  compliance: { type: 'auto', geoDataProvider: 'geoip' },
})

2. Dashboard — one profile per group

In Profiles, create two profiles from the built-in templates:

  • EU / GDPR — opt-in type, banner defaults to Reject Optional being just as prominent as Accept All
  • US / CCPA — opt-out type, banner defaults to cookies running until the visitor opts out via Do Not Sell or Share My Personal Information

Activate both. The backend's geo-resolution pipeline picks the right one per visitor — no code change needed when you add a third region later (say, LGPD for Brazil).

3. Frontend — one snippet for every visitor

components/ConsentSetup.tsx
tsx
'use client'
import { useEffect } from 'react'
import { ConsentiSetup } from '@consenti/ui'

export function ConsentSetup() {
  useEffect(() => {
    const widget = new ConsentiSetup({
      api: { enabled: true, baseUrl: 'https://your-site.com' },
      // No compliance.type set — resolved per visitor by the backend
    })
    return () => widget.destroy()
  }, [])
  return null
}
⚠️Trusting a proxy's IP header (Cloudflare, an ALB) requires trustedProxies to be configured — otherwise geo-resolution falls back to timezone/locale only. See trustedProxies in API Advanced Configuration.