feat(cmp): send extended consent data from ConsentBanner
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 35s
CI / test-python-voice (push) Successful in 34s
CI / test-bqas (push) Successful in 33s

Send consent_method, page_url, referrer, device_type, browser, os,
screen_resolution and consent_scope with each consent record for
vendor-agnostic compliance tracking.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-10 23:12:22 +02:00
parent d13f4511cb
commit 5f193c8a72
@@ -70,8 +70,25 @@ function getSavedConsent(): ConsentState | null {
return null return null
} }
async function sendConsent(consent: ConsentState) { function detectDevice(): { device_type: string; browser: string; os: string } {
const ua = navigator.userAgent
const device_type = /Mobi|Android/i.test(ua)
? (/Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile')
: 'desktop'
const browserMatch = ua.match(/(Chrome|Safari|Firefox|Edge|Opera|OPR)\/[\d.]+/)
const browser = browserMatch
? browserMatch[0].replace('OPR', 'Opera')
: 'Unknown'
const osMatch = ua.match(/(Windows NT [\d.]+|Mac OS X [\d_.]+|Linux|Android [\d.]+|iOS [\d._]+)/)
const os = osMatch ? osMatch[0].replace(/_/g, '.') : 'Unknown'
return { device_type, browser, os }
}
type ConsentMethod = 'accept_all' | 'reject_all' | 'custom_selection'
async function sendConsent(consent: ConsentState, method: ConsentMethod) {
try { try {
const { device_type, browser, os } = detectDevice()
await fetch('/api/consent', { await fetch('/api/consent', {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@@ -85,6 +102,14 @@ async function sendConsent(consent: ConsentState) {
], ],
vendors: [], vendors: [],
user_agent: navigator.userAgent, user_agent: navigator.userAgent,
consent_method: method,
page_url: window.location.href,
referrer: document.referrer || null,
device_type,
browser,
os,
screen_resolution: `${screen.width}x${screen.height}`,
consent_scope: 'domain',
}), }),
}) })
} catch { } catch {
@@ -106,16 +131,16 @@ export default function ConsentBanner() {
} }
}, []) }, [])
const save = useCallback((state: ConsentState) => { const save = useCallback((state: ConsentState, method: ConsentMethod) => {
localStorage.setItem(COOKIE_NAME, JSON.stringify(state)) localStorage.setItem(COOKIE_NAME, JSON.stringify(state))
sendConsent(state) sendConsent(state, method)
setVisible(false) setVisible(false)
window.dispatchEvent(new CustomEvent('consent-change', { detail: state })) window.dispatchEvent(new CustomEvent('consent-change', { detail: state }))
}, []) }, [])
const acceptAll = () => save({ essential: true, functional: true, analytics: true }) const acceptAll = () => save({ essential: true, functional: true, analytics: true }, 'accept_all')
const rejectAll = () => save({ essential: true, functional: false, analytics: false }) const rejectAll = () => save({ essential: true, functional: false, analytics: false }, 'reject_all')
const saveSelection = () => save(consent) const saveSelection = () => save(consent, 'custom_selection')
if (!visible) return null if (!visible) return null