Analítica sin vigilancia
Lo que Google Analytics realmente le cuesta
بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ
Tamaño
Espaciado
Fuente
- Tiene un sitio web. ¿Sabe lo que pasa en él?
- Cómo se ve la alternativa
- ¿Quién puede ver el panel?
- Lo que corre por debajo
- Pero los visitantes necesitan llegar a él
- El problema invisible: los bloqueadores de anuncios
- Hacer desaparecer la analítica
- Cuando la configuración le engaña
- El lado de Astro
- Por qué la receta se queda privada
- ¿Y la velocidad de la página?
- A lo que se reduce todo
Tiene un sitio web. ¿Sabe lo que pasa en él?
La mayoría no lo sabe. Este tampoco lo sabía. El sitio estaba en línea, se subían páginas, se escribían entradas, el contenido se traducía a cinco idiomas. Nada de eso producía una sola señal de si alguien estaba leyendo. No había recuento de páginas vistas ni datos de referente, ni manera de saber si la página de inicio estaba haciendo su trabajo o si los visitantes se iban de inmediato.
La respuesta evidente es Google Analytics. Se pone una etiqueta de script, se obtiene un panel. La mayoría de los sitios hace exactamente eso. Pero Google Analytics no es gratis. Usted paga con los datos de sus visitantes. Google combina cada visita a página con todo lo demás que sabe sobre esa persona: historial de búsqueda, hábitos en YouTube, datos de ubicación. Su sitio se convierte en un punto más de un perfil que su visitante nunca consintió construir.
Está además el problema del RGPD. Si su negocio atiende a visitantes de la UE, Google Analytics exige un banner de consentimiento legalmente conforme. La mayoría de las implementaciones lo hace mal. El riesgo legal es real.
El sitio necesitaba analítica. No de Google.
Definiciones rápidas
¿Qué significa autoalojado?
Software que corre en un servidor que usted controla, no en la plataforma de un tercero. Los datos, la configuración y el acceso se quedan con usted.
¿Qué es la analítica respetuosa con la privacidad?
Una manera de contar y entender a los visitantes de su sitio sin identificarlos como individuos. Sin rastreo entre sitios, sin perfil de su otra navegación, sin un tercero que toque los datos. Usted ve lo que pasa en su sitio; nadie más.
¿Qué es una red privada?
Una red que solo los miembros pueden ver. Los dispositivos fuera de la red ni siquiera saben que los servicios que están en ella existen, así que herramientas de administración como un panel de analítica pueden funcionar ahí sin aparecer en internet en absoluto.
Cómo se ve la alternativa
La herramienta se llama Umami.
Open source, con licencia MIT, respetuosa con la privacidad, sin cookies. Corre en su propio servidor. Inshallah los datos nunca saldrán de su infraestructura. No hace falta banner de consentimiento porque no hay nada a lo que consentir. Sin cookies, sin datos personales, sin rastreo entre sitios.
Lo que le da: páginas vistas, referentes, desglose por navegador y dispositivo, país de origen y eventos personalizados. Panel limpio, datos en tiempo real. Inshallah un empresario puede abrirlo y entender qué pasa, sin formación.
Lo que no le da: perfiles individuales de visitantes, grabaciones de sesión ni mapas de calor. No identifica a visitantes individuales. Le dice qué pasó en su sitio.
Umami ya corría en el servidor, detrás de una VPN privada. Ahí es donde empezaron las decisiones interesantes.
¿Quién puede ver el panel?
La mayoría de las guías de analítica autoalojada terminan con «visite su-dominio.com e inicie sesión». Su panel de analítica queda entonces en la internet pública. Cualquiera puede encontrarlo. Los escáneres automatizados lo descubrirán. Los bots probarán las credenciales por defecto.
El panel es una herramienta de administración. Tiene una página de inicio de sesión, una aplicación web y una base de datos detrás. Cada una de ellas es una superficie de ataque. Si usted se pierde una actualización de seguridad, el panel, y potencialmente el servidor, queda expuesto.
La instancia de Umami de este sitio no existe en la internet pública. Corre detrás de una red privada (NetBird).
El panel solo es accesible desde dispositivos que forman parte de esa red. Para todos los demás no hay página de inicio de sesión, ni mensaje de error, ni respuesta. El dominio resuelve a una IP que solo existe dentro de la VPN; desde internet no hay nada con lo que conectarse. No hay nada que atacar porque no hay nada que encontrar.
Es un principio que va mucho más allá de la analítica: la forma más alta de seguridad es no ser visible en primer lugar.
Lo que corre por debajo
El servicio de analítica corre como dos contenedores en un pod de Podman: PostgreSQL y la aplicación Next.js, compartiendo un espacio de nombres de red para que la aplicación llegue a la base de datos sin exponerla. Todo corre como un usuario dedicado de cuenta de servicio, sin shell, supervisado junto al resto de servicios del servidor. Beszel sigue la salud de los recursos (CPU, RAM, disco, red); Dozzle se encarga de los registros (lo que hace el servicio, los errores que ha encontrado). Recursos y registros responden preguntas distintas, y un servicio en el que se confía en producción necesita ambos.
Pero los visitantes necesitan llegar a él
Si el servicio de analítica está oculto de internet, ¿cómo le envían datos los navegadores de los visitantes?
No hablan directamente con el servicio de analítica. Hablan con el sitio mismo. El servidor web (Caddy) actúa como proxy y reenvía dos rutas concretas al servicio de analítica internamente. Con los valores por defecto documentados de Umami, eso se ve más o menos así:
(umami_proxy) { handle /umami.js { reverse_proxy 127.0.0.1:8089 }
handle /api/send { reverse_proxy 127.0.0.1:8089 }}Una ruta sirve el script de rastreo. La otra recibe los datos de analítica. Ambas se importan al bloque Caddy del sitio:
example.com { import tls_config root * /var/www/example.com import umami_proxy import static_files}Desde el punto de vista del visitante, ambas peticiones van al mismo dominio que el sitio, sin servicio externo y sin petición cross-origin. El navegador carga un script desde el sitio y envía datos de vuelta al sitio.
El servicio de analítica procesa todo entre bastidores, totalmente invisible para el visitante y totalmente inalcanzable desde fuera.
Para una empresa, ningún proveedor se sienta entre usted y su analítica. Inshallah los precios no cambien de la noche a la mañana, las funcionalidades no se pueden retirar y el producto no puede ser comprado y apagado. Los datos históricos se quedan en el servidor que usted controla, consultables y exportables en sus términos.
El problema invisible: los bloqueadores de anuncios
Los bloqueadores de anuncios bloquean también la analítica respetuosa con la privacidad.
Umami no usa cookies. No rastrea individuos. No comparte datos con nadie. Pero las principales listas de bloqueo (EasyPrivacy, uBlock Origin, AdGuard) incluyen reglas que apuntan a Umami específicamente. Los bloqueadores no evalúan la ética. Hacen coincidir patrones:
- Patrones de dominio: cualquier cosa con
analytics,statsotrackingen el subdominio - Nombres de script:
script.jsservido desde una herramienta de analítica conocida - Patrones de endpoint:
/api/sendestá específicamente en la entrada de la lista de bloqueo de Umami
Las estimaciones del uso de bloqueadores de anuncios suelen caer en el rango del 10 al 40 por ciento, más alto en públicos jóvenes y técnicamente avezados. Esos visitantes nunca aparecerán en su analítica. Tomará decisiones basadas en datos incompletos sin saber que están incompletos.
Autoalojar resuelve el problema de la soberanía de los datos. No resuelve el problema de los bloqueadores. La solución tiene que ir más allá.
Hacer desaparecer la analítica
La solución al problema de los bloqueadores es conceptual, no técnica. Haga que las peticiones de analítica parezcan recursos ordinarios del sitio. Otro nombre para el script, otra ruta para el endpoint, ambos confundiéndose con lo que el sitio ya carga. Los patrones de las listas de bloqueo dejan de coincidir.
Un proxy inverso asigna una ruta pública a lo que la aplicación espera internamente. El navegador ve una petición same-origin ordinaria; el servicio de analítica recibe los datos detrás.
Cuando la configuración le engaña
Esto fue lo que más tardó. Es donde se ve la diferencia entre «seguí una guía» y «entiendo el sistema».
Umami expone dos variables de entorno para el renombrado. TRACKER_SCRIPT_NAME controla el nombre de archivo bajo el que el servidor sirve el script de rastreo. COLLECT_API_ENDPOINT controla la ruta a la que el rastreador envía los datos. Ambas parecen configuración de tiempo de ejecución ordinaria.
TRACKER_SCRIPT_NAME lo es. El nombre del script se decide cuando el servidor responde a una petición. Se pone la variable, se reinicia, el servidor sirve el script bajo el nuevo nombre. Listo.
COLLECT_API_ENDPOINT es la trampa. Después de ponerla y reiniciar, el enrutamiento del lado del servidor obedeció. Aceptaba peticiones en la nueva ruta. Todo parecía correcto. Pero en el navegador, el rastreador seguía enviando a /api/send. El proxy no conocía esa ruta, así que los datos se perdían en el vacío. El panel mostraba cero visitantes. Ningún error en ningún sitio. Todo se veía bien. Nada funcionaba.
El código fuente explica por qué. El script de rastreo lo construye Rollup durante la construcción de la imagen Docker:
plugins: [ replace({ __COLLECT_API_ENDPOINT__: process.env.COLLECT_API_ENDPOINT || '/api/send', }),]El endpoint se compila como literal de cadena en la salida JavaScript. En tiempo de ejecución, la variable de entorno cambia dónde escucha el servidor, pero el navegador ejecuta código precompilado con la ruta vieja grabada dentro.
La imagen Docker oficial de ghcr.io/umami-software/umami se entrega con /api/send codificado en duro en el script de rastreo. Poner COLLECT_API_ENDPOINT a un valor nuevo en el archivo .env hace que el servidor acepte peticiones en la ruta nueva, pero el rastreador sigue diciéndole al navegador que envíe a /api/send. Los dos lados se contradicen en silencio.
La solución es construir la imagen desde las fuentes con el nuevo valor incorporado en tiempo de compilación. El Dockerfile de Umami no expone esta variable como argumento de build de fábrica, pero dos líneas en la fase del builder cierran ese hueco:
ARG COLLECT_API_ENDPOINT=/api/sendENV COLLECT_API_ENDPOINT=$COLLECT_API_ENDPOINTARG declara una variable de tiempo de build; ENV la hace visible a Rollup para que el valor se compile dentro del script de rastreo. Con esas dos líneas en su sitio, construir con un valor personalizado es una sola bandera:
podman build --build-arg COLLECT_API_ENDPOINT=<your-endpoint> -t umami-custom:latest .El resultado es la misma imagen que la oficial, con una cadena distinta en un solo archivo JavaScript.
Si el host corre Podman en modo rootless con un usuario de cuenta de servicio aparte, la imagen construida bajo su usuario de desarrollo no es visible para ese usuario de servicio. Cada usuario rootless tiene un almacén de imágenes aislado. La transferencia son dos comandos:
podman save localhost/umami-custom:latest -o /tmp/umami-custom.tarcd /tmp && sudo -u umami podman load -i /tmp/umami-custom.tarEl cd /tmp importa. sudo -u umami hereda por defecto el directorio de trabajo del que llama. Si su shell está dentro de su home de desarrollo, la carga falla con cannot chdir: Permission denied porque el usuario de servicio no puede leer dentro de su home. El error apunta a chdir, no a sudo ni a podman, así que la causa no es obvia la primera vez que muerde.
Eso cubre cómo se ve un build personalizado de Umami en general. Lo que este sitio pone en <your-endpoint>, y la ruta de script que coincide y que el proxy público reescribe, no está en esta entrada.
El lado de Astro
El script de rastreo necesita cargarse en cada página. En Astro, eso quiere decir añadirlo al layout compartido:
<script is:inline defer src="/umami.js" data-website-id="..." data-host-url="/"></script>Algunas notas.
is:inline le dice a Astro que deje la etiqueta de script exactamente como está escrita y que no la procese ni la empaquete. El rastreador es un script de terceros del tipo fire-and-forget; no necesita la pipeline de empaquetado de Astro.
defer carga el script sin bloquear el renderizado de la página. La analítica nunca debe ralentizar la página.
La referencia de Astro añade una nota que se lee más amplia que su alcance real:
Will not be bundled into an external file. This means that attributes like
deferwhich control the loading of an external file will have no effect.
Eso describe el caso del contenido inline, donde no hay archivo externo cuya carga pueda diferirse. Para un script con src, is:inline solo le dice a Astro que no procese la etiqueta. La salida dist la emite tal cual con defer intacto, y el navegador aplica el atributo con normalidad.
data-host-url="/" sobrescribe la URL base que el rastreador usa para construir su endpoint. Sin eso, el rastreador deriva la base desde la propia ubicación del script. Un script en una ruta de subdirectorio (digamos /path/to/umami.js) enviaría a /path/to/api/... en lugar de a /api/.... Poner el valor a / (o a la raíz del sitio, sea cual sea) lo mantiene correcto.
Este sitio también tiene un 404.html autónomo que está fuera de la pipeline de Astro (un rodeo a un bug de enrutamiento del framework, documentado en una entrada aparte).
La misma etiqueta de script se añade ahí a mano, ya que no pasa por el layout compartido.
Por qué la receta se queda privada
La solución conceptual ya está nombrada: hacer que el script y el endpoint parezcan recursos ordinarios del sitio. Este sitio lo hace. Los nombres concretos, y el razonamiento que ata la elección de nombres al perfil de contenido de un sitio, no están en esta entrada.
El coste de hacer esto es real. La imagen aguas arriba se puede actualizar con podman pull. Un build personalizado quiere decir reconstruir desde las fuentes en cada lanzamiento aguas arriba.
Los bloqueadores de anuncios existen porque los rastreadores se ganaron la desconfianza. La mayor parte de la analítica en internet realmente es vigilancia: scripts de terceros, fingerprinting, datos pasados aguas abajo. Los bloqueadores no pueden distinguir qué sitios son honestos. Bloquean los patrones.
Una contramedida basada en coincidencia de patrones ayuda por igual a sitios honestos y deshonestos. Una entrada pública con una receta que funciona es la misma llave en manos de un dentista que cuenta sus citas y de una empresa de rastreo que intenta volver a poner su píxel en la pantalla de alguien. El primer uso está bien. El segundo es lo que hizo necesarios a los bloqueadores.
Por eso la entrada se detiene en el principio.
La configuración completa, los nombres concretos y el razonamiento detrás de cómo se eligen para un sitio dado, se queda fuera de la documentación pública por el motivo de arriba. Si eso es relevante para su situación, la página Acerca de es por donde empezar.
¿Y la velocidad de la página?
Un sitio rápido retiene visitantes. Las páginas lentas pierden gente, caen en el ranking de búsqueda y se sienten poco profesionales. La analítica tiene que pesarse frente a ese coste.
Hay una solución conocida para scripts de analítica pesados: Partytown. Mueve el script a un hilo en segundo plano para que la página principal siga respondiendo mientras el rastreador hace su trabajo. Para sitios que cargan algo como Google Tag Manager o Facebook Pixel (50 a 200 KB de JavaScript que sondea e inyecta de forma continua), Partytown es una ganancia de velocidad real.
Esta configuración no la necesita.
El rastreador de Umami pesa 2,63 KB sin comprimir, 1,43 KB después de gzip. Carga con defer, dispara una sola petición POST cuando se visita una página y termina.
Añadir Partytown haría las cosas más lentas. Su runtime ronda los 15 KB tras gzip, todo cargado en el navegador del visitante: un cargador de 1,2 KB más un worker de 13,6 KB que intercepta peticiones en segundo plano. Nada de eso corre en el servidor. Envolver un script de 1,43 KB en 15 KB de sobrecarga es diez veces más JavaScript que el script en sí.
La respuesta honesta es la más sencilla. Un rastreador lo bastante pequeño como para que la página siga rápida porque nada la está ralentizando.
A lo que se reduce todo
Cada pieza de esta configuración resuelve un problema concreto. Umami sustituye a Google Analytics sin la vigilancia. La red privada mantiene el panel fuera de internet. El proxy de Caddy permite a los visitantes llegar a la analítica a través del sitio mismo. El problema de los bloqueadores tiene una solución que esta entrada señala sin recorrerla. Cada decisión por sí sola es pequeña.
Juntas deciden dos cosas: si usted sabe lo que pasa en su sitio y si la relación con sus visitantes se queda con usted.
Inshallah merece la pena hacerlo bien.
¿Necesito el rodeo a los bloqueadores de anuncios, o basta con autoalojar?
Autoalojar por sí solo resuelve la cuestión de la soberanía de los datos. El problema de los bloqueadores de anuncios es independiente: con los endpoints por defecto, una proporción conocida de sus visitantes seguirá sin aparecer en sus números.
Si su único objetivo es dejar de entregar datos a Google, una instalación por defecto de Umami basta. Si quiere que el conteo de visitantes refleje la realidad, el enfoque de renombrar a través del proxy es el que cierra esa brecha.
¿Cuánto cuesta esto en comparación con Google Analytics?
Coste de servidor, no de suscripción. La huella es una base de datos y una pequeña aplicación Node.js que corre junto a lo demás que ya aloja. No hay precios por visita, por evento ni por funcionalidad. El modelo es: usted paga por el servidor que ya necesita.
¿Umami cumple el RGPD desde la instalación?
Más cerca que Google Analytics, pero no de forma automática. Umami no usa cookies y no comparte datos con terceros, lo que elimina los fallos de cumplimiento más comunes.
Algunas partes siguen necesitando su atención: su política de privacidad, el país donde corre su servidor y si almacena direcciones IP.
¿Puedo migrar mi histórico de Google Analytics?
En general, no. Umami empieza a recoger desde el momento en que se instala; los datos históricos de GA se quedan dentro del producto de Google. Algunas personas exportan informes de GA para archivo, pero las métricas no encajan con la limpieza suficiente para fusionarse con Umami a partir de ahí.
Setups 1 de 1
Volver a SetupsIngeniero aeroespacial
Emprendedor ético en público
Tú te ocupas de tu negocio
Yo me encargo del lado digital
Trabaja conmigo
- IA con honestidad
- Infraestructura privada
- Sitios web que rinden
Cuéntame sobre tu situación:
javed@javedab.com Más sobre mí