Aller au contenu
snorklee
Produit Vue d'ensemble Trafic IA Analytics Tarifs Manifeste Documentation Contact Connexion Essai gratuit 7 jours

Self-host del tracker (anti-blocco)

Chrome 121+, uBlock Origin, Brave Shields, AdGuard e la maggior parte dei blocchi pubblicitari bloccano per impostazione predefinita qualsiasi richiesta verso un dominio di terze parti etichettato come "analytics", anche quando il servizio non effettua alcun tracking pubblicitario (come nel nostro caso).

Senza intervento, perdi oggi dal 5 al 20% delle sessioni, e questa quota salirà al 30-50% nei prossimi 12-24 mesi quando Chrome applicherà il Tracking Protection a tutte le sessioni normali (non solo alla navigazione privata).

La soluzione: servire il tracker e l'API dal tuo dominio. Il browser vede allora una richiesta "1st-party" indistinguibile da una chiamata a un'immagine o a un foglio di stile. Nessun blocco blocca questo.

Questa pagina documenta come farlo con configurazioni first-party compatibili con un approccio di infrastruttura europea. Scegli hosting e regione di esecuzione in base alle tue esigenze di conformità, performance e supporto.

WordPress — usa il plugin ufficiale

Su WordPress, non partire da Nginx, Caddy o DNS. Il plugin ufficiale Snorklee Analytics 2.3.4+ include già la modalità self-host:

  1. Installa o aggiorna il plugin dalla dashboard Snorklee o dalla pagina Plugin WordPress Snorklee.
  2. In wp-admin, apri Snorklee.
  3. Verifica il dominio del sito e lascia l'URL dashboard su https://snorklee.com, salvo istanza self-hosted.
  4. Abilita Self-host mode e salva.
  5. Avvia Testa installazione. Il risultato deve indicare self-host o proxy 1st-party rilevato.

Il plugin serve /js/flow.js da WordPress, inoltra /api/event, /api/ping, mette in cache il tracker JavaScript per 1 ora via Transients API e non memorizza eventi in WordPress.


Come funziona — schema generale

┌──────────────────────────────────────────────────────────────────────────┐
│                                                                          │
│   PRIMA (3rd-party, bloccato)                                            │
│   ──────────────────────────                                             │
│                                                                          │
│   navigatore ──► <script src="https://snorklee.com/w.js">             │
│                  ❌ ERR_BLOCKED_BY_CLIENT                                 │
│                                                                          │
│   navigatore ──► POST https://snorklee.com/api/event                  │
│                  ❌ ERR_BLOCKED_BY_CLIENT                                 │
│                                                                          │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│                                                                          │
│   DOPO (1st-party via il tuo proxy, mai bloccato)                        │
│   ────────────────────────────────────────────                           │
│                                                                          │
│   navigatore ──► <script src="/js/flow.js"> su miosito.com               │
│                  ✅ servito dal tuo proxy da snorklee.com             │
│                                                                          │
│   navigatore ──► POST miosito.com/api/event                              │
│                  ✅ inoltrato dal tuo proxy verso snorklee.com        │
│                                                                          │
└──────────────────────────────────────────────────────────────────────────┘

Stai facendo il proxy del tracker e di 2 endpoint API dal tuo dominio verso snorklee.com:

Percorso sul tuo dominioDestinazione su snorkleeRuolo
/js/flow.jssnorklee.com/w.jsScript del tracker
/api/eventsnorklee.com/api/eventPageview + eventi personalizzati
/api/pingsnorklee.com/api/pingHeartbeat "live" ogni 30 s

Lo snippet da incollare nell'<head> diventa:

<script defer src="/js/flow.js" data-site="miosito.com"></script>

Tutti i percorsi sono in 1st-party, nessuno esce verso un dominio di terze parti dal browser. Lato server, il tuo proxy fa da ponte con snorklee.com in modo trasparente.

Importante — preservazione dell'IP visitatore: il tuo proxy deve trasmettere l'header X-Forwarded-For correttamente, altrimenti la geolocalizzazione lato snorklee ricade sull'IP del tuo proxy invece di quello del visitatore. Ogni ricetta qui sotto lo include esplicitamente.

Ricetta 1 — Nginx (la più universale)

Funziona su: qualsiasi VPS Linux (OVH, Scaleway, Hetzner, Clever Cloud con runtime Nginx, IONOS, Infomaniak, ecc.).

Sovranità: neutrale (dipende dal tuo provider; scegli UE).

Aggiungi questo blocco nel tuo file di configurazione Nginx, all'interno del server { ... } che serve il tuo sito (tipicamente /etc/nginx/sites-available/miosito.conf):

# snorklee — proxy 1st-party (anti-blocco)
location = /js/flow.js {
    proxy_pass        https://snorklee.com/w.js;
    proxy_set_header  Host snorklee.com;
    proxy_ssl_server_name on;
    proxy_set_header  X-Forwarded-For $remote_addr;
    proxy_set_header  X-Real-IP       $remote_addr;
    proxy_set_header  User-Agent      $http_user_agent;
    proxy_set_header  Accept-Language $http_accept_language;
    proxy_hide_header Set-Cookie;
    proxy_read_timeout 10s;
}

