Référence du tracker t.js
Le tracker est servi par le Worker de collecte sur GET /js/t.js
(Cache-Control: public, max-age=86400, stale-while-revalidate=604800 + ETag).
~1,5 Ko min+gzip (budget CI : 3 Ko). Zéro dépendance, IIFE, tout le code sous
try/catch silencieux : il ne lève jamais d’erreur dans la page hôte.
<script defer src="https://elvn.live/js/t.js" data-site="SITE_PUBLIC_ID"></script>Attributs data-*
Section intitulée « Attributs data-* »| Attribut | Requis | Effet |
|---|---|---|
data-site |
oui | Identifiant public du site. Sans lui, le tracker ne fait rien. |
data-api |
non | Endpoint de collecte custom (ex. /stats/e en proxy first-party). Défaut : <origine du script>/api/e, ou /api/e si l’origine est introuvable. |
data-spa="off" |
non | Désactive le suivi des navigations SPA. |
data-outbound="off" |
non | Désactive les événements outbound / download. |
data-engage="off" |
non | Désactive l’événement engage (temps actif + scroll). |
data-dev |
non | Autorise le tracking sur localhost / 127.x / [::1] (sinon le tracker reste muet en local). Attribut de présence, sans valeur. |
Les trois attributs spa / outbound / engage ne se désactivent qu’avec la
valeur exacte "off".
Ce qui est suivi automatiquement
Section intitulée « Ce qui est suivi automatiquement »- Pageview au chargement, puis à chaque navigation SPA :
history.pushState/history.replaceStatepatchés +popstate, dédoublonnés si lepathnamene change pas. - Liens sortants : clic sur un
<a href>dont le hostname diffère de la page → événementoutboundavec{url}en props. - Téléchargements : clic sur un lien interne dont le path se termine par
une extension de fichier (pdf, zip, dmg, exe, pkg, msi, deb, rpm, apk, iso,
rar, 7z, gz, tgz, tar, csv, doc(x), xls(x), ppt(x), txt, mp3/mp4, mov, avi,
wmv, wav) → événement
downloadavec{url}. - Engagement : au premier passage de l’onglet en arrière-plan
(
visibilitychange → hidden) de chaque pageview, un événementengageavec{t: temps actif cumulé en ms, d: profondeur de scroll max en %}. Le temps actif compte au plus 30 s après la dernière interaction (clic, touche, scroll). Réarmé à chaque navigation SPA. Sert au calcul réel du bounce et de la durée de visite.
Payload envoyé
Section intitulée « Payload envoyé »JSON ≤ 4 096 octets sur POST /api/e :
{ "s": "SITE_PUBLIC_ID", "u": "/chemin?utm_source=…", "r": "https://referrer…", "w": 1440, "l": "fr-FR", "e": "nom-evenement", "p": { "plan": "pro" } }| Champ | Contenu |
|---|---|
s |
Identifiant public du site (data-site). |
u |
Path + query filtrée côté client : seuls les paramètres utm_*, ref et source sont conservés. |
r |
document.referrer. |
w |
screen.width. |
l |
navigator.language. |
e |
Nom d’événement (absent pour un pageview). |
p |
Props de l’événement (absent si aucune). |
Transport : navigator.sendBeacon (corps texte → pas de préflight CORS),
fallback fetch(…, { keepalive: true }). Aucun retry client : un événement
perdu est perdu. Les envois déclenchés avant la fin du parsing du document
sont mis en file et rejoués à DOMContentLoaded.
Le Worker re-valide tout côté serveur et répond toujours 202, corps vide (événement accepté ou rejeté — aucun oracle).
Événements custom — API window.elvn
Section intitulée « Événements custom — API window.elvn »Stub de file d’attente (optionnel)
Section intitulée « Stub de file d’attente (optionnel) »Pour appeler window.elvn() avant que t.js soit chargé, ajoutez ce stub
avant le snippet — les appels sont rejoués à l’initialisation :
<script> window.elvn = window.elvn || function () { (window.elvn.q = window.elvn.q || []).push(arguments); };</script>window.elvn("signup", { plan: "pro" });window.elvn("newsletter-open");Contraintes (validées côté client ET re-validées par le Worker)
Section intitulée « Contraintes (validées côté client ET re-validées par le Worker) »- Nom : minuscules
a-z, chiffres,_,-, 1 à 64 caractères (/^[a-z0-9_-]{1,64}$/). Le tracker met en minuscules automatiquement ; un nom invalide est abandonné en silence. - Noms réservés — ne pas les utiliser pour des événements custom :
pageview,engage,outbound,download. - Props : objet plat uniquement. Valeurs scalaires : chaînes
(tronquées à 500 caractères), nombres finis, booléens. Objets imbriqués,
tableaux,
null,NaN/Infinity→ ignorés silencieusement. Clés de 1 à 64 caractères. Le JSON des props doit tenir en 2 048 octets (payload total ≤ 4 096 octets), sinon le Worker rejette l’événement. - Jamais de données personnelles dans les props (email, nom, identifiant…) — c’est la responsabilité de l’intégrateur et une condition de l’exemption CNIL (voir Vie privée).
Attribut déclaratif data-elvn-event
Section intitulée « Attribut déclaratif data-elvn-event »Délégation de clic — l’ancêtre le plus proche portant l’attribut gagne, y compris quand le clic touche un élément imbriqué :
<button data-elvn-event="cta-hero">Essayer</button>Les goals de type « event » du dashboard matchent ces noms d’événements.
Rien à configurer : pushState/replaceState sont patchés et popstate
écouté. Un pageview est envoyé à chaque changement de pathname (même path →
dédoublonné), et l’événement engage est réarmé. Pour un routeur exotique qui
ne passe pas par l’History API : il n’existe pas d’API de pageview
manuelle — gardez l’History API (ne mettez data-spa="off" que si vous
assumez de perdre les navigations internes).
Ce qui n’est jamais suivi / opt-out
Section intitulée « Ce qui n’est jamais suivi / opt-out »Le tracker s’arrête de lui-même quand :
navigator.webdriver === true(automatisation) ;- la page est dans une iframe (
window.top !== window.self) ; - la page tourne sur localhost (
localhost,127.x.x.x,[::1]) sansdata-dev; - opt-out visiteur :
localStorage.elvn_ignore === "true".
Côté serveur, le Worker rejette en silence (toujours 202) : sites
inconnus/inactifs, origine non conforme au domaine déclaré (sous-domaines
acceptés), bots (User-Agent + ASN datacenter), dépassement du rate limit
(100 evt / 10 s par site + IP tronquée), et les requêtes portant
Sec-GPC: 1 si le site respecte Global Privacy Control (option par site,
activée par défaut).
Snippet opt-out à proposer aux visiteurs (voir la page vie privée pour la version complète) :
<button onclick="localStorage.elvn_ignore = 'true'; this.textContent = 'Vous n’êtes plus compté.'"> Ne plus me compter dans les statistiques</button>Ré-inclusion : localStorage.elvn_ignore = 'false' (ou suppression de la
clé), puis rechargement.
Si le site applique une Content Security Policy, autorisez uniquement :
script-src:https://elvn.live(ou le path du proxy first-party) ;connect-src:https://elvn.live(ou l’endpointdata-apidu proxy).