J’ai divisé mes stats visiteurs par 3500. Mais c’était voulu.
La semaine dernière sur Thesparktwin.com je me suis pris une petachié de robots.
14 000 visiteurs alors que le site en fait en général 3 à 5 vrais visiteurs par jour.
Des bots bien sous tous rapports, IP résidentielle de tous les pays du monde, vrais navigateurs.
J’ai dû faire sortir tout le catalogue des drapeaux du monde à Clicky je pense.
Les seuls trucs qui les trahissent, c’est l’absence de référé, et le pays qui ne matche pas avec la langue consultée (IP guatemaltaise sur une page japonaise, uzbeque sur une page grecque, turque sur une chinoise, …).
Les pages du site sont générées en statique puis hébergées dans les caches de Cloudflare. Donc mon hébergement n’est pas trop dérangé.
Mais ce qui me dérange, c’est que mes stats sur Clicky sont devenues illisibles.
Chose à savoir, sur ces sites je suis en mode « Anti-adblock », c’est-à-dire que c’est mon serveur qui héberge des trackeurs et que je remonte les informations à Clicky de serveur à serveur.
Donc avec l’impossibilité de faire le tri des visiteurs sur leurs caractéristiques propres, je me suis dit que j’allais ne déclencher le script Clicky qu’après un vrai geste humain :
Un clic, un touchscreen ou un mouvement de souris (120 pixels cumulés, 800 millisecondes au minimum).
<script>
(function () {
var parti = false;
var opt = { passive: true, capture: true };
var forts = ['pointerdown', 'touchstart', 'keydown']; // gestes "intentionnels" : clic / touche / doigt
var n = 0, dist = 0, t0 = 0, lx = null, ly = null; // mesure du mouvement de souris
function stop() {
forts.forEach(function (g) { removeEventListener(g, humain, opt); });
removeEventListener('mousemove', bouge, opt);
removeEventListener('pointermove', bouge, opt);
}
function declencher() {
if (parti) return; parti = true;
stop();
humainDetecte(); // <-- VOTRE action ici (charger le mouchard, etc.) } // Clic / touche / doigt = geste fort -> on part tout de suite.
function humain(e) { if (!parti && !(e && e.isTrusted === false)) declencher(); }
// Souris : on exige un VRAI mouvement soutenu, pas un saut unique de robot.
function bouge(e) {
if (parti || e.isTrusted === false) return; // ignore les événements synthétiques
var x = e.clientX, y = e.clientY;
if (lx !== null) dist += Math.abs(x - lx) + Math.abs(y - ly);
lx = x; ly = y;
var now = e.timeStamp || Date.now();
if (!t0) t0 = now;
if (++n >= 10 && dist >= 120 && (now - t0) >= 800) declencher(); // ≥10 mouvements, ≥120 px, ≥800 ms
}
forts.forEach(function (g) { addEventListener(g, humain, opt); });
addEventListener('mousemove', bouge, opt);
addEventListener('pointermove', bouge, opt);
function humainDetecte() {
// TODO : ce que vous déclenchez quand un humain est confirmé.
// ex. charger Clicky, envoyer un ping, etc.
}
})();
</script>
YOUPI !!
Je suis passé de 14 000 « visiteurs » à 8 000.
Putain, les salauds de bots interagissent comme des humains sur le site.
C’est là que Claude (notre cher ami à tous), m’a proposé Turnstile de Cloudflare.
Leur captcha sans intervention.
Je pensais qu’il fallait qu’il soit visible. Mais visiblement non.
Et là : Magie.
4 visiteurs
Les bots on quand même une ethique.
Ils respectent les Captcha (je vous ai parlé de la fois où je n’arrivais pas à remplir un Captcha et qu’après parlementation avec Claude il a accepté de me lire ce que je n’arrivais pas ?).
Mais pour combien de temps ?
Si vous utilisez Clicky en mode classique, vous pouvez quand même activer Turnstile.
<script>
(function () {
// ---- À RENSEIGNER ----
var SITEKEY = 'VOTRE_SITEKEY_TURNSTILE'; // clé publique (dashboard Cloudflare > Turnstile)
var CLICKY_SITE_ID = 12345678; // votre Site ID Clicky (nombre, sans guillemets)
// ----------------------
var parti = false, demande = false, wid = null;
var opt = { passive: true, capture: true };
var forts = ['pointerdown', 'touchstart', 'keydown']; // clic / touche / doigt
var n = 0, dist = 0, t0 = 0, lx = null, ly = null; // mesure du mouvement souris
// 1) FILTRE MOUVEMENT HUMAIN ------------------------------------------------
function stop() {
forts.forEach(function (g) { removeEventListener(g, humain, opt); });
removeEventListener('mousemove', bouge, opt);
removeEventListener('pointermove', bouge, opt);
}
function partir() { if (!demande) { demande = true; stop(); chargerTS(); } }
function humain(e) { if (!parti && !(e && e.isTrusted === false)) partir(); }
function bouge(e) {
if (parti || demande || e.isTrusted === false) return; // ignore les événements synthétiques
var x = e.clientX, y = e.clientY;
if (lx !== null) dist += Math.abs(x - lx) + Math.abs(y - ly);
lx = x; ly = y;
var now = e.timeStamp || Date.now();
if (!t0) t0 = now;
if (++n >= 10 && dist >= 120 && (now - t0) >= 800) partir(); // ≥10 mvts, ≥120 px, ≥800 ms
}
forts.forEach(function (g) { addEventListener(g, humain, opt); });
addEventListener('mousemove', bouge, opt);
addEventListener('pointermove', bouge, opt);
// 2) TURNSTILE INVISIBLE ----------------------------------------------------
function rendre() {
if (wid !== null || !(window.turnstile && turnstile.render)) return;
var box = document.createElement('div');
box.style.cssText = 'position:fixed;left:-9999px;top:0;width:1px;height:1px;overflow:hidden';
document.body.appendChild(box); // hors-écran, PAS display:none (sinon l'iframe ne s'initialise pas)
wid = turnstile.render(box, {
sitekey: SITEKEY,
callback: chargerClicky, // humain validé -> on charge Clicky
'error-callback': function () { return true; } // robot -> pas de jeton, on ne charge rien
});
}
function chargerTS() {
if (window.turnstile && turnstile.render) { rendre(); return; }
if (document.getElementById('cf-ts-api')) return;
window.onloadTurnstileCallback = rendre; // appelé quand Turnstile est prêt (fiable avec defer)
var a = document.createElement('script');
a.id = 'cf-ts-api';
a.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onloadTurnstileCallback';
a.defer = true;
document.head.appendChild(a);
}
// 3) CHARGEMENT DU CLICKY OFFICIEL (seulement si humain + Turnstile OK) ------
function chargerClicky(token) {
if (parti) return; parti = true; // une seule fois ; (token non revérifié côté serveur en embed classique)
window.clicky_site_ids = window.clicky_site_ids || [];
window.clicky_site_ids.push(CLICKY_SITE_ID);
var s = document.createElement('script');
s.async = true;
s.src = '//static.getclicky.com/js';
document.head.appendChild(s);
}
})();
</script>
Il ne me reste plus qu’à revenir aux 14 000 visiteurs.
Mais réels cette fois-ci.




