[đ ] RĂ©duire le comptage des bots dans les statistiques du blog
âš 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