La mascotte orso polare di NordBastion, in piedi davanti a un leggio di pietra nordica intagliata, con sopra di essa una grande dashboard olografica ciano fluttuante che mostra grafici a barre, un grafico a linee in crescita e un anello a ciambella con un accento ambra, e un unico flusso ininterrotto di punti ciano luminosi che scorre da una finestra ad arco illuminata dall'aurora, attraverso la dashboard, fino a una porta di caveau runica, con un rack di server sul retro
Guida pratica · Analisi·18 min di lettura · 40 min pratici

Ha installato uno script per osservare i suoi lettori.
Osserva a sua volta, e riferisce altrove.

L'analisi è l'ultimo tag di terze parti che la maggior parte delle persone mantiene, ed è quello che vede tutto: ogni pagina, ogni lettore, ogni ora, su un sistema che non possiede e non può verificare. Sei passaggi per sostituirlo con un contatore proprio — Umami, Plausible Community Edition, Matomo oppure nient'altro che il log del server — in esecuzione su un server nordico noleggiato senza documento d'identità. Senza cookie per impostazione predefinita, nessun banner su cui discutere, nessun trasferimento del suo pubblico di lettori verso un paese terzo. Da $3.90 al mese. Testato su Debian 12.

I sei passaggi
  1. 01

    Scelta

    Quattro strumenti, una tabella onesta

  2. 02

    Provisioning

    Un sottodominio, tre porte

  3. 03

    Distribuisci

    Compose, Caddy, primo accesso

  4. 04

    Strumentazione

    Un tag, e il percorso first-party

  5. 05

    Conformità

    Due leggi, non una

  6. 06

    Keep

    Conservazione, backup, il log dimenticato

Prima di iniziare · Cos'è il tag

Non è un contatore. È una linea di reporting.

Contare i visitatori è davvero utile e non c'è nulla di sinistro nel volerlo fare. Deve sapere se la riscrittura ha aiutato, quale articolo le persone finiscono davvero di leggere, quale referrer manda lettori piuttosto che semplici rimbalzi, e se il deploy della notte scorsa ha silenziosamente rotto il checkout su un browser. Ognuna di queste domande trova risposta in una tabella di visualizzazioni di pagina, ed ognuna di esse è un motivo legittimo per misurare.

Ciò che vale la pena guardare in faccia è l'accordo che quasi tutti hanno accettato per ottenere queste risposte. Il tag di analisi standard è un pezzo di codice, scritto da un'azienda pubblicitaria, che inserisce in ogni pagina del suo sito e istruisce a essere eseguito nel browser del suo lettore. Legge l'indirizzo della pagina, il referrer, lo schermo, la lingua, il dispositivo; imposta o legge un identificatore sul dispositivo; invia tutto questo a un sistema che non può ispezionare, in un paese le cui regole non ha scelto; e consegna il file risultante a un'azienda i cui ricavi derivano dal sapere cosa fanno le persone. Il proprietario del sito ottiene una dashboard. La dashboard è la metà più piccola della transazione.

Il conto arriva in quattro rate, e solo una di esse è evidente. C'è il banner di consenso, che esiste quasi interamente a causa di questo unico tag, che le costa una quota misurabile di visitatori già all'ingresso, e che poi paga un secondo fornitore per gestire. C'è la questione del trasferimento, perché i dati dei suoi lettori partono verso un paese terzo e qualcuno alla fine deve scrivere perché ciò sia lecito. C'è il dato stesso, che è il suo pubblico di lettori, in un database che non può interrogare se non tramite i report che le vengono offerti. E c'è la dipendenza: il prodotto viene ritirato, rinominato o ristrutturato secondo il calendario di qualcun altro, e l'ultima volta che è accaduto le vecchie misurazioni sono andate perse insieme ad esso.

Il self-hosting li elimina tutti e quattro in una volta, e non è un lavoro impegnativo. Il software è maturo, gratuito e senza sorprese; il server costa pochi dollari al mese; il lavoro è di una serata. Quello che riottiene è una tabella di sua proprietà, su hardware in una giurisdizione che ha scelto, senza terze parti da dichiarare e — per la maggior parte delle configurazioni — nessun banner su cui discutere. Quattro modi per sapere quante persone leggono il suo sito, e quanto costa ciascuno di essi:

Proprietà Il grande tag di analisi gratuito Un SaaS di analisi orientato alla privacy Lo stesso software, il suo VPS
Chi detiene la tabella del pubblico di lettoriUn'azienda pubblicitariaUn fornitore, sotto contrattoLei, su disco
Banner di consenso necessarioSì, in pratica sempreDi solito noDi solito no — veda il passo 05
I dati escono dallo SEESì, per progettazioneDipende dal fornitoreSolo se sceglie un server al di fuori di esso
Terze parti da dichiarareAlmeno uno, più i suoi sub-responsabili del trattamentoUn solo responsabile del trattamentoNessuno
Bloccato dalle liste di filtriPesantementePer nome host, spessoRaramente, una volta che è first-party
Dati grezzi a sua disposizioneNo — solo reportTramite un'API, mentre pagaÈ il suo database
Costo mensile a 100k visualizzazioniNulla in denaroDecine di dollari, in aumento con il traffico$3.90–$7.90, fisso
Lo scelga quandoHa bisogno dell'integrazione con la piattaforma pubblicitaria e accetta il restoVuole l'etica senza gestire nullaIl pubblico di lettori è suo, e così anche la tabella

La terza colonna è una risposta reale, non un uomo di paglia: un fornitore ospitato orientato alla privacy elimina la maggior parte degli stessi problemi per le persone che non dovrebbero gestire server, e pagarne uno è un risultato migliore che mantenere il tag pubblicitario. Questa guida è per il caso in cui noleggia già un server, o aveva intenzione di farlo.

Passo 01 · Scelta

Quattro strumenti. Il database determina il conto.