location ~ ^/api/(event|ping)$ {
    proxy_pass        https://snorklee.com$request_uri;
    proxy_set_header  Host snorklee.com;
    proxy_ssl_server_name on;
    proxy_set_header  X-Forwarded-For $remote_addr;
    proxy_set_header  X-Real-IP       $remote_addr;
    proxy_set_header  User-Agent      $http_user_agent;
    proxy_set_header  Accept-Language $http_accept_language;
    proxy_set_header  Origin          $http_origin;
    proxy_hide_header Set-Cookie;
    proxy_read_timeout 10s;
}

Poi testa e ricarica:

sudo nginx -t && sudo systemctl reload nginx

Verifica: dal tuo browser, apri https://miosito.com/js/flow.js — dovresti vedere il codice del tracker minificato. Se ottieni un errore 502, verifica che proxy_ssl_server_name on; sia presente (obbligatorio per il SNI verso snorklee.com).


Ricetta 2 — Caddy (la più semplice)

Funziona su: qualsiasi server dove Caddy è in esecuzione (auto-TLS incluso).

Sovranità: neutrale (dipende dal tuo provider).

Nel tuo Caddyfile, all'interno del blocco del tuo sito:

miosito.com {
    # ... la tua configurazione esistente ...

    # snorklee — proxy 1st-party (anti-blocco)
    @snorkleeApi path /api/event /api/ping

    handle_path /js/flow.js {
        rewrite * /w.js
        reverse_proxy https://snorklee.com {
            header_up Host snorklee.com
            header_down -Set-Cookie
        }
    }

    handle @snorkleeApi {
        reverse_proxy https://snorklee.com {
            header_up Host snorklee.com
            header_down -Set-Cookie
        }
    }
}

Poi:

caddy reload --config /etc/caddy/Caddyfile
Sintassi Caddy 2.6+: si usa un matcher con nome (@snorkleeApi path …) per applicare handle a più percorsi. La forma handle /a /b /c { … } non è accettata dal parser e fa fallire caddy validate.
Caddy inietta X-Forwarded-For e X-Real-IP automaticamente, quindi non è necessario dichiararli esplicitamente come con Nginx.

Ricetta 3 — Apache (mod_proxy)

Funziona su: hosting condiviso OVH, Infomaniak, IONOS, e qualsiasi server Apache con mod_proxy attivato. Utile per siti WordPress su cPanel senza accesso root.

Sovranità: neutrale.

Nel tuo .htaccess (alla radice del sito) o <VirtualHost>:

# snorklee — proxy 1st-party (anti-blocco)
SSLProxyEngine On

# Lo script
RewriteEngine On
RewriteRule ^js/flow\.js$ https://snorklee.com/w.js [P,L]

# L'API
RewriteRule ^api/(event|ping)$ https://snorklee.com/api/$1 [P,L]

# Preservare l'IP visitatore (setifempty per non sovrascrivere un XFF a monte
# se sei dietro un altro LB/reverse-proxy che ne imposta già uno)
ProxyPreserveHost Off
RequestHeader setifempty X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader setifempty X-Real-IP       "%{REMOTE_ADDR}s"

# Non trasmettere mai cookie di sessione lato visitatore
Header always unset Set-Cookie

Moduli da attivare sul server (tipicamente già attivi sugli host FR seri): mod_proxy, mod_proxy_http, mod_ssl, mod_rewrite, mod_headers.

Su OVH condiviso, richiedi l'attivazione al supporto se necessario — è gratuita e standard.


Ricetta 4 — Bunny.net Edge Scripting

Per chi: siti ad alto traffico che vogliono un CDN edge più vicino al visitatore (guadagno di latenza + scarico del server di origine).

Presenza europea: Bunny.net è gestito da BunnyWay d.o.o. in Slovenia. Se vuoi mantenere il routing vicino all'Europa, limita le zone di pricing a Europe durante la configurazione.

Prezzi: ~0,01 €/milione di richieste Edge Script + ~0,005 €/GB di banda CDN. Per 1M pageview/mese, conta ~5 € in totale. Nessun abbonamento minimo, pagamento a consumo.

