[đ ] CrĂ©er une page publique de statistiques du blog
âš RĂ©sumĂ© de GPT-5.5 ă
Un retour sur lâenquĂȘte autour dâun compteur de visites anormalement Ă©levĂ©, le blocage du trafic local dans le comptage, et lâajout dâune page publique dâanalytics agrĂ©gĂ©s avec Cloudflare Worker et D1.
Le compteur de visites semblait faux.
Le nombre quotidien a soudain dépassé 80.
Jâaurais pu penser Ă du trafic de recherche. Mais quelque chose clochait. Depuis plusieurs jours, je modifiais beaucoup le blog et, pendant le travail avec lâIA, jâavais ouvert plusieurs fois le serveur local et lâURL publique.
Il fallait donc poser la question.
Ătait-ce du vrai trafic ?
Ou mon propre travail était-il compté aussi ?
Le compteur Ă©tait trop honnĂȘte
Jâai dâabord revu la structure.
Le compteur créé dans le travail sur le compteur de visites utilise Cloudflare Worker et D1.
Quand une page se charge, JavaScript envoie /track au Worker. Le Worker incrémente counters, page_counters et dedupe_views dans D1. Google Analytics sert seulement de baseline ; les nouveaux incréments vont dans D1.
Le problĂšme Ă©tait que cette structure Ă©tait trop honnĂȘte.
Si un navigateur ouvrait une page, elle était comptée.
Le serveur local pointait lui aussi vers le Worker de production. Les origins autorisées du Worker incluaient localhost:4000 et 127.0.0.1:4000.
Donc une prévisualisation locale pouvait augmenter le vrai compteur D1 de production.
La dĂ©duplication Ă©tait aussi basĂ©e sur visitorId + path. La mĂȘme page dans le mĂȘme navigateur est dĂ©dupliquĂ©e pendant 10 minutes, mais ouvrir plusieurs articles diffĂ©rents compte chaque article.
D1 lâa montrĂ© clairement.
day:2026-06-06 = 14
day:2026-06-07 = 38
day:2026-06-08 = 81
day:2026-06-09 = 5
Le 2026-06-08, beaucoup dâanciens Daily Review et de posts naver-* avaient Ă©tĂ© touchĂ©s une fois. Cela ressemblait davantage Ă une session de vĂ©rification quâĂ de vrais lecteurs.
Le local doit afficher, pas compter
La premiÚre correction était simple.
En local, les statistiques peuvent sâafficher, mais /track ne doit pas ĂȘtre envoyĂ©.
localhost
127.0.0.1
::1
Dans ces environnements, le script client saute le tracking.
Mais faire confiance au client seul est fragile. Si le JS change ou si une requĂȘte manuelle arrive, le problĂšme revient. Le Worker compte donc /track uniquement depuis lâorigin de production.
TRACK_ALLOWED_ORIGIN=https://hyuk.blog
Les requĂȘtes venant dâorigins locales sont maintenant ignorĂ©es avec origin_not_tracked.
Jâai aussi ajoutĂ© un opt-out pour vĂ©rifier la production sans polluer le compteur.
?hyuk_no_track=1
?visitor_tracking=off
?visitor_tracking=on
Ce nâest pas une administration cachĂ©e. Câest seulement un interrupteur pour inspecter la page publique sans modifier les chiffres.
Les statistiques nâavaient pas besoin dâĂȘtre privĂ©es
Au dĂ©but, jâai envisagĂ© une page dâanalytics privĂ©e.
Mais ce nâĂ©tait pas nĂ©cessaire.
Si je ne stocke pas les IP brutes, les User-Agent bruts, les full referrer URLs ni les logs dâĂ©vĂ©nements individuels, la page peut ĂȘtre publique. Il suffit de stocker des valeurs agrĂ©gĂ©es affichables.
La direction a donc changé.
Pas une page privée de logs.
Une page publique de statistiques du blog.
/analytics/
Je lâai ajoutĂ©e Ă la navigation principale et au petit bloc de visites dans la sidebar.
D1 ne garde que des agrégats
La nouvelle table est simple.
analytics_daily_dimensions
date
dimension
value
count
updated_at
Quand une page view est réellement comptée, le Worker classe les dimensions publiques et les agrÚge par jour.
Les dimensions sont :
page
content_group
locale
country
region
continent
colo
asn_org
device
viewport
browser
os
language
client_timezone
color_scheme
connection
traffic_source
referrer_domain
hour
weekday
Le point important est ce qui nâest pas stockĂ©.
Le referrer est stockĂ© comme domaine, pas comme URL complĂšte. Le User-Agent est classĂ© en browser, OS et device. LâIP nâest pas stockĂ©e.
Ce nâest pas un entrepĂŽt analytique strict. Câest un tableau de flux public pour un blog personnel.
Aujourdâhui, mois, total et pĂ©riode personnalisĂ©e
Au début, je pensais seulement à aujourd'hui / mois / total, comme le compteur existant.
Mais une page de statistiques doit permettre des périodes.
LâAPI /analytics accepte :
/analytics?range=today
/analytics?range=month
/analytics?range=total
/analytics?range=custom&start=2026-06-09&end=2026-06-12
Ici, total signifie le total depuis le dĂ©but de collecte de analytics_daily_dimensions, le 2026-06-09. Ce nâest pas le total de la sidebar, qui inclut encore le baseline GA.
Je nâai pas mĂ©langĂ© ces deux sens.
Dâabord utilisable sur mobile
Les pages de statistiques cassent vite sur mobile.
Un grand tableau devient immĂ©diatement pĂ©nible. Jâai donc utilisĂ© des cartes avec listes Ă barres.
En haut, il nây a que quatre chiffres.
Période sélectionnée
Aujourd'hui
Ce mois-ci
Total
En dessous, chaque dimension a sa carte.
Sur mobile, les boutons de pĂ©riode passent sur deux lignes, les KPI en deux colonnes et les cartes dĂ©taillĂ©es en une colonne. Le formulaire de pĂ©riode personnalisĂ©e sâempile verticalement.
Sur desktop, les KPI restent sur une ligne et les cartes sâĂ©talent en deux colonnes.
Jâai vĂ©rifiĂ© dans le navigateur. Pas dâoverflow horizontal, pas dâerreur console.
Ce qui a été vérifié
Les vérifications :
node --check cloudflare/ga-stats-worker.js
node --check assets/js/custom/visitor-stats.js
node --check assets/js/custom/analytics-dashboard.js
bundle exec jekyll build
npx wrangler d1 execute hyuk-blog-view-counter --remote --file cloudflare/schema.sql
npx wrangler deploy --keep-vars
AprÚs le déploiement, /analytics?range=today a répondu normalement.
La nouvelle table agrĂ©gĂ©e Ă©tait encore vide. Câest attendu. Les analytics dĂ©taillĂ©s commencent Ă se remplir avec les vraies visites publiques aprĂšs le dĂ©ploiement.
Jâai aussi testĂ© le tracking depuis une origin locale.
{"status":"ignored","reason":"origin_not_tracked"}
La vĂ©rification locale du blog nâincrĂ©mente donc plus le compteur de production.
Du compteur de visites aux analytics publics
Au dĂ©but, il nây avait que trois petits chiffres.
Aujourdâhui, mois, total.
Mais en lâutilisant vraiment, le plus important nâĂ©tait pas le chiffre lui-mĂȘme. CâĂ©tait que le chiffre ne soit pas polluĂ©. Et pour un blog public, afficher un flux agrĂ©gĂ© sĂ»r correspond mieux quâune page privĂ©e de logs.
Ce nâest pas une comptabilitĂ© exacte.
Mais cela répond maintenant à des questions utiles.
Quels posts sont lus ?
De quels pays viennent les visites ?
Mobile ou desktop ?
Recherche, direct ou referral ?
Et surtout, quel bruit venant de mon propre travail faut-il exclure ?
Câest le rĂŽle de /analytics/.
Laisser un commentaire