Documentation · v1.0.0

LeadIntent Agent
Référence Technique

Un agent de suivi côté navigateur, respectueux du consentement, qui capture le comportement des visiteurs, classifie l'intention d'achat et transmet des événements structurés à votre pipeline backend — sans jamais lire les données personnelles des champs de formulaire.

Vanilla JS · Aucune dépendance Bundle IIFE · ~18 Ko brut RGPD / DNT compatible

01 —Introduction

Le Lead Intent Agent (LIA) est un bundle JavaScript mono-fichier (lia.js) conçu pour être intégré dans n'importe quelle propriété web. Il observe en continu le comportement des visiteurs, enrichit chaque événement avec le contexte de l'appareil, de la langue et de l'acquisition, et transmet des charges utiles structurées à une API backend.

LIA a été construit autour de trois principes fondamentaux :

  • Privacy-first — respecte les entêtes DoNotTrack, ne lit jamais les valeurs des champs de formulaire, et assainit les paramètres URL pour supprimer les données personnelles avant la transmission.
  • Livraison résiliente — les événements sont mis en lot en mémoire et transmis via fetch + keepalive avec réessais à backoff exponentiel. Les événements de sortie de page utilisent la sémantique sendBeacon pour résister à la fermeture d'onglet.
  • Zéro dépendance — livré sous forme d'IIFE unique sans prérequis d'exécution externe, compatible avec tous les navigateurs modernes et les frameworks SPA.
💡
Structure du bundle

L'arborescence source est divisée en six modules ES (identity.js, context.js, behaviour.js, suspicion.js, transport.js, tracker.js) orchestrés par agent.js. Le script de build (build.js) supprime la syntaxe ES module et enveloppe le résultat dans un IIFE, produisant lia.js et lia.min.js.

02 —Vue d'ensemble de l'architecture

L'agent suit une architecture en pipeline : les signaux bruts du navigateur traversent des étapes d'enrichissement avant d'être mis en file d'attente dans un buffer d'événements en mémoire. Une boucle de vidage basée sur un timer transmet les lots à l'API ; un callback de mise à jour de session permet au serveur de renvoyer des données de scoring dans l'état de l'agent.

SIGNAUX NAVIGATEUR défilement / clic événements form. changements route visibility / unload CŒUR DE L'AGENT identity.js context.js behaviour.js tracker.js suspicion.js enrichissement buildEvent() enqueue() TRANSPORT file en mémoire (≤100) timer de vidage 5s 3 réessais (backoff exp.) keepalive au déchargement POST /batch API BACKEND POST /events/batch POST /identify callback mise à jour session (score / segment) STOCKAGE LOCAL / SESSION lia_visitor_id (longue durée) lia_session_id + TTL lia_first_touch

03 —Carte des modules

LIA est composé de six modules spécialisés. Chaque module a une responsabilité unique et communique via l'orchestrateur agent.js.

🔑

identity.js

Génère et persiste le visitor_id (longue durée) et le session_id (TTL). Repli gracieux : localStorage → sessionStorage → mémoire vive.

🌍

context.js

Capture l'empreinte de l'appareil, la famille navigateur/OS, la locale, le fuseau horaire, les infos réseau et les paramètres UTM. Assainit les query strings pour supprimer les données personnelles.

📊

behaviour.js

Suit les jalons de profondeur de défilement (25/50/75/90/100%), le temps actif, la détection d'inactivité (30s), et déclenche engaged_session quand les deux seuils sont atteints.

🕵️

suspicion.js

Calcule un score de suspicion de bot côté client (0–100) en utilisant les drapeaux WebDriver, les indices d'UA headless, les dimensions d'écran nulles, le nombre de plugins et la variance de timing.

🚀

transport.js

Gère le batching des événements (max 10/lot, capacité de file 100), le timer de vidage (5s), la logique de réessai (3 tentatives, backoff exponentiel) et la livraison fiable au déchargement.

🎯

tracker.js

Détection des clics CTA avec reconnaissance des plateformes de réservation. Suivi du cycle de vie des formulaires (ouvert → démarré → champ touché → soumis) via IntersectionObserver et délégation d'événements.

04 —Installation

Installez LIA en ajoutant un objet de configuration et la balise script dans le <head> de votre HTML. L'agent s'initialise automatiquement lorsque le DOM est prêt.

index.htmlHTML
<!-- 1. Déclarer la config AVANT la balise script -->
<script>
  window.LeadIntentConfig = {
    siteId:     'votre-site-id',
    apiBaseUrl: 'https://api.votrebackend.com',
    apiKey:     'sk-...',
    sessionTtlMinutes: 30,
    captureForms:     true,
    respectDoNotTrack: true,
    debug:            false,
  };