Passaggi:

  1. Crea un account su bunny.net (carta di credito, ~5 € di credito iniziale gratuito).
  2. Crea una "Pull Zone":
  • Scheda CDN → pulsante Add Pull Zone
  • Name: miosito-snorklee (libero)
  • Origin URL: https://snorklee.com
  • Pricing tier: Standard
  • Pricing zones: puoi lasciare solo Europe se vuoi limitare routing e costi a quella zona
  1. Collega il tuo dominio via CNAME:
  • Scheda HostnamesAdd Hostnameflow.miosito.com
  • Presso il tuo registrar DNS (Gandi, OVH, ecc.): crea un record CNAME flow.miosito.com → miosito-snorklee.b-cdn.net
  • Attendi 5 min, torna su Bunny → clicca Generate Free SSL Certificate (Let's Encrypt automatico)
  1. Mappa il percorso:
  • Scheda Edge RulesAdd Edge Rule
  • Action: Override URL
  • Match: Request URL contains "/js/flow.js"
  • Override URL: https://snorklee.com/w.js
  • Salva
  1. Snippet finale:
<script defer src="https://flow.miosito.com/js/flow.js" data-site="miosito.com"></script>

Tutti i percorsi /api/* passano automaticamente verso snorklee.com/api/* tramite la Pull Zone.

Nota IP visitatore: Bunny aggiunge X-Forwarded-For correttamente per impostazione predefinita. Verifica nella scheda Dashboard, sezione Pubblico, card Paesi, che i paesi vengano rilevati correttamente dopo 1-2 ore.

Ricetta 5 — Next.js / Nuxt rewrites

Per chi: siti con stack JavaScript moderno il cui hosting supporta rewrite o route server.

Hosting: verifica che la piattaforma conservi gli header utili (X-Forwarded-For, metodo HTTP, User-Agent, Accept-Language) e che la regione di esecuzione scelta corrisponda alle tue esigenze di privacy e performance.

Opzioni possibili: hosting Node/SSR classico, serverless con regione esplicita, container Docker o piattaforma frontend che espone rewrite lato server.

Next.js — in next.config.js:

module.exports = {
  async rewrites() {
    return [
      {
        source: '/js/flow.js',
        destination: 'https://snorklee.com/w.js',
      },
      {
        source: '/api/event',
        destination: 'https://snorklee.com/api/event',
      },
      {
        source: '/api/ping',
        destination: 'https://snorklee.com/api/ping',
      },
    ];
  },
};

Nuxt 3 — in nuxt.config.ts:

export default defineNuxtConfig({
  routeRules: {
    '/js/flow.js': { proxy: 'https://snorklee.com/w.js' },
    '/api/event': { proxy: 'https://snorklee.com/api/event' },
    '/api/ping': { proxy: 'https://snorklee.com/api/ping' },
  },
});
I rewrites Next/Nuxt preservano automaticamente X-Forwarded-For e il metodo HTTP. Gli eventi POST vengono trasmessi correttamente.

Scegliere l'hosting

Il proxy first-party funziona con molti hosting. Prima di scegliere una piattaforma, verifica soprattutto:

  • la regione di esecuzione realmente usata dal proxy;
  • il periodo di conservazione dei log lato hosting;
  • la trasmissione corretta di X-Forwarded-For;
  • la possibilità di rimuovere cookie o header inutili;
  • gli impegni contrattuali necessari per la tua policy privacy.

Verifica che funzioni

  1. Lo script si carica — apri https://miosito.com/js/flow.js nel tuo browser, dovresti vedere il codice del tracker minificato (inizia con !function()...).
  2. Gli eventi partono — apri DevTools (F12) → scheda Network, naviga nel tuo sito. Dovresti vedere una richiesta POST /api/event che risponde 204 No Content.
  3. La geolocalizzazione funziona — connettiti alla dashboard snorklee, attendi 1-2 minuti e verifica la card Paesi nella scheda Dashboard (sezione Pubblico). Se tutti i visitatori appaiono dal paese del tuo server proxy invece del loro vero paese, X-Forwarded-For non viene trasmesso. Rivedi la configurazione del proxy.
  4. Il tracker nella scheda Integrazione della dashboard — la sonda HTTP "Testa l'installazione" rileva automaticamente la modalità self-host e mostra "Proxy 1st-party rilevato" nel risultato.

Domande frequenti

Il proxy rallenta il mio sito? No, o in modo marginale. Il tracker flow.js pesa ≈ 2 KB gzip e rimane nella cache del browser. Gli eventi /api/* partono tramite sendBeacon non bloccante, quindi invisibili al visitatore anche se il proxy aggiunge 50 ms di latenza.

E se il mio proxy va in panne? Gli eventi vengono persi durante l'interruzione (nessuna coda offline, per dottrina §25 TDDDG / GDPR minimizzazione). Il sito continua a funzionare normalmente, si ferma solo la misurazione dell'audience. Come qualsiasi altro servizio di terze parti in panne (Google Analytics, Plausible, ecc.).

Posso fare il proxy solo dello script e non dell'API? Sì, con l'attributo data-api:

<script defer src="/js/flow.js" data-site="miosito.com" data-api="https://snorklee.com"></script>

Lo script viene servito in 1st-party (supera i blocchi basati sul nome del file), ma gli eventi partono direttamente verso snorklee.com (nuovamente bloccati dai blocchi basati sul dominio). È meno efficace della ricetta completa e non lo raccomandiamo — è documentato qui per casi particolari.

E se voglio cambiare provider di analytics in seguito? La struttura del proxy rimane la stessa, cambi solo i domini di destinazione. Lo snippet <script src="/js/flow.js" data-site="..."> è universale.


Hai bisogno di aiuto?

  • 🛠️ Scheda Integrazione della dashboard → pulsante Testa l'installazione (sonda HTTP automatica)
  • 📧 Contatto protezione dati/supporto: vedi la scheda Conformità della dashboard
  • 📚 Documentazione completa: /docs