contar lectores sin seguirlos

10 de septiembre de 2026 meta analyticsprivacysvelte

Quería saber si alguien realmente lee este blog. No quiénes son, solo si las publicaciones en las que paso las noches se ven, en qué páginas aterriza la gente, y si se quedan o se van enseguida. La respuesta normal es pegar un script de alguna empresa de analítica y dejar que ellos lo averigüen, pero todo el sentido de este proyecto es que nada sale de mi servidor. Así que lo construí yo mismo.

Las reglas que fijé antes de escribir una sola línea de código: nada de terceros, nada se recopila antes de que el visitante diga que sí, y nada se almacena que pueda identificar a una persona. Lo que se guarda es un id de visitante aleatorio (un UUID que el navegador inventa por sí mismo, nada derivado de ti), la ruta que visitaste con los parámetros de consulta eliminados, y el referente solo si viniste de otro sitio. Ninguna dirección IP en la tabla de analítica, ningún user agent, nada de fingerprinting.

El consentimiento es un pequeño banner con una elección real, y la elección se recuerda. Di que no (o no digas nada) y el código de analítica simplemente nunca arranca. Di que sí y el navegador acuña su propio id y empieza a reportar vistas de página. También hay un interruptor en el pie de página para cambiar de opinión más tarde, que elimina la cookie.

The analytics tab in admin, pageviews and visitors over the last days

La parte que más me gusta es cómo funciona el "tiempo en la página". En lugar de rastrear cuándo te vas (algo que los navegadores hacen poco fiable de todos modos), la página envía un pequeño latido cada 15 segundos, pero solo mientras la pestaña está realmente visible:

function startHeartbeat() {
    stopHeartbeat();
    heartbeatTimer = setInterval(() => {
        if (document.visibilityState === 'visible') sendEvent('heartbeat');
    }, HEARTBEAT_INTERVAL_MS);
}

Así que una publicación dejada abierta en una pestaña de fondo todo el día no cuenta para nada, y cuatro latidos significan que alguien realmente miró la página durante un minuto. Tiempo de lectura medido de una forma que no puede mentir demasiado en ninguna de las dos direcciones.

El endpoint recolector del servicio de blog responde 204 pase lo que pase. Payload incorrecto, límite de tasa alcanzado, base de datos caída, dice 204. No hay nada útil que un atacante pueda aprender probándolo, y un pipeline de analítica roto nunca debería romper la página real para un lector. Los eventos de más de 90 días se eliminan automáticamente, porque la analítica de la temporada pasada es trivia, no información.

El error que vale la pena admitir: la primera versión del banner de consentimiento pedía consentimiento sin enlazar a la política de privacidad, así que te pedía aceptar algo que nunca explicaba. La revisión de código lo detectó. El banner ahora enlaza a la política, y la política obtuvo una sección que explica exactamente qué se recopila (la lista de arriba) y qué no. También faltaba una bandera Secure en la cookie de visitante, que se corrigió con el mismo arreglo.

El panel de administración obtuvo una pestaña de analítica donde por fin puedo ver los números: vistas de página, visitantes únicos, páginas más vistas, referentes, y cuánto tiempo se queda la gente. Resulta que algunos de vosotros sí leéis las publicaciones largas. Eso fue genuinamente agradable de aprender, y lo aprendí sin saber ni una sola cosa sobre quiénes sois.

0 comentarios

Inicia sesión para comentar.

Iniciar sesión

¿Olvidaste tu contraseña?

¿No tienes cuenta?