Aller au contenu
snorklee
Trafic IA Analytics Tarifs Manifeste Documentation Contact Connexion Essai gratuit 14 jours

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:

  1. Instala o actualiza el plugin desde el panel Snorklee o desde la página Plugin WordPress de Snorklee.
  2. En wp-admin, abre Snorklee.
  3. Verifica el dominio del sitio y deja la URL del panel en https://snorklee.com, salvo instancia self-hosted.
  4. Activa Self-host mode y guarda.
  5. 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 dominioDestino en snorkleeFunción
/js/flow.jssnorklee.com/w.jsScript del tracker
/api/eventsnorklee.com/api/eventPageviews + eventos personalizados
/api/pingsnorklee.com/api/pingHeartbeat "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 en X-Forwarded-For sí 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 igualmente X-Forwarded-For en 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 aplicar handle a varias rutas. La forma handle /a /b /c { … } no es aceptada por el parser y hace fallar caddy validate.
Caddy inyecta X-Forwarded-For y X-Real-IP automá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:

  1. Crear una cuenta en bunny.net (tarjeta bancaria, ~5 € de crédito inicial gratuito).
  2. 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
  1. Conectar tu dominio por CNAME:
  • Pestaña HostnamesAdd Hostnameflow.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)
  1. Mapear la ruta:
  • Pestaña Edge RulesAdd Edge Rule
  • Action: Override URL
  • Match: Request URL contains "/js/flow.js"
  • Override URL: https://snorklee.com/w.js
  • Guardar
  1. 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

  1. El script se carga — abre https://misitio.com/js/flow.js en tu navegador: debes ver el código de Snorklee minificado (comienza por !function()...).
  2. Los eventos se envían — abre DevTools (F12) → pestaña Network, luego navega por tu sitio. Debes ver una solicitud POST /api/event que responde 204 No Content.
  3. 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.
  4. 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