zylior
← Blog

Scorer l'intention d'achat de tes visiteurs sans CRM lourd

Tu veux savoir qui parmi tes visiteurs est vraiment sur le point d'acheter — sans installer un CRM à 200 €/mois et passer trois jours à câbler des workflows. Bonne nouvelle : un simple pixel first-party (un script JS que tu poses sur ton site) suffit à capter les signaux qui comptent. Le reste, c'est de l'arithmétique pondérée que tu fais tourner en SQL ou dans un cron.

Les signaux qui valent quelque chose (et ceux que tu peux jeter)

L'erreur classique : tracker 40 événements et noyer le signal. En réalité, l'intention d'achat se lit dans une poignée de comportements. Voici ceux qui corrèlent réellement avec une conversion, par ordre de poids décroissant.

Le pixel first-party : ce que tu poses, ce que tu envoies

First-party = ton propre endpoint, ton propre cookie. Pas de dépendance à un SaaS tiers, pas de blocage par les adblockers de tiers, et tu restes maître de la donnée (RGPD-friendly si tu restes en intention anonyme + consentement). Concrètement, un script léger qui envoie un battement de cœur (heartbeat) quand l'onglet est visible, et un événement à chaque page clé.

// pixel.js — ~30 lignes, posé sur toutes tes pages
const vid = localStorage.getItem('vid') || crypto.randomUUID();
localStorage.setItem('vid', vid);

function send(type, meta = {}) {
  navigator.sendBeacon('/collect', JSON.stringify({
    vid, type, path: location.pathname, ts: Date.now(), meta
  }));
}

send('pageview');

// temps ACTIF : on n'incrémente que si l'onglet est visible
let active = 0;
setInterval(() => {
  if (document.visibilityState === 'visible') {
    active += 5;
    if (active % 30 === 0) send('heartbeat', { active });
  }
}, 5000);

// profondeur de scroll, envoyée une seule fois par palier
let maxScroll = 0;
window.addEventListener('scroll', () => {
  const d = Math.round((scrollY + innerHeight) / document.body.scrollHeight * 100);
  if (d >= maxScroll + 25) { maxScroll = d; send('scroll', { depth: d }); }
}, { passive: true });

Côté serveur, `/collect` fait un `INSERT` brut dans une table `events(vid, type, path, ts, meta_jsonb)`. C'est tout. Tu ne calcules rien à la volée : tu stockes des événements bruts et tu scores en batch. Ça t'évite des bugs de double-comptage et tu peux re-scorer tout l'historique quand tu changes la pondération.

La formule de scoring : pondère, plafonne, décote

Le score d'un visiteur = somme de points par signal, plafonnée par signal (sinon un seul fou de scroll te fausse tout) et décotée dans le temps (une visite pricing d'il y a 20 jours ne vaut plus une visite d'hier). Voici une grille de départ — calibre-la ensuite sur tes vrais convertis.

-- score par visiteur, recalculé chaque heure en cron
WITH scored AS (
  SELECT vid,
    LEAST(SUM(CASE WHEN type='pageview' AND path='/pricing' THEN 25 END), 50) AS pricing,
    LEAST(SUM(CASE WHEN path = ANY(ARRAY['/docs','/security','/vs']) THEN 15 END), 45) AS funnel,
    LEAST(COUNT(DISTINCT date_trunc('hour', to_timestamp(ts/1000))) * 10, 40) AS sessions
  FROM events
  WHERE to_timestamp(ts/1000) > now() - interval '30 days'
  GROUP BY vid
)
SELECT vid, COALESCE(pricing,0)+COALESCE(funnel,0)+COALESCE(sessions,0) AS score
FROM scored ORDER BY score DESC;
Ne devine pas tes poids. Exporte tes 20 derniers clients signés, rejoue leur historique de signaux avant signature, et regarde quels scores ils avaient. Si tes convertis plafonnaient à 40 et que ton seuil 'chaud' est à 80, ton seuil est faux — pas tes clients.

Le seuil 'lead chaud' et le bon moment pour relancer

Un seuil absolu ("80 = chaud") vieillit mal. Préfère un seuil relatif : le top 10 % des scores du mois glissant. Ça s'auto-calibre quand ton trafic change. Concrètement, calcule le 90e percentile des scores actifs et traite tout ce qui dépasse comme un lead chaud à traiter dans les 24 h.

Câble une seule alerte : un cron horaire qui pousse dans un canal Slack `#leads-chauds` chaque `vid` qui vient de franchir le 90e percentile, avec son top-3 des pages vues. Tu traites à la main au début — 5 leads/semaine ne justifient aucune automatisation. Tu n'automatises la relance que quand le volume te déborde.

Commence minimal : pose le pixel cette semaine, stocke les événements bruts, lance la requête de scoring en read-only et regarde-la tourner 10 jours sans rien relancer. Tu verras vite si tes scores collent à la réalité de tes signatures. Ensuite seulement tu branches l'alerte Slack et tu ajustes les poids sur tes vrais convertis. Un scoring d'intention utile tient en une table d'événements, une requête SQL et un cron — le CRM usine à gaz, tu te le gardes pour quand tu auras une équipe commerciale à nourrir.

La newsletter

En t’inscrivant, tu acceptes de recevoir la newsletter Zylior. Désinscription en 1 clic dans chaque email.