</script>
<!-- 2. Charger l'agent (async est possible) -->
<script async src="/lia.js"></script>
⚠️
Config avant script

Si window.LeadIntentConfig n'est pas présent à l'exécution de lia.js, l'agent utilise un MutationObserver sur <head> pour attendre l'objet de configuration. Déclarez la config de manière synchrone avant le script pour une initialisation optimale.

05 —Référence de configuration

CléTypeDéfautDescription
siteIdstringrequis Identifiant unique du site suivi. Envoyé avec chaque événement.
apiBaseUrlstringrequis URL de base de l'API backend. L'agent ajoute /v1/events/batch, /v1/identify, etc.
apiKeystringrequis Envoyé en tant qu'entête X-Api-Key sur toutes les requêtes.
sessionTtlMinutesnumber30Délai d'expiration de session par inactivité en minutes.
captureFormsbooleantrueActiver le suivi du cycle de vie des formulaires.
captureScrollbooleantrueActiver le suivi de profondeur de défilement et la mesure du temps actif.
captureClicksbooleantrueActiver la détection des clics CTA via les sélecteurs configurés.
respectDoNotTrackbooleantrueSi true, définit consent_state à essential_only lorsque l'entête DNT du navigateur vaut 1.
ctaSelectorsstring[][]Sélecteurs CSS supplémentaires à traiter comme éléments CTA, fusionnés avec la liste intégrée.
pageCategoryRulesRule[][]Tableau de règles { match: RegExp, category: string } évaluées avant les heuristiques intégrées.
debugbooleanfalseActive la sortie console.log détaillée et force une identité fraîche à chaque chargement (développement uniquement).

06 —Consentement & Confidentialité

LIA est livré avec des hooks de gestion du consentement en propre. Le suivi est entièrement bloqué lorsque le consentement est 'denied'. Une méthode setConsent() permet l'intégration avec n'importe quelle CMP externe.

consentement.jsJavaScript
// États : 'unknown' | 'granted' | 'denied' | 'essential_only'

maCMP.onDecision((decision) => {
  window.LeadIntentAgent.setConsent(
    decision.analytics ? 'granted' : 'denied'
  );
});

const session = window.LeadIntentAgent.getSession();
// → { sessionId, visitorId, leadId, score, segment }

Gardes-fous de confidentialité intégrés

  • Les query strings sont assainies — seuls les paramètres UTM et une liste d'autorisation connue sont transmis.
  • Les valeurs des champs de formulaire ne sont jamais lues — seule la classification du type de champ (email, téléphone, entreprise) est suivie.
  • L'entête DoNotTrack force le mode essential_only lorsque respectDoNotTrack: true.
  • La méthode reset() efface toute identité persistée de toutes les couches de stockage.

07 —Module d'identité

LIA maintient deux niveaux de persistance d'identité avec des replis de stockage automatiques :

Visitor ID

  • lia_visitor_id longue durée

Généré une fois par navigateur via crypto.randomUUID(). Persiste jusqu'à suppression. Utilisé pour la reconnaissance de visiteur inter-sessions.

Session ID

  • lia_session_id TTL session
  • lia_session_start horodatage

Rafraîchi à chaque interaction. Expire après sessionTtlMinutes d'inactivité. Une nouvelle session émet session_started.

First Touch

  • lia_first_touch préservé

Capture les paramètres UTM et le referrer dès la toute première visite. Jamais écrasé — préservé pour l'attribution sur toutes les sessions suivantes.

08 —Suivi comportemental

Le module de comportement surveille la qualité d'engagement en utilisant des listeners non-invasifs et throttlés. Il ne se déclenche jamais sur chaque événement DOM brut — tous les signaux sont anti-rebondis ou limités par jalons.

Les jalons suivis sont : profondeur de défilement à 25%, 50%, 75%, 90% et 100% — temps actif à 30s, 60s, 120s — session engagée (temps actif ≥ 30s ET défilement ≥ 50%) — résumé de sortie de page au déchargement.

Le temps d'inactivité (30s sans interaction) met en pause le compteur de temps actif. Les changements de visibilité (onglet caché) sont également tracés séparément.

09 —Couche transport

Le module transport gère toutes les communications réseau. Il regroupe les événements par lots, réessaie les livraisons échouées, et s'assure que les événements critiques (soumissions de formulaires, réservations) sont vidés immédiatement.

