[🛠] Limpiar el panel de estadísticas del blog
✨ Resumen de GPT-5.5
Registro de cómo corregí una página pública de estadísticas donde visitas y vistas se mezclaban, separando visitas por sesiones de 30 minutos de vistas por apertura de página en un panel legible también en móvil.
Justo después de crear la página pública de estadísticas del blog, ya había algo que no me cerraba.
Los números aparecían.
Pero sus nombres se mezclaban con demasiada facilidad.
Visitantes, visitas, vistas, sesiones, page views. En una pantalla de blog parecen términos parecidos, pero en el modelo de conteo no son lo mismo. Si un contador público los mezcla, los números dejan de ser confiables aunque se rendericen bien.
Al principio parecía suficiente mostrar “vistas de hoy”, “vistas de este mes” y “vistas totales”. Pero lo que quería en la barra lateral era más cercano a cuántas visitas tuvo el blog hoy, no cuántas veces se abrió un artículo.

Así que separé el modelo.
Visitas
-> sesiones con 30 minutos de inactividad
Vistas
-> número de aperturas de páginas o posts

4943 no era un conteo de visitas
Lo primero era corregir el significado del baseline.
El valor 4943 importado desde Google Analytics era screenPageViews. Es decir, vistas de página. Mostrarlo como visitantes o visitas totales sería incorrecto.
Por eso limpié el Worker y la documentación al mismo tiempo.
totalPageViews
-> GA screenPageViews baseline + D1 page views
totalSessions
-> GA sessions baseline + D1 sessions
Las visitas y las vistas no pueden usar el mismo baseline. Añadí una ruta separada para sembrar el baseline de sesiones.
/admin/seed-session-baseline
También añadí ese paso al flujo de despliegue del Worker en GitHub Actions. Si el Worker se despliega pero el baseline queda vacío, el total público de visitas puede verse roto.
Usar la respuesta de /track de inmediato
La estructura inicial daba un rodeo.
El cliente enviaba /track para contar, y luego leía /analytics otra vez para pintar la pantalla. Con caché y orden de peticiones, la visita recién contada podía no aparecer de inmediato.
Ahora /track devuelve también el payload de analytics más reciente.
Carga de página
-> POST /track
-> Worker actualiza sesión/vistas
-> la misma respuesta incluye analytics fresco
-> el cliente renderiza la barra lateral y la vista de la página actual
Las actualizaciones periódicas siguen leyendo /analytics.
La primera pantalla usa el valor recién actualizado; después, la API de lectura mantiene la interfaz al día.
Una sesión no debe crecer con cada cambio de página
Las vistas pueden crecer cuando el lector pasa de un post a otro.
Las visitas son distintas. Si una persona lee tres posts dentro de la misma sesión del blog, eso no debería convertirse en tres visitas. Añadí una tabla sessions al Worker y uní sesiones por visitor hash y última actividad.
El límite es de 30 minutos.
Dentro de 30 minutos desde la última actividad
-> misma sesión
Después de más de 30 minutos
-> nueva sesión
Así las visitas de hoy/mes/total en la barra lateral se mueven menos que las page views. Las vistas por post siguen usando el page path.
Las páginas multilingües siguen la misma regla.
/daily-review/.../ y /en/daily-review/.../ son versiones del mismo post. La clave de vistas usa el canonical path, y cambiar de idioma dentro de una sesión no crea otra visita.
Convertir el panel en algo más parecido a una tabla
La primera página de estadísticas se apoyaba en tarjetas KPI y listas con barras.
No estaba mal, pero al mostrar visitas y vistas juntas la estructura se volvió ambigua. Más tarjetas hacían la pantalla móvil más larga y era difícil ver qué número era visita y cuál era vista en cada período.
Por eso convertí la comparación superior en algo más cercano a una tabla.

Período Visitas Vistas
Rango elegido n n
Hoy n n
Este mes n n
Total n n
El total también necesitaba dos filas.
Total
-> seguimiento directo desde 2026/06/09
Total
-> incluye estadísticas anteriores a 2026/06/09
No significan lo mismo.
El seguimiento directo es el valor respaldado por dimensiones en D1 desde que empezó la recolección pública. El total con historial suma el baseline de GA. Si se mezclan en una sola fila, el número parece más grande, pero no coincide con las dimensiones detalladas.
También separé el texto de resumen.
Visitas: excluye visitas repetidas dentro de 30 min. Vistas: aperturas de página.
El seguimiento directo empieza desde 2026/06/09.
Hacer menos molesta la entrada de fechas
En una página de estadísticas se cambian fechas con frecuencia.
Al principio pensé que bastaba con range=today, range=month, range=total y range=custom. Pero para revisar rangos directos hay que tocar inicio y fin muchas veces.
Así que hice que los inputs se comportaran más como una herramienta.
formato YYYY/MM/DD
date picker oculto
selección de segmento año/mes/día
ajuste con ArrowUp / ArrowDown
ajuste con la rueda del mouse
clamp entre inicio y fin
Siguen siendo dos inputs pequeños, pero cambiar fechas dejó de sentirse tan torpe.
También dejé de ocultar el rango personalizado hasta pulsar un botón. Los inputs quedan visibles y los presets solo mueven las fechas al rango correspondiente.
Era más predecible.
Separar dimensiones detalladas en pestañas
Mostrar todas las dimensiones a la vez ensuciaba la página.
Páginas, entorno del visitante, fuente de tráfico, región e idioma son datos útiles, pero juntos en una sola pantalla se leen mal. Los agrupé en pestañas.
Páginas
Entorno del visitante
Tráfico
Región/idioma
Los paths pueden ser largos, así que añadí title a las etiquetas y ajusté el CSS para que el wrapping y el truncado no rompieran el layout. Los valores de página que empiezan por / se volvieron enlaces.
El objetivo no era un dashboard vistoso.
Quería abrirlo en el teléfono y ver rápido qué posts se estaban leyendo, cuántas visitas hubo hoy y cuántas vistas se contaron.
También ajustar las etiquetas multilingües
La página de estadísticas no existe solo en coreano.
También hay páginas activas como /en/analytics/, /ja/analytics/ y /zh-Hans/analytics/. Etiquetas como “visitas”, “vistas”, “sesiones de 30 minutos” y “vistas GA + D1” tenían que cambiar en el front matter de cada locale.
Si se omite eso, la estructura cambia pero otros idiomas conservan texto antiguo.
En un blog multilingüe, arreglar una pantalla no es arreglar una sola página. El significado de las etiquetas también debe moverse.
Lo que comprobé
Comprobé sobre todo renderizado y significado de métricas.
node --check cloudflare/ga-stats-worker.js
node --check assets/js/custom/analytics-dashboard.js
node --check assets/js/custom/visitor-stats.js
bundle exec jekyll build
Cloudflare Worker deploy
GitHub Pages deploy
El criterio fue este.
La barra lateral muestra sessions como visitas
Las vistas por post siguen siendo page views
Visitas totales y vistas totales usan baselines distintos
El total directo y el total con GA están separados
La entrada de fechas no choca con today/month/total
La tabla período/visitas/vistas no se desborda en móvil
Después de este trabajo, la página de estadísticas quedó más silenciosa.
Hay más números, pero confunden menos. Una visita es una visita, y una vista es una vista. Total es total, pero total directo y total con historial no son lo mismo.
Lo importante no era hacer que los números parecieran más grandes.
Era no esconder qué significa cada uno.
Deja un comentario