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#

il quadro
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.

cookie.jsJavaScript
// 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.

pagina.htmlHTML
<!-- 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#

self-hosting dei font
# 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.
Una volta sola. Da quel momento non c'è più niente da dichiarare, da consentire o da difendere — e la pagina carica anche più in fretta, perché 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#

csp.jsJavaScript
// 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.

controllo rapido
# 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#

consenso.jsJavaScript
// 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 tecnicaConsenso?Cosa comporta
Font ospitati in proprionouna volta sola, e più veloce
Font da dominio esternobanner, informativa, precedente giudiziario a sfavore
Librerie dal proprio dominionoun file in più da aggiornare
Librerie da CDN pubblicaIP a terzi a ogni caricamento
Mappa statica + collegamentononessuna interazione dentro la pagina
Mappa incorporataiframe da bloccare fino al consenso
Video: anteprima locale + clical clicl'utente sceglie consapevolmente
Video incorporato direttamentecontatta il fornitore al caricamento
Log del server per sicurezzanolegittimo interesse, da dichiarare nell'informativa
Statistiche di terze partisalvo 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.