ParamètreValeurNotes
MAX_BATCH_SIZE10Événements par lot vidé
FLUSH_INTERVAL_MS5 000Intervalle de vidage basé sur timer
MAX_RETRY_ATTEMPTS3Réessais avec backoff exponentiel (500ms, 1s, 2s)
MAX_QUEUE_SIZE100Suppression FIFO en cas de dépassement (le plus ancien supprimé)

Événements critiques — vidage immédiat

Les événements suivants contournent le timer de lot et déclenchent un flush() immédiat : form_submitted · booking_started · identify · session_ended · booking_opened

10 —Moteur de suspicion

Le module de suspicion calcule un score de qualité côté client pour détecter le trafic automatisé. Ce sont des signaux faibles uniquement ; l'enrichissement côté serveur fait autorité. Un score ≥ 30 déclenche un événement headless_suspected.

SignalScoreMéthode de détection
webdriver_true+30navigator.webdriver === true
headless_chrome_ua+20/HeadlessChrome/.test(userAgent) ET pas de window.chrome
zero_screen+20screen.width === 0 && screen.height === 0
no_plugins+5navigator.plugins.length === 0 (non-Firefox)
no_languages+5navigator.languages.length === 0
permissions_anomaly+5typeof navigator.permissions === 'undefined'

11 —API publique

appelLeadIntentAgent.init(config)Initialiser l'agent

Doit être appelé une seule fois avant toute autre méthode. Typiquement appelé automatiquement via window.LeadIntentConfig. Émet session_started ou session_resumed.

appelLeadIntentAgent.track(eventName, properties)Émettre un événement personnalisé
  • eventNamestringNom de l'événement personnalisé. Envoyé avec l'enrichissement complet de page et de contexte.
  • propertiesobject?Propriétés arbitraires clé-valeur fusionnées dans l'enveloppe properties.
asyncLeadIntentAgent.identify(payload)Associer la session à un lead connu
  • payload.emailstring?Adresse email du lead. Envoyée à POST /v1/identify.
  • payload.namestring?Nom complet du lead.
  • payload.companystring?Nom de l'entreprise.

Retourne la réponse backend incluant lead_id. Les événements suivants incluront ce lead_id pour l'attribution.

getLeadIntentAgent.getSession()Snapshot de session actuelle

Retourne { sessionId, visitorId, leadId, score, segment } de manière synchrone. Le score et le segment sont renseignés après le premier aller-retour API.

appelLeadIntentAgent.setConsent(state)Mettre à jour l'état du consentement

États acceptés : 'granted' | 'denied' | 'essential_only' | 'unknown'. Définir 'denied' arrête immédiatement toute émission d'événements.

appelLeadIntentAgent.reset()Effacer toutes les données d'identité

Supprime toutes les clés du localStorage, sessionStorage et du stockage en mémoire. Réinitialise les IDs de session, visiteur et lead. Arrête le timer de vidage.

12 —Catalogue d'événements

Nom de l'événementTypePropriétés clésDescription
session_startedcycle de vievisitor_idDéclenché lors de la création d'une nouvelle session
session_resumedcycle de vievisitor_idDéclenché lors de la reprise d'une session dans son TTL
page_viewcycle de viepage_category, is_entry_pageDéclenché à chaque navigation, y compris les changements de route SPA
page_exitcycle de vieactive_time_seconds, max_scroll_depthDéclenché au déchargement de page ; livré via keepalive fetch
scroll_depth_reachedcomportementaldepth_percent (25/50/75/90/100)Déclenché une fois par jalon par page, throttlé à 200ms
active_time_30scomportementalactive_secondsTemps actif cumulé atteint 30 secondes
engaged_sessionintentionactive_secondsActif ≥ 30s ET défilement ≥ 50% — signal d'engagement de haute qualité
cta_clickintentioncta_text, cta_idClic sur un élément CTA correspondant aux sélecteurs configurés
booking_openedintentionsource, hrefClic sur un lien de réservation Calendly / Cal.com / Acuity
form_openedcritiqueform_idFormulaire entré dans le viewport (seuil 30% via IntersectionObserver)
form_startedcritiqueform_idPremier champ focalisé dans un formulaire
form_submittedcritiqueform_id, elapsed_secondsÉvénement de soumission de formulaire. Déclenche un vidage immédiat du transport.
pricing_viewintentionpage_categoryAuto-émis quand le chemin de page correspond à la catégorie tarification
headless_suspectedcomportementalsignals[], scoreScore de suspicion ≥ 30 — trafic automatisé suspecté