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.
| Scenario | api.enabled | compliance.type | How it resolves |
|---|---|---|---|
| 1A | false | 'auto' | Browser timezone + navigator.language → compliance group → pre-built profile |
| 1B | false | fixed group ID | Loads the matching pre-built profile directly — no geo-detection at all |
| 2A | true | '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:
Intl.DateTimeFormat().resolvedOptions().timeZone— e.g.Europe/Parisnavigator.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).
// 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 }
})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:
GET /consenti/api/v1/resolve-profile?tz=Europe%2FParis&lang=fr-FR&locale=fr-FRThe backend responds with:
{
"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.
// Scenario 2A — server geo-resolves the compliance group
new ConsentiSetup({
api: {
enabled: true,
baseUrl: 'https://consent.example.com',
},
compliance: { type: 'auto' },
})/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 ID | Region / Law | Model | GPC default |
|---|---|---|---|
| opt-in | EU / EEA — GDPR | Opt-in | honor |
| opt-out | California — CCPA | Opt-out | honor |
| opt-out-strict | California — CPRA | Strict opt-out | strict |
| opt-in-dpdpa | India — DPDPA | Opt-in | honor |
| opt-in-china | China — PIPL | Opt-in | ignore |
| opt-in-brazil | Brazil — LGPD | Opt-in | honor |
| general-privacy-consent | Global / general | Opt-in | honor |
| notice-only | Informational | Notice | ignore |