Consenti

How Auto-Detection Works

Consenti can automatically show the right banner for each visitor's jurisdiction — GDPR for EU visitors, CCPA for Californians, LGPD for Brazilians — without you writing any geo-detection code. This guide explains the three resolution scenarios and when to use each.

The three scenarios

Which scenario runs depends on two settings: whether api.enabled is true, and what compliance.type is set to.

Scenarioapi.enabledcompliance.typeHow it resolves
1Afalse'auto'Browser timezone + navigator.language → compliance group → pre-built profile
1Bfalsefixed group IDLoads the matching pre-built profile directly — no geo-detection at all
2Atrue'auto'GET /resolve-profile?tz&lang&locale → backend geo-resolves → returns profile URL

Scenario 1A — Client-side auto (no backend)

This is the default when you omit the api config entirely. The widget reads two browser signals:

  1. Intl.DateTimeFormat().resolvedOptions().timeZone — e.g. Europe/Paris
  2. navigator.language — e.g. fr-FR

These are matched against an embedded 195-country map to derive a compliance group. A visitor with timezone Europe/Paris gets the opt-in (GDPR) group. A visitor with timezone America/Los_Angeles gets opt-out (CCPA).

typescript
// Scenario 1A — fully client-side, zero network calls except the profile chunk
new ConsentiSetup({
  // compliance.type defaults to 'auto' when omitted
  // api defaults to { enabled: false }
})
⚠️Timezone detection is a heuristic. A visitor using a VPN or travelling internationally may trigger the wrong compliance group. For higher accuracy, use Scenario 2A with a server-side geo resolver.

Scenario 1B — Fixed compliance group

When you want the same regulation for every visitor (e.g. you only serve EU users, or you want to apply GDPR globally as the strictest baseline), set compliance.type to a specific group ID. No geo-detection happens at all.

new ConsentiSetup({ compliance: { type: 'opt-in' } })

Scenario 2A — Server-side geo-resolution

When you have a Consenti backend running, the widget delegates geo-resolution entirely to the server. This is more accurate because your backend can use real IP geolocation (MaxMind, geoip-lite, ipinfo.io) rather than relying on timezone heuristics.

On page load the widget sends one request:

text
GET /consenti/api/v1/resolve-profile?tz=Europe%2FParis&lang=fr-FR&locale=fr-FR

The backend responds with:

json
{
  "path": "/consenti/api/v1/profiles/default/opt-in/fr-FR",
  "resolvedLocale": "fr-FR",
  "resolvedComplianceGroup": "opt-in",
  "profileId": "gdpr-profile-uuid",
  "version": 3
}

The widget then fetches the profile JSON directly from the returned path. This second request is served from disk (zero DB) and is CDN-cacheable.

typescript
// Scenario 2A — server geo-resolves the compliance group
new ConsentiSetup({
  api: {
    enabled: true,
    baseUrl: 'https://consent.example.com',
  },
  compliance: { type: 'auto' },
})
💡The /resolve-profile response is cached in sessionStoragefor the tab's lifetime. Navigating between pages never re-fetches it.

The 8 built-in compliance groups

Group IDRegion / LawModelGPC default
opt-inEU / EEA — GDPROpt-inhonor
opt-outCalifornia — CCPAOpt-outhonor
opt-out-strictCalifornia — CPRAStrict opt-outstrict
opt-in-dpdpaIndia — DPDPAOpt-inhonor
opt-in-chinaChina — PIPLOpt-inignore
opt-in-brazilBrazil — LGPDOpt-inhonor
general-privacy-consentGlobal / generalOpt-inhonor
notice-onlyInformationalNoticeignore

Frequently asked questions