feat(cmp): Phase 2 — send scripts_blocked, scripts_released, cookies_set

ConsentBanner detects loaded scripts (analytics/marketing) and cookies
after consent, sends them to the CMP backend for transparency tracking.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-11 22:52:41 +02:00
parent 519cc274bb
commit f6489e7748
@@ -86,9 +86,40 @@ function detectDevice(): { device_type: string; browser: string; os: string } {
type ConsentMethod = 'accept_all' | 'reject_all' | 'custom_selection'
interface ScriptEntry { src: string; category: string }
interface CookieEntry { name: string; domain: string; expiry_days: number; category: string }
function detectScripts(): { blocked: ScriptEntry[]; released: ScriptEntry[] } {
const scripts = Array.from(document.querySelectorAll('script[src]'))
const released: ScriptEntry[] = []
const blocked: ScriptEntry[] = []
for (const el of scripts) {
const src = el.getAttribute('src') || ''
if (/google.*tag|gtag|analytics/i.test(src)) released.push({ src, category: 'analytics' })
else if (/facebook|fbevents|linkedin|tiktok/i.test(src)) released.push({ src, category: 'marketing' })
}
return { blocked, released }
}
function detectCookies(): CookieEntry[] {
const cookies: CookieEntry[] = []
for (const c of document.cookie.split(';')) {
const name = c.trim().split('=')[0]
if (!name) continue
let category = 'functional'
if (/^_ga|^_gid|^_gat/i.test(name)) category = 'analytics'
else if (/^_fb|^_gcl|^_li/i.test(name)) category = 'marketing'
else if (/^bp_consent|^session|^csrf/i.test(name)) category = 'essential'
cookies.push({ name, domain: window.location.hostname, expiry_days: 0, category })
}
return cookies
}
async function sendConsent(consent: ConsentState, method: ConsentMethod) {
try {
const { device_type, browser, os } = detectDevice()
const { blocked, released } = detectScripts()
const cookies_set = detectCookies()
await fetch('/api/consent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -110,6 +141,9 @@ async function sendConsent(consent: ConsentState, method: ConsentMethod) {
os,
screen_resolution: `${screen.width}x${screen.height}`,
consent_scope: 'domain',
scripts_blocked: blocked,
scripts_released: released,
cookies_set,
}),
})
} catch {