Servir el código de Snorklee desde tu dominio (anti-bloqueo)
Chrome 121+, uBlock Origin, Brave Shields, AdGuard y la mayoría de bloqueadores de anuncios bloquean por defecto cualquier llamada hacia un dominio externo etiquetado como "analytics" — aunque el servicio no haga ninguna publicidad ni ningún seguimiento publicitario, que es nuestro caso.
Si no haces nada, pierdes hoy del 5 al 20 % de tus visitas, y esa proporción subirá al 30-50 % en 12-24 meses, cuando Chrome extienda su Tracking Protection a todas las sesiones (no solo la navegación privada).
La solución: servir el código de Snorklee y la API desde tu propio dominio. El navegador ve entonces una llamada "1st-party", imposible de distinguir de la carga de una imagen o una hoja de estilos. Y eso no lo bloquea ningún bloqueador.
Esta página te muestra cómo, con configuraciones first-party pensadas para una infraestructura europea. Elige el alojamiento y la región de ejecución según tus necesidades de cumplimiento, rendimiento y soporte.
WordPress — pasa por el plugin oficial
En WordPress, no te pongas a configurar Nginx, Caddy o el DNS. El plugin oficial Snorklee Analytics 2.3.4+ ya hace todo el trabajo:
- Instala o actualiza el plugin desde el panel Snorklee o desde la página Plugin WordPress de Snorklee.
- En wp-admin, abre Snorklee.
- Verifica el dominio del sitio y deja la URL del panel en
https://snorklee.com, salvo instancia self-hosted. - Activa Self-host mode y guarda.
- Lanza Probar la instalación. El resultado debe indicar self-host o proxy first-party detectado.
El plugin sirve /js/flow.js desde WordPress, reenvía /api/event y /api/ping, mantiene el código JavaScript en caché durante 1 hora (mediante Transients API) y no almacena ningún evento en WordPress.
Cómo funciona — esquema general
┌──────────────────────────────────────────────────────────────────────────┐
│ │
│ ANTES (3rd-party, bloqueado) │
│ ───────────────────────── │
│ │
│ navegador ──► <script src="https://snorklee.com/w.js"> │
│ ❌ ERR_BLOCKED_BY_CLIENT │
│ │
│ navegador ──► POST https://snorklee.com/api/event │
│ ❌ ERR_BLOCKED_BY_CLIENT │
│ │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ │
│ DESPUÉS (1st-party vía tu proxy, nunca bloqueado) │
│ ───────────────────────────────────────────── │
│ │
│ navegador ──► <script src="/js/flow.js"> en misiitio.com │
│ ✅ servido por tu proxy desde snorklee.com │
│ │
│ navegador ──► POST misitio.com/api/event │
│ ✅ retransmitido por tu proxy hacia snorklee.com │
│ │
└──────────────────────────────────────────────────────────────────────────┘
Reenvías el script y 2 endpoints API desde tu dominio hacia snorklee.com:
| Ruta en tu dominio | Destino en snorklee | Función |
|---|---|---|
/js/flow.js | snorklee.com/w.js | Script del tracker |
/api/event | snorklee.com/api/event | Pageviews + eventos personalizados |
/api/ping | snorklee.com/api/ping | Heartbeat "live" cada 30 s |
El código que pegas en tu <head> se convierte en:
<script defer src="/js/flow.js" data-site="misitio.com"></script>
Todas las rutas son 1st-party: visto desde el navegador, nada sale hacia un dominio externo. Es tu proxy el que, en el servidor, hace el puente con snorklee.com sin que el visitante lo note.
Lo que cuesta el reenvío — la dirección del visitante: cuando tu servidor reenvía/api/event, lo vemos a él, nunca al navegador. La dirección que transmites enX-Forwarded-Forsí nos llega, pero nos negamos a geolocalizarla: en un punto de entrada público cualquiera podría declarar la dirección que quisiera. En una instalación con reenvío no hay, por tanto, ni país ni región, y los visitantes únicos dejan de ser fiables (se derivan de esa misma dirección: visitantes distintos se funden en uno). No es la única medición afectada: la clave de visita se deriva de esa misma dirección, así que la atribución de fuentes, la distinción directo/IA, los visitantes en directo y la interacción también dejan de ser fiables, y el tope antiabuso (50 peticiones por minuto y dirección) se aplica ahora a todo tu sitio de golpe. Las páginas vistas y las pasadas de robots sí siguen contándose. Snorklee te lo señala en la cola de decisiones en lugar de dibujar un mapa falso. Conserva igualmenteX-Forwarded-Foren las recetas de abajo: es lo que permite verificar la identidad de los robots IA. Si el mapa te importa más que el anti-bloqueo, reenvía solo el script (mira las FAQ al final de la página).
Receta 1 — Nginx (la más universal)
Funciona en: cualquier VPS Linux (OVH, Scaleway, Hetzner, Clever Cloud con runtime Nginx, IONOS, Infomaniak, etc.).
Soberanía: neutra (depende de tu proveedor de alojamiento; elige UE).
Añade este bloque en tu archivo de configuración Nginx, dentro del server { ... } que sirve tu sitio (normalmente /etc/nginx/sites-available/misitio.conf):
# snorklee — proxy 1st-party (anti-bloqueo)
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;
}
Luego prueba y recarga:
sudo nginx -t && sudo systemctl reload nginx
Para comprobar: abre https://misitio.com/js/flow.js en tu navegador — debes ver el código de Snorklee minificado. Si aparece el error 502, comprueba que proxy_ssl_server_name on; esté presente (obligatorio para el SNI hacia snorklee.com).
Receta 2 — Caddy (la más sencilla)
Funciona en: cualquier servidor donde corra Caddy (TLS automático incluido).
Soberanía: neutra (depende de tu proveedor de alojamiento).
En tu Caddyfile, dentro del bloque de tu sitio:
misitio.com {
# ... tu configuración existente ...
# snorklee — proxy 1st-party (anti-bloqueo)
@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
}
}
}
Luego:
caddy reload --config /etc/caddy/Caddyfile
Sintaxis Caddy 2.6+: se usa un matcher con nombre (@snorkleeApi path …) para aplicarhandlea varias rutas. La formahandle /a /b /c { … }no es aceptada por el parser y hace fallarcaddy validate.
Caddy inyectaX-Forwarded-ForyX-Real-IPautomáticamente, por lo que no es necesario declararlos explícitamente como en Nginx.
Receta 3 — Apache (mod_proxy)
Funciona en: alojamiento compartido OVH, Infomaniak, IONOS y cualquier servidor Apache con mod_proxy activado. Útil para sitios WordPress en cPanel sin acceso root.
Soberanía: neutra.
En tu .htaccess (en la raíz del sitio) o <VirtualHost>:
# snorklee — proxy 1st-party (anti-bloqueo)
SSLProxyEngine On
# El script
RewriteEngine On
RewriteRule ^js/flow\.js$ https://snorklee.com/w.js [P,L]
# La API
RewriteRule ^api/(event|ping)$ https://snorklee.com/api/$1 [P,L]
# Preservar la IP del visitante (setifempty para no sobreescribir un XFF previo
# si estás detrás de otro LB/reverse-proxy que ya lo añade)
ProxyPreserveHost Off
RequestHeader setifempty X-Forwarded-For "%{REMOTE_ADDR}s"
RequestHeader setifempty X-Real-IP "%{REMOTE_ADDR}s"
# No transmitir nunca cookies de sesión al visitante
Header always unset Set-Cookie
Módulos a activar en el servidor (normalmente ya activos en alojadores FR serios): mod_proxy, mod_proxy_http, mod_ssl, mod_rewrite, mod_headers.
En OVH compartido, solicita la activación al soporte si es necesario — es gratuito y estándar.
Receta 4 — Bunny.net Edge Scripting
Para quién: sitios de alto tráfico que quieren un CDN edge más cercano al visitante (ganancia de latencia + descarga del servidor de origen).
Presencia europea: Bunny.net está operado por BunnyWay d.o.o. en Eslovenia. Si quieres mantener el enrutamiento cerca de Europa, limita las zonas de pricing a Europe durante la configuración.
Precios: ~0,01 €/millón de solicitudes Edge Script + ~0,005 €/GB de ancho de banda CDN. Para 1M pageviews/mes, cuenta ~5 € en total. Sin suscripción mínima, pago por uso.
Pasos:
- Crear una cuenta en bunny.net (tarjeta bancaria, ~5 € de crédito inicial gratuito).
- Crear una "Pull Zone":
- Pestaña CDN → botón Add Pull Zone
- Name:
misitio-snorklee(libre) - Origin URL:
https://snorklee.com - Pricing tier: Standard
- Pricing zones: puedes mantener solo Europe si quieres limitar el enrutamiento y los costes a esa zona
- Conectar tu dominio por CNAME:
- Pestaña Hostnames → Add Hostname →
flow.misitio.com - En tu registrar DNS (Gandi, OVH, etc.): crear un registro
CNAME flow.misitio.com → misitio-snorklee.b-cdn.net - Esperar 5 min, volver a Bunny → clic en Generate Free SSL Certificate (Let's Encrypt automático)
- Mapear la ruta:
- Pestaña Edge Rules → Add Edge Rule
- Action: Override URL
- Match:
Request URL contains "/js/flow.js" - Override URL:
https://snorklee.com/w.js - Guardar
- Snippet final:
<script defer src="https://flow.misitio.com/js/flow.js" data-site="misitio.com"></script>
Todas las rutas /api/* pasan automáticamente hacia snorklee.com/api/* a través de la Pull Zone.
Nota: Bunny transmite X-Forwarded-For por defecto, y es lo que permite verificar la identidad de los robots IA. El mapa de países, en cambio, se queda vacío en cualquier instalación con reenvío — mira el recuadro al principio de la página.
Receta 5 — Next.js / Nuxt rewrites
Para quién: sitios con stack JavaScript moderno cuyo alojamiento admite rewrites o rutas de servidor.
Alojamiento: comprueba que tu plataforma conserva los headers útiles (X-Forwarded-For, método HTTP, User-Agent, Accept-Language) y que la región de ejecución elegida corresponde a tus necesidades de privacidad y rendimiento.
Opciones posibles: alojamiento Node/SSR clásico, serverless con región explícita, contenedor Docker o plataforma frontend que exponga rewrites del lado servidor.
Next.js — en 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 — en 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' },
},
});
Los rewrites de Next/Nuxt preservan automáticamente X-Forwarded-For y el método HTTP. Los eventos POST pasan correctamente.
Elegir tu alojamiento
El proxy first-party funciona con muchos alojamientos. Antes de elegir uno, fíjate sobre todo en:
- la región de ejecución que utiliza realmente el proxy;
- el periodo de conservación de logs del alojamiento;
- la transmisión correcta de
X-Forwarded-For(sirve para verificar la identidad de los robots IA, no para situar a tus visitantes); - la posibilidad de retirar cookies o headers innecesarios;
- los compromisos contractuales que necesitas para tu propia política de privacidad.
Verificar que funciona
- El script se carga — abre
https://misitio.com/js/flow.jsen tu navegador: debes ver el código de Snorklee minificado (comienza por!function()...). - Los eventos se envían — abre DevTools (F12) → pestaña Network, luego navega por tu sitio. Debes ver una solicitud
POST /api/eventque responde204 No Content. - Lo que no vas a ver — en una instalación con reenvío la tarjeta Países se queda vacía y los visitantes únicos son aproximados: es lo esperado, no un fallo de configuración (mira el recuadro al principio de la página). Hoy ninguna configuración del proxy lo cambia.
- El resultado en la pestaña Integración — la sonda "Probar instalación" detecta el modo self-host por sí sola e indica "Proxy 1st-party detectado" en el resultado.
Preguntas frecuentes
¿El proxy ralentiza mi sitio? No, o apenas. El código flow.js pesa ≈ 2 KB gzip y permanece en caché del navegador. Los eventos /api/* se envían mediante sendBeacon, que no bloquea nada: el visitante no nota ninguna diferencia, aunque el proxy añada 50 ms.
¿Y si mi proxy falla? Los eventos de ese rato se pierden (sin cola offline — es una decisión asumida, §25 TDDDG / minimización RGPD). Tu sitio, en cambio, sigue funcionando con normalidad: solo se detiene la medición de audiencia. Como cualquier otro servicio de terceros en fallo (Google Analytics, Plausible, etc.).
¿Puedo reenviar solo el script y no la API? Sí, con el atributo data-api:
<script defer src="/js/flow.js" data-site="misitio.com" data-api="https://snorklee.com"></script>
El script se sirve en 1st-party (esquiva los bloqueadores que filtran por el nombre de archivo), pero los eventos vuelven directamente a snorklee.com, donde los bloqueadores que filtran por dominio los rebloquean. Es un equilibrio, no una media tinta: pierdes la parte de visitas bloqueadas y, a cambio, conservas el país de tus visitantes y visitantes únicos fiables — algo que el reenvío completo no puede devolverte.
¿Y si quiero cambiar de herramienta de analytics más adelante? La estructura del proxy no cambia: solo modificas los dominios de destino. El código <script src="/js/flow.js" data-site="..."> es el mismo en todas partes.
¿Necesitas ayuda?
- 🛠️ Pestaña Integración del panel → botón Probar instalación (sonda HTTP automática)
- 📧 Contacto de protección de datos/soporte: ver la pestaña Conformidad del panel
- 📚 Documentación completa: /docs