I banner dei cookie sono ovunque e sono quasi sempre fatti male. Ma dietro il fastidio c'è una sostanza precisa, e capirla permette di stare in regola facendo meno lavoro, non di più: la conformità più solida non si ottiene aggiungendo un banner, si ottiene togliendo le dipendenze che lo rendevano necessario.
Due norme, non una#
Due norme diverse, spesso confuse in una sola: ePrivacy (Dir. 2002/58/CE, art. 5.3 — in Italia art. 122 Codice Privacy) → riguarda l'ARCHIVIAZIONE o l'ACCESSO a informazioni sul terminale dell'utente. Cookie, localStorage, IndexedDB, cache API, identificatori di dispositivo. Serve il consenso, con due eccezioni: a) trasmissione della comunicazione b) strettamente necessario a un servizio CHIESTO DALL'UTENTE GDPR (Reg. UE 2016/679) → riguarda il TRATTAMENTO di dati personali, cookie o non cookie. L'indirizzo IP è un dato personale. Trasferirlo a un terzo è un trattamento, e richiede una base giuridica.Conseguenza che sorprende sempre: si può violare il GDPR SENZA usareun solo cookie. È esattamente il caso dei font caricati da un dominioesterno.La confusione fra le due è all'origine di quasi tutti gli errori. «Non usiamo cookie, quindi siamo a posto» è un ragionamento che tiene sotto ePrivacy e non tiene affatto sotto il GDPR: se la vostra pagina fa in modo che il browser del visitatore contatti un server di un'altra società, avete trasmesso a quella società l'indirizzo IP di una persona. È un trattamento di dati personali, e serve una base giuridica.
Quali cookie richiedono il consenso#
// La distinzione operativa non è "tecnico vs profilazione": è// "strettamente necessario al servizio CHIESTO DALL'UTENTE" o no.// ✓ Non richiedono consensores.cookie('sessione', id, { httpOnly: true, secure: true, sameSite: 'lax' });res.cookie('carrello', token, { httpOnly: true, secure: true });res.cookie('csrf', gettone, { secure: true, sameSite: 'strict' });res.cookie('lingua', 'it', { maxAge: ANNO }); // scelta dell'utente// (e il cookie che ricorda il rifiuto del banner: senza, il banner// ricomparirebbe a ogni pagina, il che è esso stesso un problema)// ✗ Richiedono consenso PREVENTIVO, prima di essere scrittires.cookie('_ga', ...); // statistiche, anche se "anonime"res.cookie('_fbp', ...); // pubblicitàres.cookie('ab_test', ...); // test A/B: non è chiesto dall'utenteres.cookie('heatmap_sid', ...); // registrazione della sessione// La zona grigia: le statistiche. Il Garante italiano ammette senza// consenso l'analytics con IP mascherato, nessun incrocio con altre// fonti e nessuna condivisione con terzi — condizioni che quasi nessuna// configurazione predefinita rispetta.Il criterio non è la tecnologia ma la finalità, e la formula della direttiva è più stretta di come viene di solito riassunta: strettamente necessario a fornire un servizio esplicitamente richiesto dall'utente. Un test A/B è tecnico quanto un cookie di sessione, ma nessun utente ha chiesto di partecipare a un esperimento: richiede consenso.
Il tracciamento che non passa dai cookie#
<!-- Nessuno di questi scrive un cookie. Tutti trasferiscono l'IP del visitatore a un terzo PRIMA che l'utente abbia scelto qualcosa. --><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter"><script src="https://cdn.jsdelivr.net/npm/chart.js"></script><iframe src="https://www.youtube.com/embed/xxxxxxx"></iframe><iframe src="https://www.google.com/maps/embed?pb=..."></iframe><img src="https://www.gravatar.com/avatar/9f2c..."><!-- Il caso dei font è quello che ha fatto giurisprudenza: nel gennaio 2022 il Tribunale di Monaco (3 O 17493/20) ha condannato il gestore di un sito al risarcimento per aver trasmesso l'IP di un visitatore a Google tramite Google Fonts, senza consenso — pur non essendoci alcun cookie coinvolto. -->Nessuna di queste righe scrive un cookie. Tutte fanno sì che il browser del visitatore apra una connessione verso un server di un'altra società, comunicandogli — perché è come funziona HTTP — l'indirizzo IP, la pagina di provenienza tramite Referer, e le caratteristiche del browser.
Il caso dei font è quello che ha fatto giurisprudenza: nel gennaio 2022 il Tribunale di Monaco ha condannato il gestore di un sito a risarcire un visitatore per aver trasmesso il suo indirizzo IP a Google attraverso Google Fonts, senza consenso. La cifra era simbolica; il precedente no, e ha generato in Germania un'ondata di richieste analoghe.
La soluzione tecnica: portare tutto in casa#
# Portare i font in casa: una volta, e il problema non esiste più.# 1. Si scarica il CSS chiedendolo come farebbe un browser modernocurl -sH 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) Firefox/128.0' \> 'https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;700&display=swap' \> -o fonts.css# 2. Si scaricano i woff2 a cui puntagrep -o 'https://[^)]*\.woff2' fonts.css | sort -u | while read u; do> curl -sO "$u"> done# 3. Si riscrivono gli URL sui percorsi localised -i 's|https://fonts.gstatic.com/[^)]*/|/fonts/|g' fonts.css# Risultato: zero richieste a domini esterni, zero IP trasferiti,# e un caricamento piu' veloce perche' sparisce una connessione TLS# verso un altro host.Lo stesso vale per il resto delle dipendenze esterne: le librerie JavaScript si servono dal proprio dominio invece che da una CDN pubblica; le mappe si sostituiscono con un'immagine statica e un collegamento, o con un fornitore che si può ospitare; i video incorporati si caricano solo dopo un clic esplicito, con un'anteprima locale al posto dell'iframe.
Verificare invece di sperare#
// Verificare invece di sperare: una Content-Security-Policy che consente// solo il proprio dominio trasforma ogni dipendenza esterna dimenticata// in un errore visibile in console, invece che in una violazione silenziosa.app.use((req, res, next) => { res.setHeader('Content-Security-Policy', [ "default-src 'self'", "img-src 'self' data:", "style-src 'self'", "font-src 'self'", "script-src 'self'", "connect-src 'self'", "frame-src 'none'", // niente iframe di terzi "base-uri 'self'", "form-action 'self'" ].join('; ')); next();});// In fase di introduzione, per non rompere niente:// Content-Security-Policy-Report-Only: ...; report-uri /api/csp// Si raccolgono le violazioni per una settimana, si sistema, poi si// passa alla versione che blocca davvero.Una Content-Security-Policy che consente solo il proprio dominio è il controllo continuo che nessuna revisione manuale può garantire. Il giorno in cui qualcuno incolla nel template un widget con un tag <script> verso un dominio esterno, la richiesta viene bloccata dal browser e compare un errore in console — invece di funzionare in silenzio per otto mesi.
# Che cosa contatta davvero il vostro sito: la verifica che vale# piu' di qualunque dichiarazione. Nel pannello Rete del browser,# oppure senza browser:curl -s https://esempio.it | grep -oE '(src|href)="https?://[^"]+"' \> | grep -v 'esempio\.it' | sort -u# (nessuna riga = nessuna risorsa da domini esterni nell'HTML)# Attenzione: questo non vede le richieste generate da JavaScript.# Per quelle serve il pannello Rete, filtrando per dominio, oppure# una CSP in modalita' report che le denuncia da sola.Se il banner serve davvero#
// Se i cookie non necessari SERVONO davvero, il banner ha requisiti// precisi. Le tre violazioni più diffuse://// ✗ Nessun pulsante "Rifiuta" al primo livello, o meno visibile di// "Accetta". Il rifiuto deve costare quanto l'accettazione.// ✗ Script di terze parti caricati PRIMA della scelta. Il consenso è// preventivo: se lo script è già partito, il banner è decorativo.// ✗ Scorrimento della pagina o chiusura con la X interpretati come// consenso. Il consenso deve essere un atto positivo inequivocabile.// L'implementazione corretta non carica nulla finché non c'è la scelta:function abilitaStatistiche() { if (localStorage.getItem('consenso.statistiche') !== 'si') return; const s = document.createElement('script'); s.src = '/vendor/analytics.js'; document.head.appendChild(s);}// E deve esistere un modo per CAMBIARE IDEA in ogni momento, non solo// per accettare: un collegamento permanente nel piè di pagina.Le tre violazioni elencate sono anche le tre più contestate dalle autorità europee. La terza merita una precisazione perché è controintuitiva: continuare a navigare non è consenso. Il GDPR richiede un atto positivo inequivocabile, e lo scorrimento della pagina non lo è — così come non lo è la chiusura del banner con la X, che semmai equivale a un rifiuto.
| Scelta tecnica | Consenso? | Cosa comporta |
|---|---|---|
| Font ospitati in proprio | no | una volta sola, e più veloce |
| Font da dominio esterno | sì | banner, informativa, precedente giudiziario a sfavore |
| Librerie dal proprio dominio | no | un file in più da aggiornare |
| Librerie da CDN pubblica | sì | IP a terzi a ogni caricamento |
| Mappa statica + collegamento | no | nessuna interazione dentro la pagina |
| Mappa incorporata | sì | iframe da bloccare fino al consenso |
| Video: anteprima locale + clic | al clic | l'utente sceglie consapevolmente |
| Video incorporato direttamente | sì | contatta il fornitore al caricamento |
| Log del server per sicurezza | no | legittimo interesse, da dichiarare nell'informativa |
| Statistiche di terze parti | sì | salvo le condizioni di esenzione, raramente rispettate |
L'informativa#
Resta obbligatoria anche senza cookie e senza terze parti: qualunque sito tratta almeno i dati di navigazione nei log del server, e chi ha un modulo di contatto tratta ciò che vi viene scritto. Ma un'informativa aderente a un sito che non traccia nulla è breve, e la sua brevità è essa stessa un'informazione per chi la legge.
Quello che deve contenere: chi è il titolare e come contattarlo; quali dati, per quali finalità e con quale base giuridica; per quanto tempo sono conservati; a chi vengono comunicati (idealmente: a nessuno); i diritti degli articoli 15-22 e come esercitarli. Un modello generico copiato altrove che elenca trattamenti inesistenti è peggio che inutile: dichiara di fare cose che non fate, e in caso di verifica è la prima incongruenza che salta all'occhio.