Questi quattro non sono quattro varianti della stessa cosa. Differiscono in ciò in cui memorizzano i dati, e questa unica scelta determina l'impronta di memoria, la crescita del disco, il rischio di aggiornamento e la profondità dei report. Legga prima la colonna dell'archiviazione e poi quella delle funzionalità; è l'ordine in cui la decisione viene effettivamente presa.

Strumento Stack e archiviazione Livello ragionevole Lo scelga per
UmamiApplicazione Node + PostgreSQL o MySQL. Due container.Sentinel · $3.90La risposta predefinita. Leggero, leggibile, senza cookie, multi-sito, con licenza MIT.
Plausible Community EditionApplicazione Elixir + PostgreSQL + ClickHouse. Quattro container.Garrison · $7.90Obiettivi, funnel e dashboard pubbliche; query rapide su grandi volumi.
MatomoApplicazione PHP + MariaDB, più un job di archiviazione pianificato.Garrison · $7.90Parità di funzionalità con lo strumento dominante — segmenti, coorti, e-commerce, importazione dei log.
GoAccessUn unico binario che legge il log degli accessi del server web. Nessun database.Qualunque cosa già utilizziNessun JavaScript — siti statici, documentazione, API.

Umami è quello da scegliere a meno che non abbia un motivo per non farlo. È un'applicazione Node su un unico database relazionale, si accontenta di un gigabyte di memoria, lo schema è una manciata di tabelle che può interrogare lei stesso, e i report coprono ciò per cui la maggior parte delle persone apre una dashboard: pagine, referrer, paesi, dispositivi, più eventi personalizzati quando li desidera. È senza cookie per impostazione predefinita e non le chiede di configurarlo.

Plausible Community Edition è la versione self-hostable del prodotto ospitato, e il pezzo aggiuntivo è ClickHouse — un column store che rende le query aggregate su decine di milioni di righe praticamente istantanee, e che userà tutta la memoria che gli lascia usare. È un compromesso equo sopra qualche milione di visualizzazioni mensili, e uno strano sotto quella soglia. Legga i termini di licenza del progetto prima di distribuirlo: l'edizione community è pensata per gestire la propria analisi, non per essere rivenduta come servizio.

Matomo è il solo dei quattro a sostituire davvero lo strumento dominante funzione per funzione, e l'onestà di questa affermazione vale in entrambe le direzioni: si ottengono segmenti, funnel, coorti, attribuzione e-commerce, heatmap tramite plugin e la possibilità di importare i propri log del server, ma si ottiene anche un'ampia applicazione PHP le cui tabelle grezze crescono rapidamente e i cui report sono precalcolati da un job di archiviazione che deve pianificare lei stesso. Due elementi lo rendono comunque degno di attenzione: può essere configurato per non impostare alcun cookie, e configurazioni di misurazione dell'audience basate su di esso sono apparse negli elenchi pubblicati dai regolatori relativi agli strumenti esenti dal consenso — verifichi l'elenco attuale piuttosto che un articolo di blog, ma sulla carta è un vantaggio reale.

GoAccess è l'opzione che nessuno suggerisce e che diverse persone dovrebbero scegliere. Legge il log degli accessi che il suo server web scrive già e lo trasforma in un report da terminale o in un'unica pagina HTML autonoma. Nel browser non viene eseguito nulla, sul dispositivo non viene salvato nulla, e non c'è alcuna domanda sul consenso da porsi perché non c'è raccolta oltre alla richiesta stessa. Ciò a cui rinuncia è tutto quello che accade all'interno della pagina e ogni speranza di contare le persone piuttosto che le richieste. Per un sito di documentazione o un blog statico, questo è spesso un compromesso equo — e si accompagna bene a uno degli altri strumenti piuttosto che sostituirlo.

La decisione in una riga

Se non riesce a nominare la funzionalità di cui ha bisogno da Plausible o Matomo, allora le serve Umami. Lo distribuisca in venti minuti, lo utilizzi per un mese, e lasci che sia la domanda a cui non riesce a rispondere a dirle se cambiare. Migrare in seguito le costa la cronologia e nulla altro, e la cronologia che perderebbe è di un mese.

Passo 02 · Provisioning

Un server, un nome. Prima fissi il nome.

Ordini il VPS e scelga il bastione in base a dove si trovano i suoi lettori e a dove vuole che risiedano i dati — Stoccolma, Helsinki, Oslo e Reykjavík si trovano tutte all'interno dello SEE, ed è proprio questo il punto. Poi esegua il passaggio di hardening della prima ora prima che qualsiasi altra cosa tocchi il server: SSH solo con chiavi, una porta spostata, un firewall con blocco predefinito, aggiornamenti automatici. Sono gli stessi quaranta minuti per ogni guida di questa serie e non sono facoltativi su una macchina che conterrà un anno del pubblico di lettori di qualcuno.

Poi stabilisca il nome host, perché è incorporato nello snippet di tracciamento in ogni pagina di ogni sito che misura, e cambiarlo in seguito significa modificarli tutti mentre il vecchio nome continua a ricevere hit. Due forme funzionano. Un sottodominio dedicato del sito che sta misurando — il reverse proxy sul server di analisi risponde per esso, ed è la cosa più semplice che funzioni. Oppure un nome neutro su un dominio proprio, se un'unica istanza servirà diversi siti non collegati tra loro e preferisce che il codice sorgente di ciascun sito non riveli gli altri. Crei il record e lo lasci risolvere prima di andare oltre: il proxy richiede un certificato a un'autorità di certificazione al primo avvio, e l'autorità verifica il nome dall'esterno.

dig +short stats.example.com          # must return the VPS address before you deploy
ufw default deny incoming
ufw allow 47222/tcp                  # administrative SSH, moved off 22
ufw allow 80/tcp                     # ACME challenge and the redirect to 443
ufw allow 443/tcp                    # the dashboard and the collection endpoint
ufw enable && ufw status numbered

