2026.06.09 (Mar)

✹ 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