2026.06.11 (Jeu)

✹ RĂ©sumĂ© de GPT-5.5  

Retour sur la rĂ©duction du trafic de crawlers cloud et de clients headless lĂ©gers dans le comptage Cloudflare Worker, avec filtres ASN/organisation, signaux de visible engagement et dĂ©blocage d’un ASN de FAI bloquĂ© par erreur.

Les chiffres analytics semblaient encore étranges.

Aprùs l’ajout de la page publique de statistiques, mon travail local ne polluait plus le compteur de production. Mais un autre problùme est apparu.

Certaines requĂȘtes ne ressemblaient pas Ă  une lecture humaine.

Elles ouvraient plusieurs chemins trùs vite, utilisaient un User-Agent qui ressemblait à un navigateur, mais ne se comportaient pas comme un lecteur restant sur une page. Sur un blog statique public, les crawlers sont normaux. Le problùme, c’est que s’ils touchent aussi /track, ils gonflent les vues et les visites publiques.

Quand j’avais ajoutĂ© le compteur, j’avais Ă©crit que les bots et les visites en double Ă©taient suffisamment bloquĂ©s. En production, ce « suffisamment » devait ĂȘtre relevĂ©.

Le User-Agent ne suffisait pas

Le Worker avait déjà des contrÎles de base.

bot user-agent
Cloudflare verified bot
Cloudflare bot score
dedupe window

Cela attrape les bots évidents.

Mais tous les crawlers n’écrivent pas bot dans leur User-Agent. Certaines requĂȘtes ressemblent Ă  Chrome. Le User-Agent seul ne distingue pas correctement une personne d’un navigateur automatisĂ© lĂ©ger.

Les donnĂ©es request.cf de Cloudflare contiennent ASN et organisation ASN. J’ai donc fait vĂ©rifier ces champs par /track.

TRACK_BLOCKED_ASNS
TRACK_BLOCKED_AS_ORGS

Les variables d’environnement ne remplacent pas entiĂšrement les defaults. Elles s’ajoutent aux defaults du Worker. Les axes clairement bloquĂ©s restent dans le code, et les dĂ©couvertes d’exploitation peuvent ĂȘtre ajoutĂ©es par environnement.

La comparaison exacte du nom d’organisation Ă©tait trop faible.

Huawei Cloud
Huawei-Cloud-HK
Huawei Cloud Singapore POP
Huawei Clouds Singapore

Les noms varient ainsi. La comparaison accepte donc Ă  la fois l’égalitĂ© exacte et le texte contenu. Un seul default peut couvrir plusieurs variantes.

Ajouter 3 secondes de visible engagement

Un filtre ASN seul est trop centré sur le réseau.

Un lecteur rĂ©el peut ĂȘtre derriĂšre un FAI ou un rĂ©seau d’entreprise. Un crawler peut aussi venir d’un rĂ©seau ordinaire. Il fallait donc regarder des signaux cĂŽtĂ© client.

DĂ©sormais, le client n’envoie /track qu’aprĂšs que la page est restĂ©e visible un court moment.

track_delay_seconds = 3

Trois secondes, ce n’est pas long. Un vrai lecteur ne le sent presque pas. Mais cela filtre des previews instantanĂ©es, du scraping en onglet cachĂ©, et des chargements qui disparaissent tout de suite.

Le client envoie ces valeurs dans le payload.

engagementMs
visibilityState
documentHidden
viewportWidth
viewportHeight

Le Worker les valide Ă  nouveau.

Il ne suffit pas de faire confiance au JS. Si engagementMs est infĂ©rieur au seuil, la requĂȘte est ignorĂ©e comme client_visible_too_short. Si le viewport est nul ou invalide, elle est ignorĂ©e comme client_viewport_invalid.

Les signaux visibles n’étaient pas optionnels

La premiÚre implémentation restait trop souple.

Elle vĂ©rifiait visibilityState et documentHidden quand ils existaient, mais une requĂȘte sans ces champs pouvait encore passer. Cela durcissait le nouveau client, mais laissait passer des appels manuels Ă  /track sans signaux.

