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.Related documentation