Tre porte, e nient'altro. Il database non deve essere pubblicato: vive sulla rete Docker interna, raggiungibile dal container dell'applicazione e da nessun altro su internet. Questo è il modo più comune in assoluto in cui un server di analisi self-hosted finisce in un risultato di scansione — una porta PostgreSQL o MySQL associata all'indirizzo pubblico perché un file Compose preso da un tutorial conteneva una mappatura di porte che era lì per lo sviluppo locale.

Sul dimensionamento, resista alla tentazione di comprare più del necessario. Un Sentinel — 2 vCPU, 4 GB, 120 GB NVMe, $3.90 al mese — fa funzionare Umami più Postgres con margine di riserva, e conterrà anni di eventi per un sito con visualizzazioni mensili a sei cifre. Passi a un Garrison — 4 vCPU, 8 GB, 240 GB — se ha scelto Plausible, perché ClickHouse ci si trova meglio, oppure Matomo, perché il job di archiviazione vuole più core. La banda è illimitata su ogni livello e il traffico di analisi è un errore di arrotondamento rispetto ad essa: ogni hit è poche centinaia di byte.

Passo 03 · Deploy

Due container e un proxy. Poi chiuda la porta.

Il deployment di riferimento qui sotto è Umami, perché è quello che la maggior parte dei lettori dovrebbe eseguire e perché la struttura si generalizza: un container applicativo, un container database che può raggiungere e che nessun altro può raggiungere, e un reverse proxy che detiene il certificato. Plausible e Matomo differiscono nel numero di container e nei nomi delle variabili, non nella struttura — prenda i loro file Compose ufficiali e applichi le stesse tre regole.

Le tre regole, in ordine di quanto le costeranno se ignorate. Blocchi ogni immagine su un tag esatto, mai su uno mobile: uno stack di analisi che scarica silenziosamente una nuova versione principale durante un riavvio non correlato è una migrazione dello schema che non ha pianificato. Generi il secret dell'applicazione da una vera fonte casuale e lo conservi — cifra il materiale di sessione, e cambiarlo in seguito, nel migliore dei casi, disconnette tutti. Non pubblichi alcuna porta del database: i due container condividono una rete ed è tutto il controllo degli accessi di cui hanno bisogno.

mkdir -p /srv/analytics && cd /srv/analytics
openssl rand -base64 32 > .app_secret      # keep this file; back it up with the database
openssl rand -base64 24 > .db_password
chmod 600 .app_secret .db_password

Il file Compose. Due servizi, una rete privata, un volume denominato per il database, e nessuna porta pubblicata — il proxy è la sola cosa che comunica con il mondo esterno:

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-v2.x.y   # an exact tag, never :latest
    environment:
      DATABASE_URL: postgresql://umami:CHANGE_ME@db:5432/umami
      APP_SECRET:   CHANGE_ME                                # the openssl output above
    depends_on: [db]
    restart: unless-stopped
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB:       umami
      POSTGRES_USER:     umami
      POSTGRES_PASSWORD: CHANGE_ME
    volumes:
      - umami-db:/var/lib/postgresql/data
    restart: unless-stopped
volumes:
  umami-db:

Caddy è qui la via più breve verso una configurazione TLS corretta: due righe di configurazione, un certificato ottenuto e rinnovato senza un cron job, e impostazioni predefinite moderne che non deve andare a cercare. Se sul server esegue già nginx, mantenga nginx — il requisito è un proxy davanti, non questo proxy in particolare. In ogni caso l'applicazione di analisi non deve mai essere ciò che resta in ascolto direttamente sulla porta 443.

# Caddyfile — Caddy runs as a third service in the same Compose project, so
# "umami" resolves on the internal network. It is the only service that
# publishes ports (80 and 443).
stats.example.com {
    encode zstd gzip
    reverse_proxy umami:3000
}

Lo avvii, poi faccia l'unica cosa che è davvero critica in termini di tempo. docker compose up -d, attenda le migrazioni, e apra la dashboard. Ognuno di questi strumenti fornisce o un account amministratore predefinito documentato o una schermata di prima registrazione aperta, e il nome host è diventato di pubblico dominio nell'istante in cui il certificato è stato emesso, perché i log di certificate transparency sono pubblici e vengono scansionati continuamente. Cambi la password predefinita e chiuda la registrazione entro pochi minuti dal primo caricamento riuscito, non domani.

docker compose up -d
docker compose logs -f umami          # wait for the schema migration to finish
docker compose ps                     # both services healthy, no published ports listed
ss -tlnp | grep -E ':(5432|3306)'     # must print nothing at all
I cinque minuti che decidono chi possiede l'istanza

Umami viene distribuito con un account amministratore documentato la cui password è la stessa per ogni installazione al mondo. Il primo visitatore di Plausible diventa il proprietario a meno che la registrazione non sia disabilitata nell'ambiente. Matomo guida il primo visitatore attraverso un installer che crea il superuser. In tutti e tre i casi, la finestra tra "il certificato esiste" e "ha effettuato l'accesso" è una finestra in cui qualcun altro può accedere al posto suo — e non ha nemmeno bisogno di indovinare il nome host, perché viene pubblicato per lui. Acceda prima lei, cambi la credenziale, poi imposti l'interruttore di registrazione su chiuso e ricarichi la pagina per confermare che la modifica sia stata applicata.

Passo 04 · Strumentazione

Un tag. Poi decida su quale dominio risiede.

Registri il sito nella dashboard, copi l'identificatore che le fornisce, e inserisca un tag script differito nel template — nell'head o alla fine del body, non importa molto, ma differito in entrambi i casi così non potrà mai ritardare la pagina. Questa è l'intera integrazione. Non c'è alcun tag manager, nessun container, nessun data layer e nessun collegamento per la modalità di consenso, e questa assenza è la maggior parte di ciò per cui è venuto.

<script defer src="https://stats.example.com/script.js"
        data-website-id="00000000-0000-0000-0000-000000000000"></script>