La condition du Worker est donc devenue stricte.

visibilityState === "visible"
documentHidden === false

Si ces deux conditions ne sont pas exactement satisfaites, la requĂȘte est ignorĂ©e comme client_signal_missing.

L’idĂ©e est de traiter hidden et missing comme la mĂȘme famille. /track est l’endpoint qui augmente les compteurs publics. Une requĂȘte vers cet endpoint doit ressembler Ă  une requĂȘte envoyĂ©e par la page normale et le client normal. Sans signaux, elle ne doit pas passer.

/analytics reste lisible publiquement, mais /track est plus exigeant.

Lire les statistiques
-> public

Augmenter les vues
-> production origin
-> visible engagement
-> viewport valide
-> filtres bot/ASN/org passés

Les valeurs bloquĂ©es doivent ĂȘtre revues

Ce travail a aussi montrĂ© qu’une blocklist ne s’amĂ©liore pas simplement en grandissant.

En voulant bloquer des crawlers cloud, on peut bloquer par erreur un ASN de FAI rĂ©el. Cela supprime aussi des lecteurs rĂ©els. J’ai donc retirĂ© de la liste intĂ©grĂ©e l’ASN ajoutĂ© par erreur.

Les filtres forts semblent rassurants, mais les false positives ont un coût.

Compter les bots gonfle le nombre.
Bloquer des personnes efface de vrais lecteurs.

Les deux sont mauvais.

Le critĂšre est donc devenu ceci.

Bloquer dans le Worker les axes clairement cloud/crawler.
Exiger les signaux visibles du client.
Ne pas mettre du trafic de type FAI humain dans les blocages intégrés.
Garder les valeurs suspectes avec ignored_reason pour audit.

analytics_events conserve des lignes minimales avec ignored_reason mĂȘme pour les requĂȘtes ignorĂ©es. Sans cela, il devient difficile d’expliquer pourquoi un nombre a baissĂ© ou ce qui a Ă©tĂ© bloquĂ©.

Les chiffres doivent apparaĂźtre vite, mais pas trop facilement

Un compteur de visites repose sur un équilibre inconfortable.

S’il se met Ă  jour trop lentement, il semble cassĂ©. C’est pourquoi le travail sur le compteur utilisait un baseline GA plus des incrĂ©ments immĂ©diats en D1.

Mais si compter est trop facile, les bots comptent aussi.

Ce changement dĂ©place un peu l’équilibre vers la prudence. Les lecteurs normaux comptent toujours aprĂšs 3 secondes. Mais l’automatisation instantanĂ©e, les documents cachĂ©s, les viewports invalides et les axes cloud connus entrent plus difficilement.

Les statistiques publiques ne sont pas une comptabilité parfaite.

Mais elles doivent au moins ressembler Ă  une trace de lecture humaine. Les grands nombres ne sont pas l’objectif. Les nombres fiables rendent la dĂ©cision suivante possible.

Ce que j’ai vĂ©rifiĂ©

J’ai vĂ©rifiĂ© ceci pendant le travail.

node --check cloudflare/ga-stats-worker.js
node --check assets/js/custom/visitor-stats.js
git diff --check
bundle exec jekyll build
Cloudflare Worker deploy
GitHub Pages deploy

J’ai aussi fait des smoke tests du Worker.

/analytics?range=today
-> trackDelaySeconds: 3

/track without visibilityState
-> ignored, client_signal_missing

/track with visibilityState="hidden"
-> ignored, client_signal_missing

/track with documentHidden=true
-> ignored, client_signal_missing

J’ai aussi confirmĂ© que le HTML dĂ©ployĂ© de la page d’accueil contenait data-track-delay-seconds="3".

Ce n’était pas une modification spectaculaire.

Mais les chiffres publics ont besoin de ce genre de dĂ©fense. Les vues sont visibles, donc un mauvais comptage casse vite la confiance. Ce travail n’a pas rendu le compteur plus grand. Il l’a rendu plus difficile Ă  tromper.

Laisser un commentaire