Carichi una pagina del sito, poi guardi la dashboard: l'hit dovrebbe essere lì entro pochi secondi. Se non lo è, la console del browser e la scheda rete rispondono in meno di un minuto — le due modalità di errore sono un identificatore digitato in modo errato, che produce una richiesta accettata e scartata, e una richiesta che non parte affatto, il che significa che un'estensione l'ha bloccata. Escluda il proprio traffico prima di iniziare a leggere i numeri, altrimenti i suoi stessi ricaricamenti di pagina saranno il suo referrer principale per una settimana.

Ora la decisione su cui vale la pena riflettere. Il frammento di codice sopra effettua una richiesta verso un nome host che non è quello del sito, e una parte dei suoi visitatori esegue software che blocca tali richieste in base a un pattern. Le liste intercettano i nomi di file noti — qualsiasi cosa termini con il nome dello script del fornitore — e i domini ospitati noti, indipendentemente dal server a cui puntano. La correzione ha due parti: rinominare il file dello script e l'endpoint di raccolta con qualcosa che non sia un nome da tracker, cosa che ognuno di questi strumenti supporta, e servirli dall'origine stessa del sito tramite un percorso che il suo proxy esistente inoltra. A quel punto non resta più alcuna richiesta di terze parti da bloccare.

# On the site's own web server — the two paths the tracker needs, first-party:
example.com {
    handle /p/s.js      { reverse_proxy https://stats.example.com { header_up Host stats.example.com } }
    handle /p/collect   { reverse_proxy https://stats.example.com { header_up Host stats.example.com } }
    # ... the rest of the site
}

Due dettagli fanno funzionare tutto questo invece che a metà. Il proxy deve trasmettere l'indirizzo del visitatore in un header che l'applicazione di analisi è configurata per considerare attendibile, altrimenti ogni hit verrà attribuito al suo stesso server web e il report per paese sarà una singola barra. E al tracker deve essere indicato dove inviare i suoi dati, il che è un attributo data sul tag script in tutti e tre gli strumenti — rinominare il file senza reindirizzare l'endpoint le dà uno script che si carica e non riporta a nessun posto.

Questo è anche il limite onesto della misurazione. Un visitatore con JavaScript disattivato, o con una lista rigorosa più una regola cosmetica first-party, non verrà contato, e non si dovrebbe spendere alcuna quantità di ingegneria per rincorrerlo — un filtro a livello di rete è una preferenza dichiarata e la risposta educata è il log del server, che li conta senza raccogliere nulla in più. Gli eventi e le applicazioni a pagina singola sono l'altra metà della strumentazione: ogni strumento espone una piccola funzione per eventi personalizzati, e ognuno di essi ha bisogno di una chiamata esplicita al cambio di rotta, perché un framework che sostituisce la vista senza una navigazione non produce alcun caricamento di pagina che lo script possa notare.

Passo 05 · Conformità

Due leggi, non una. La maggior parte di internet le confonde.

Il motivo per cui le persone non riescono a concordare sul fatto che l'analisi richieda un banner è che stanno discutendo di due regole diverse come se fossero una sola. Le si separi e la risposta diventa gestibile. L'articolo 5(3) della direttiva ePrivacy — recepito nel diritto nazionale di ogni Stato membro, e la vera fonte del banner dei cookie — afferma che salvare informazioni su, o accedere a informazioni già salvate su, l'apparecchiatura terminale di un abbonato richiede il suo consenso, a meno che non sia strettamente necessario per fornire un servizio che ha esplicitamente richiesto. Noti cosa non dice: non dice cookie, e non dice dato personale. Cattura localStorage, cattura il fingerprinting del dispositivo, e si applica anche a un valore che non identifica nessuno.

Il GDPR è la seconda regola e disciplina una questione diversa: cosa può fare con i dati personali una volta che li ha. Si applica alla sua analisi indipendentemente dal fatto che salvi qualcosa sul dispositivo, perché una richiesta web fornisce un indirizzo IP e la Corte di giustizia ha stabilito nella causa Breyer (C-582/14) che un indirizzo IP può costituire un dato personale nelle mani di un operatore di un sito web. Le due regole si sommano quindi: l'articolo 5(3) chiede ha scritto sul dispositivo?, il GDPR chiede cosa ha fatto con quello che è arrivato?.

Un server di analisi senza cookie è costruito per rispondere a entrambe in modo circoscritto. Non salva nulla sul dispositivo — nessun cookie, nessuna voce in localStorage, nessun identificatore di alcun tipo — il che esclude l'articolo 5(3) dal gioco, perché non c'è alcuna memorizzazione né alcun accesso alla memorizzazione. E prende l'indirizzo IP che riceve necessariamente, lo combina con lo user agent, il sito e un salt segreto che viene ruotato ogni giorno, ne calcola l'hash, conserva l'hash e scarta l'indirizzo. Quell'hash permette allo strumento di distinguere due visitatori nell'arco di un giorno e smette di essere utile nel momento in cui il salt viene ruotato, il che è esattamente il motivo per cui la stessa persona il giorno dopo conta come un nuovo visitatore. Il trattamento è reale, ed è quanto di più piccolo un trattamento possa essere.

Ciò che resta è una base giuridica per quell'operazione circoscritta, e in pratica gli operatori si basano sul legittimo interesse ai sensi dell'articolo 6(1)(f), documentato con una valutazione di bilanciamento che è breve perché i fatti sono semplici: nessuna profilazione, nessuna condivisione, nessun tracciamento cross-site, uno pseudonimo che muore ogni giorno, un periodo di conservazione definito. Diverse autorità di controllo sono andate oltre e hanno pubblicato criteri secondo i quali una misurazione dell'audience strettamente limitata è esente dal consenso del tutto — i criteri variano da paese a paese, vengono aggiornati, e quello che conta per lei è il suo. Questo non è un parere legale. È la mappa di quali strumenti si applicano, affinché il parere che riceve possa riguardare la sua situazione specifica invece della forma generale del problema.

La domanda Tag di analisi ad-tech Senza cookie, self-hosted nello SEE
Scrive sul dispositivo del visitatore?Sì — quindi si applica il consenso dell'articolo 5(3)No — l'articolo 5(3) non si attiva
Identificatore persistente conservato?Da mesi ad anni, tra i vari sitiUn hash con salt che scade ogni giorno
Trasferimento verso un paese terzo da documentare?Sì, con un meccanismo di trasferimento da mantenereNessuno — il server è nello SEE
Responsabili del trattamento da nominare e contrattualizzareIl fornitore e i suoi sub-responsabili del trattamentoIl suo host, per l'hardware, e nessun altro
Chi può rispondere a una richiesta di accesso dell'interessatoLei, tramite qualunque export esistaLei, con SQL — e spesso non c'è nulla da restituire

Un'ultima riga appartiene al fascicolo, perché è l'argomento silenzioso per fare tutto questo. La liceità dell'invio dei dati dei visitatori europei a un servizio di analisi statunitense è stata oggetto di contenzioso per un decennio: la Corte di giustizia ha annullato il precedente quadro di trasferimento nella causa Schrems II (C-311/18) nel 2020, diverse autorità di controllo nazionali si sono pronunciate contro il tag di analisi standard su questa base nel 2022 — l'Austria a gennaio, la Francia a febbraio, l'Italia a giugno, con altre a seguire — e una nuova decisione di adeguatezza, l'EU-US Data Privacy Framework, ha ripristinato una via di trasferimento nel luglio 2023 ed è essa stessa oggetto di contestazione. Non deve necessariamente avere un'opinione su come questo finirà. Un server a Helsinki elimina la questione dal suo fascicolo in modo permanente, e questo vale più che avere ragione sullo stato attuale della vicenda.

Passo 06 · Conservazione

Conservazione, backup, aggiornamenti. E il log che ha dimenticato.

Imposti il periodo di conservazione il primo giorno, mentre è ancora un numero astratto piuttosto che un anno di dati a cui è affezionato. Ognuno di questi strumenti può eliminare gli eventi grezzi secondo una pianificazione e conservare i riepiloghi aggregati; dodici mesi di dettaglio sono generosi per quasi ogni scopo, e significa che la risposta onesta a "per quanto tempo li conserva" è un numero piuttosto che "indefinitamente". Questo risolve anche il problema dello spazio su disco prima che si presenti, il che conta soprattutto per Matomo, le cui tabelle grezze sono quelle che crescono.

Faccia il backup del database in un posto che non sia questa macchina e lo cifri durante il trasferimento — la guida ai backup è il trattamento completo, e la versione breve è un dump notturno incanalato in un repository append-only su una seconda macchina, idealmente in una seconda giurisdizione. Faccia il backup anche del secret dell'applicazione: un database che può ripristinare e un secret che non può sono una dashboard in cui nessuno può accedere. Poi lo ripristini una volta su un VPS di prova, di proposito, prima che ne abbia bisogno.

docker compose exec -T db pg_dump -U umami umami | zstd -q -o /srv/backup/umami-$(date -u +%F).sql.zst
restic -r sftp:backup@bastion-2:/srv/repo backup /srv/backup /srv/analytics/.app_secret
restic -r sftp:backup@bastion-2:/srv/repo forget --keep-daily 7 --keep-weekly 8 --prune

Gli aggiornamenti meritano un po' più di attenzione di un normale avanzamento di container, perché queste applicazioni possiedono uno schema. Legga le note di rilascio per le versioni principali che sta superando, faccia il backup prima e non dopo, poi cambi il tag bloccato e avvii lo stack mentre osserva i log — una migrazione che fallisce a metà è recuperabile dal dump della notte precedente ed è molto spiacevole senza di esso. Non c'è alcun motivo per essere sull'ultima versione nella settimana in cui appare, e c'è un buon motivo per non esserlo.

Il log che vanifica tutto l'esercizio

Ha appena distribuito uno stack che deliberatamente non salva mai un indirizzo IP. A due metri di distanza, il suo reverse proxy sta scrivendo l'indirizzo IP completo di ogni singolo visitatore in un log degli accessi, in chiaro, e lo conserva per tutto il tempo indicato dalla rotazione predefinita — sia sul server di analisi sia sul server web davanti al suo sito effettivo. Quel log è un insieme di dati più grande e più sensibile del database di analisi, è un trattamento di cui deve rendere conto, e quasi nessuno se ne ricorda. Decida a cosa serve: se è solo per il debug, tronchi o mascheri l'ultimo ottetto nel formato del log e ruoti in modo aggressivo; se lo desidera per una misurazione basata sui log, lo dichiari nella policy e gli assegni un periodo di conservazione reale. Quello che non deve fare è lasciarlo all'impostazione predefinita e descrivere il suo sito come se non raccogliesse indirizzi IP.

Infine, i limiti su cui vale la pena essere onesti, perché un contatore self-hosted non è una versione strettamente migliore di ciò che ha eliminato. Perde l'identità cross-device e cross-day, quindi visitatore di ritorno significa qualcosa di più circoscritto di prima. Perde l'integrazione con la piattaforma pubblicitaria, il che conta se acquista traffico ed è irrilevante se non lo fa — i dati di search console sono un prodotto separato e non ne sono influenzati. Si assume un aggiornamento e un backup, un costo ricorrente reale misurato in serate. E il server stesso diventa qualcosa che vale la pena proteggere: custodisce il suo pubblico di lettori, è sulla rete pubblica, e la checklist di hardening più un percorso privato verso la dashboard sono le due cose che lo mantengono tranquillo.

Note dal campo · Sei trappole

Sei modi in cui questo può andare storto. Due di essi sono silenziosi.

Trappola 01 · Fatale

La password predefinita che tutti conoscono

Uno di questi strumenti fornisce la stessa credenziale amministrativa su ogni installazione al mondo; gli altri assegnano la proprietà a chiunque si registri per primo. Il nome host viene pubblicato nei log di certificate transparency nel momento in cui il TLS funziona. Acceda, la cambi, chiuda la registrazione — nei primi cinque minuti, non domani.

Trappola 02 · Fatale

La porta del database del tutorial

I file Compose scritti per un laptop pubblicano la porta 5432 o 3306 in modo che l'autore potesse connettersi da una GUI. Copi uno di questi su un server pubblico e la tabella dei lettori è a un tentativo di password di distanza. Il container dell'applicazione raggiunge il database tramite la rete interna; non c'è bisogno di pubblicare nulla se non il proxy.

Trappola 03 · Legale

Presumere che self-hosted significhi esente

Spostare il software sul proprio server risponde alla questione del trasferimento e a quella del responsabile del trattamento. Non risponde all'articolo 5(3) se poi attiva una funzionalità che scrive sul dispositivo, e non scrive la sua privacy policy. L'esenzione è una proprietà della configurazione, non dell'hosting.

Trappola 04 · Silenziosa

Ogni visitatore arriva dallo stesso paese

Un reverse proxy che non trasmette l'indirizzo del client fa sembrare che ogni hit provenga dal proxy stesso. La dashboard si riempie, i totali sembrano corretti, e le colonne di geografia e unicità sono silenziosamente fittizie. Verifichi la suddivisione per paese il primo giorno, non nella revisione trimestrale.

Trappola 05 · Silenziosa

Il log degli accessi che sta ancora conservando

Lo stack è stato scelto perché non salva mai un indirizzo IP. Il proxy davanti ad esso li salva tutti in chiaro per impostazione predefinita, e lo stesso fa il server web davanti al suo sito effettivo. Li mascheri o li ruoti deliberatamente, e li descriva nella policy — oppure smetta di affermare di non raccoglierli.

Trappola 06 · Evitabile

Rincorrere i vecchi numeri

I nuovi totali non corrisponderanno ai vecchi e nessuna configurazione li farà corrispondere. Regole di conteggio diverse, una quota bloccata diversa, e nessun banner che filtra il campione. Dedichi le due settimane a conoscere il proprio rapporto, poi tratti la nuova cifra come base di riferimento e smetta di conciliare due definizioni.

FAQ · Analisi self-hosted

Domande, con risposta.

Undici domande che emergono nel farlo — a cominciare da quella che tutti sbagliano in entrambe le direzioni.

Posso davvero eliminare il banner dei cookie se faccio self-hosting?

Spesso sì, e la ragione è più precisa di "il self-hosting va bene". Sono in gioco due regole distinte. L'articolo 5(3) della direttiva ePrivacy — quella che tutti chiamano la legge sui cookie — richiede il consenso per salvare informazioni sul dispositivo di un visitatore, o per leggerne, a meno che non sia strettamente necessario per un servizio che ha richiesto. Si applica ai cookie, ma anche a localStorage, a sessionStorage e a qualsiasi altra cosa lasci dietro di sé, e si applica indipendentemente dal fatto che il dato sia personale. Uno strumento che non scrive nulla sul dispositivo semplicemente non la attiva. Il GDPR è la seconda regola e non scompare: riceve comunque un indirizzo IP e una stringa user-agent a ogni richiesta, e un indirizzo IP è un dato personale nelle mani di un operatore di un sito web (Corte di giustizia, Breyer, C-582/14). Ciò che fa un server di analisi senza cookie è calcolare l'hash di quell'IP con un salt che viene ruotato ogni giorno e poi scartarlo, quindi ciò che finisce nel database è uno pseudonimo giornaliero per sito, non una persona. Si tratta di un trattamento circoscritto e ben documentato, su cui la maggior parte degli operatori si basa facendo leva sul legittimo interesse, e diverse autorità di controllo hanno pubblicato criteri secondo i quali la pura misurazione dell'audience è esente dal consenso. È una posizione difendibile, non una formula magica: annoti cosa raccoglie, perché, e per quanto tempo, e legga le linee guida del suo stesso regolatore piuttosto che la landing page di un fornitore. Nulla in questa pagina costituisce consulenza legale.

Quale dovrei scegliere se non voglio pensarci?

Umami. È un'unica applicazione Node e un database PostgreSQL, sta comodamente sotto 1 GB di memoria, la dashboard è leggibile dalla prima visita, è senza cookie di default, e un'unica istanza serve senza problemi tutti i siti che possiede. Per la stragrande maggioranza delle persone che sostituiscono Google Analytics su un blog, un sito di documentazione, un negozio o un sito aziendale, è la risposta giusta e gli altri tre sono una discussione di cui non aveva bisogno. Scelga invece Plausible Community Edition se vuole funnel, obiettivi di fatturato e una proposta di dashboard pubblica più solida, ed è disposto a gestire ClickHouse per ottenerli. Scelga Matomo se ha davvero bisogno del set di funzionalità di Google Analytics — segmenti, coorti, report personalizzati, attribuzione e-commerce, importazione di log grezzi — e accetta di gestire un'ampia applicazione PHP con un job di archiviazione pianificato. Scelga GoAccess se non vuole alcun JavaScript sulla pagina.

Perché i numeri non corrispondono a quelli di Google Analytics?

Perché stanno contando cose diverse, e lo scarto corre in entrambe le direzioni contemporaneamente. Verso l'alto: Google Analytics dietro un banner di consenso vede soltanto i visitatori che hanno premuto accetta, il che in Europa corrisponde di norma alla metà di essi, mentre un contatore senza cookie e senza banner li vede tutti. Ancora verso l'alto: il suo nuovo endpoint è sul suo stesso dominio e non è presente nelle liste di filtri che scartano le richieste verso i tracker più noti. Verso il basso: un hash che ruota ogni giorno non può riconoscere la stessa persona il giorno dopo, quindi un lettore che visita il sito lunedì e giovedì è due visitatori, non un visitatore di ritorno — le sessioni sono ricomposte nell'arco di un giorno e mai tra giorni o dispositivi diversi. Ancora verso il basso: la maggior parte degli strumenti self-hosted include un filtro anti-bot prudente e nessuna inflazione in stile Discover. Il consiglio pratico è smettere di conciliare i numeri. Esegua entrambi per due settimane per conoscere il proprio rapporto, lo scriva su un post-it, poi elimini il tag Google e usi i nuovi numeri come la base di riferimento che ora sono. Ciò che conta per le decisioni è la forma della tendenza e la classifica relativa di pagine e fonti, ed entrambe sopravvivono intatte al passaggio.

I blocker di pubblicità bloccheranno anche la mia istanza?

In parte, e vale la pena sapere esattamente come, perché il meccanismo è più rozzo di quanto si pensi. Le grandi liste di filtri funzionano su pattern: i nomi host dei servizi ospitati, e un insieme di nomi di file e percorsi noti — una richiesta per qualcosa che termina in plausible.js, umami.js o matomo.php è riconoscibile indipendentemente dal server verso cui è diretta. Sposti il software su stats.example.com con i nomi di file predefiniti e perderà comunque una parte del pubblico più tecnico. Ci sono due correzioni oneste e si sommano tra loro. Rinomini lo script e l'endpoint di raccolta con qualcosa che non sia un nome da tracker — ognuno di questi strumenti lo consente, e costa una sola riga di configurazione. Li serva dalla stessa origine del sito stesso, tramite un percorso sul suo dominio principale che il reverse proxy inoltra, in modo che non resti alcuna richiesta di terze parti da bloccare. Insieme, questi due accorgimenti recuperano la maggior parte della perdita. Non la recupererà del tutto, e non dovrebbe volerlo: un visitatore che utilizza una lista rigorosa più JavaScript disattivato ha fatto una scelta, e la risposta corretta a ciò è il log del server, non una corsa agli armamenti.

Fare da proxy allo script tramite il proprio dominio è un dark pattern?

Merita la domanda, e la risposta dipende da cosa stesse proteggendo il blocker. Una lista di filtri ha uno strumento grezzo e due obiettivi molto diversi: la rete ad-tech che segue una persona attraverso diecimila siti e costruisce un profilo, e il contatore che dice a un unico proprietario di sito che la sua pagina di documentazione è stata letta quattrocento volte ieri. Bloccare il primo è una persona che si difende dalla sorveglianza. Bloccare il secondo è un danno collaterale causato da una regola che non sa distinguerli. Servire il proprio contatore dal proprio dominio non significa far passare di nascosto un tracker oltre una difesa; significa eliminare una richiesta di terze parti che non sarebbe mai dovuta esistere, e la stessa visita genera comunque una riga nel suo log degli accessi. Il punto in cui questo smette di essere difendibile è il momento in cui ciò che sta facendo passare tramite proxy non è ciò che è descritto qui — se aggiunge identificatori cross-site, fingerprinting o una pipeline verso una piattaforma pubblicitaria, il blocker aveva ragione e il proxy è una menzogna. Il test è semplice e vale la pena applicarlo a se stessi una volta: potrebbe pubblicare una pagina che descrive esattamente cosa raccoglie questo endpoint, e un lettore si limiterebbe a scrollare le spalle? Se sì, lo faccia passare tramite proxy. Se no, il problema non è il proxy.

Quanto deve essere grande davvero il VPS?

Più piccolo di quanto teme, con un'eccezione. Umami è un processo Node e un database Postgres: si stabilizza sotto 1 GB di memoria per un sito normale e il database cresce di circa la dimensione di una riga di testo per ogni visualizzazione di pagina, quindi un Sentinel — 2 vCPU, 4 GB, 120 GB NVMe, $3.90 al mese — ha anni di margine. GoAccess è un errore di arrotondamento. Matomo sta nel mezzo: PHP e MariaDB sono poco esigenti finché non viene eseguito il job di archiviazione, che è il picco di CPU per cui deve dimensionare, e le sue tabelle grezze crescono più velocemente delle altre perché conserva più dati per ogni hit. L'eccezione è Plausible Community Edition, e il motivo è ClickHouse piuttosto che Plausible: un column store è costruito per scambiare memoria con velocità di query e si servirà di qualsiasi cosa lasci a disposizione. Funziona con 4 GB se limita le sue cache nella configurazione predefinita, ed è comodo a 8 GB — motivo per cui il livello Garrison a $7.90 è la soglia ragionevole per questo strumento. In ogni caso, il numero che alla fine forza un aggiornamento è il disco, non la memoria, e il passo 06 è come lo si ferma.

Un'unica istanza può misurare più siti diversi?

Sì, ed è il modo normale di gestirli. Tutti e tre gli strumenti JavaScript sono multi-sito per progettazione: registra ogni dominio nella dashboard, ognuno ottiene il proprio identificatore, e lo stesso endpoint dello script accetta hit per tutti loro mantenendo i report separati. Un server, un certificato, un backup, un aggiornamento — venti siti. Due cose da tenere a mente man mano che l'elenco cresce. I report sono separati per sito, quindi se amministra siti per clienti, usi i permessi utente e team propri dello strumento piuttosto che consegnare a tutti l'account amministratore, e verifichi cosa implica un'istanza condivisa prima di accettarlo in un contratto: diventa la parte che detiene i dati dei loro visitatori. E l'endpoint di tracciamento è un nome condiviso, il che significa che il dominio che lo serve appare nel codice sorgente di ogni sito dell'elenco — un fatto che vale la pena menzionare a un cliente i cui concorrenti leggono il codice sorgente delle pagine, e un argomento a favore del percorso first-party del passo 04.

Ho davvero bisogno di JavaScript? E l'analisi del log del server?

Per un'ampia categoria di siti, il log è sufficiente, ed è la misurazione più onesta disponibile: non raccoglie nulla in più, perché le righe esistono già. GoAccess legge il log degli accessi di un server web e produce un report da terminale o una dashboard HTML autonoma — pagine principali, referrer, codici di stato, banda, tempi di risposta, user agent — per un sito statico, un set di documentazione o un'API, questo è la maggior parte di ciò che un tag script le avrebbe detto. Due limiti decidono se è sufficiente per lei. Un log non può vedere cosa accade all'interno della pagina: nessuna profondità di scorrimento, nessun clic su link esterni, nessun evento sui pulsanti, nessun cambio di rotta in un'applicazione a pagina singola, perché nulla di tutto ciò tocca il server. E un log conta le richieste piuttosto che le persone, quindi è in balìa della cache e di una popolazione di bot che oggi costituisce la maggioranza del traffico grezzo — il filtraggio è un'attività di manutenzione permanente, non un passaggio di configurazione. C'è anche una trappola per la privacy nella direzione opposta a quella che si aspetterebbe, e il passo 06 la tratta: il log che sta analizzando contiene indirizzi IP completi, che sono più dati personali di quanti ne conservasse lo strumento JavaScript che ha respinto.

Posso importare la mia cronologia di Google Analytics?

Realisticamente, no, e pianificare tenendone conto è meglio che combatterlo. Matomo è il solo dei quattro con una storia di importazione seria, e anche lì i percorsi pratici sono importare i propri log del server web e usare gli strumenti di migrazione per istanze Matomo più vecchie, piuttosto che un trasferimento pulito dei report elaborati da Google. Umami e Plausible Community Edition possono accettare un caricamento in blocco tramite le loro API se è disposto a scrivere la mappatura, ma starebbe inventando sessioni e visitatori a partire da export aggregati, e il risultato è un grafico che appare continuo e non è confrontabile attraverso il punto di giunzione. Ciò che funziona davvero: esporti da Google i report a cui tiene prima che la proprietà scompaia — i totali mensili, le pagine principali, le fonti principali, i conteggi delle conversioni — come CSV, li conservi nello stesso posto dei suoi altri archivi, e avvii il nuovo strumento come una base di riferimento nuova a partire da una data che annota. Consulterà l'export vecchio due volte nel primo anno e mai più, e ogni numero al suo interno era comunque misurato secondo una definizione diversa.

Cosa devo scrivere esattamente nella privacy policy?

Meno di quanto pensi, e la brevità è proprio il punto — un paragrafo che può difendere vale più di una pagina che ha copiato. Dica cos'è lo strumento e che lo gestisce lei stesso; indichi la posizione del server e l'operatore legale, perché poter dire "su una macchina che noleggiamo in Finlandia" è tutto il beneficio di questa operazione. Dica cosa viene registrato per ogni visita: la pagina, il referrer, il paese, il dispositivo e la famiglia di browser, e un identificatore pseudonimo derivato dall'indirizzo IP e dallo user agent con un salt che cambia ogni giorno, dal quale l'IP originale non può essere recuperato. Dica cosa non viene registrato: nessun cookie, nessun identificatore cross-site, nessun profilo, nessun dato venduto o condiviso. Indichi la base giuridica su cui si basa e il periodo di conservazione, e si assicuri che il numero che scrive sia quello con cui lo strumento è configurato. Se il suo reverse proxy conserva i log degli accessi, questo è un trattamento separato con una propria conservazione — lo menzioni, perché è quello che si tende a dimenticare. Poi mantenga il paragrafo sincronizzato con la configurazione: una policy che descrive l'impostazione di due anni fa è peggiore di una vaga.

Perché l'host conta per un server che contiene solo visualizzazioni di pagina?

Perché "solo visualizzazioni di pagina" sottostima cosa sia davvero un database di analisi. Aggregato su un anno, è il pubblico di lettori del suo sito: quali pagine, in quale ordine, da quali paesi, a quali orari, provenendo da quali link — e per un piccolo editore o un negozio di nicchia, questo è un business plan e un elenco di fonti in un'unica tabella. È anche, dal punto di vista giurisdizionale, esattamente il tipo di dato che un avversario chiede a un fornitore piuttosto che chiederlo a lei. Ne derivano due proprietà. Dove si trova il server decide quale procedimento legale può raggiungerlo: una macchina a Stoccolma, Helsinki, Oslo o Reykjavík si trova all'interno dello SEE, il che elimina del tutto la questione del trasferimento internazionale dal suo fascicolo di conformità, e all'interno di quattro ordinamenti costituzionali con solide tradizioni di libertà di stampa. E il nome sull'account decide cosa riveli l'account stesso: su NordBastion non c'è alcun documento d'identità, nessun nome legale e nessuna carta, la fattura si salda in Monero o Bitcoin, e la macchina che custodisce il pubblico dei suoi lettori non è una riga in un database clienti da qualche parte con il suo passaporto allegato. La guida alle giurisdizioni tratta in dettaglio la soglia legale minima di ciascuno dei quattro paesi.

Ottenere il server

Il suo pubblico di lettori, su una macchina nello SEE che non è registrata al suo nome.

Sentinel — 2 vCPU, 4 GB e 120 GB di NVMe per $3.90 al mese, a Helsinki, Stoccolma, Oslo o Reykjavík — fa funzionare Umami e il suo database con margine per anni di eventi. Passi a Garrison a $7.90 se ha scelto Plausible o Matomo. Nessuna email alla registrazione, nessun documento d'identità, nessuna carta, e nessuna terza parte in possesso dell'elenco di chiunque abbia mai letto il suo sito.

Ultima revisione · 2026-10-12 · Fonti · Documentazione di Umami, Plausible Community Edition, Matomo e GoAccess; direttiva ePrivacy 2002/58/EC, articolo 5(3); regolamento (UE) 2016/679; sentenze della Corte di giustizia nelle cause Breyer (C-582/14) e Schrems II (C-311/18); decisione di adeguatezza EU-US Data Privacy Framework del luglio 2023 · Cadenza · annuale

Hosting privato, costruito nel Nord.