Script de tracking
Le script de tracking est le troisième canal d'un connecteur. C'est lui qui crée le visiteur, enregistre les pages vues, alimente les paniers et déclenche les scénarios et widgets côté navigateur.
Sans lui, la relance de panier abandonné et les widgets ne fonctionnent pas, les paniers ne peuvent pas être créés par l'API de données.
Le tracking s'intègre avec le loader spm.js : un tag de quatre lignes à coller une fois, puis des commandes à appeler au fil des événements de votre site. Le loader s'occupe de tout le reste , identité visiteur, envoi des paniers, consentement.
Étape 1 : Collez le tag
Une fois par chargement de document (pas par route), idéalement dans le <head> :
<script>
window.spm = window.spm || function () { (spm.q = spm.q || []).push(arguments); };
spm('consent', true); // ⚠ à remplacer par la réponse de votre bannière cookies, étape 2
spm('init', 'SPM123456'); // votre identifiant de boutique (Paramètres → Accès API)
</script>
<script async src="https://v2.app-spm.com/api/assets/js/spm.js"></script>C'est tout ce qui est obligatoire. spm() existe avant même que le fichier soit chargé : les appels s'empilent dans une file et sont rejoués à l'arrivée du script, l'ordre de chargement n'a aucune importance, vous pouvez appeler spm('…') depuis n'importe quel composant, thème ou tag manager.
Domaine de tracking first-party
Si votre boutique dispose d'un domaine de tracking vérifié (ex. t.ma-boutique.com), remplacez simplement l'hôte dans le src du tag. Le loader lit sa propre origine : tous ses appels suivent automatiquement.
Étape 2 : Branchez le consentement (votre CMP)
Une CMP (Consent Management Platform) est votre bannière cookies, Axeptio, Didomi, OneTrust, Cookiebot, tarteaucitron… C'est elle qui recueille et retient le choix du visiteur, catégorie par catégorie.
La ligne spm('consent', true) du tag est un exemple à remplacer : passez-y la réponse réelle de votre bannière pour la catégorie dont dépend le tracking. Le loader est en opt-in strict :
- tant que
spm('consent', true)n'est pas reçu, aucune requête ne part : tout est mis en attente ; - sur
spm('consent', false)(refus ou retrait), le loader cesse tout envoi et purge l'identifiant visiteur local.
Exemple avec Axeptio :
window._axcb = window._axcb || [];
window._axcb.push(function (axeptio) {
axeptio.on('cookies:complete', function (choices) {
spm('consent', choices.shopimind === true); // le nom du vendor configuré dans votre CMP
});
});Avec tarteaucitron :
tarteaucitron.user.shopimindConsent = function (accepted) {
spm('consent', accepted);
};Le principe est le même quelle que soit la CMP : elle décide, le loader obéit. Un site sans bannière cookies (outil interne, B2B fermé) peut laisser true en dur.
Exclure certaines pages du tracking
Indépendamment du consentement, des pages précises peuvent être exclues du tracking (tunnel de paiement, espace compte, pages légales…). C'est une configuration de votre boutique côté ShopiMind , demandez-nous de l'activer en nous listant les URLs concernées.
Étape 3 : Appelez les commandes selon vos événements
| Commande | Quand l'appeler | Effet |
|---|---|---|
spm('init', ident, opts?) | Une fois, dans le tag | Démarre le tracking : crée ou retrouve le visiteur, charge le moteur, les scénarios et les widgets. opts.trackingUrl force la base si besoin. |
spm('consent', bool) | À chaque décision de la CMP | Ouvre (true) ou ferme (false) toutes les émissions. |
spm('identify', { id_customer }) | Quand la session est authentifiée, avant init si elle est déjà connue au chargement | Rattache le visiteur à son compte client, votre identifiant, le même que customer_id dans l'API. Appelée avant init, le rattachement est immédiat ; après, il s'applique au prochain envoi de panier. |
spm('logout') | À la déconnexion | Cesse d'envoyer l'identifiant client. Ne touche pas au visiteur. |
spm('page', ctx) | Avant init, quand le contexte est connu | Contexte de la page : id_product, id_category, id_manufacturer, id_combination, id_cart. Sert au ciblage des scénarios. |
spm('cart', cart, { lang }?) | À chaque mutation du panier : ajout, retrait, quantité, code promo, vidage compris | Envoie le panier (anti-rebond intégré). Le format de cart est décrit ci-dessous. |
spm('order', { id_cart, id_order }) | Avant init, sur la page de confirmation | Clôt le panier et attribue la conversion. |
// À la connexion / déconnexion
spm('identify', { id_customer: '4212' });
spm('logout');
// Sur une fiche produit, avant init
spm('page', { id_product: 'P-4471', id_combination: 'V-2' });
// À chaque mutation du panier
spm('cart', {
id_customer: '4212', id_cart: 'A7C31F',
date_add: '2026-08-04T10:12:07.000000+02:00',
date_upd: '2026-08-04T10:40:55.000000+02:00',
amount: '129.90', amount_without_tax: '108.25',
tax_rate: '1', currency: 'EUR',
voucher_used: [], voucher_amount: '0',
products: [
{ id_product: 'P-4471', id_combination: 'V-2', id_manufacturer: 'M-8',
qty: '2', price: '64.95', price_discount: '58.45',
price_without_tax: '54.12' }
],
}, { lang: 'fr' });
// Sur la page de confirmation de commande, avant init
spm('order', { id_cart: 'A7C31F', id_order: 'O-9912' });Le format de l'objet cart
| Champ | Type | Rôle |
|---|---|---|
id_cart | chaîne | Identifiant du panier dans votre système. Gardez le même d'une page à l'autre : c'est la clé de suivi. |
id_customer | chaîne | Votre identifiant client (le même que customer_id dans l'API). "" si le visiteur est anonyme. |
date_add / date_upd | ISO 8601 | Création et dernière modification du panier, avec microsecondes et décalage réel : 2026-08-04T10:12:07.000000+02:00. |
amount | chaîne | Total TTC. |
amount_without_tax | chaîne | Total HT. |
tax_rate | chaîne | Taux de conversion de devise (le plus souvent "1"). |
currency | ISO 4217 | Devise du panier. |
voucher_used | tableau | Codes promo appliqués (tableau de chaînes, [] si aucun). |
voucher_amount | chaîne | Montant total des remises ("0" si aucune). |
products | tableau | Une entrée par ligne de panier, voir ci-dessous. |
Chaque entrée de products :
| Champ | Type | Rôle |
|---|---|---|
id_product | chaîne | Identifiant du produit (le même que product_id dans l'API). |
id_combination | chaîne | Déclinaison sélectionnée ("" si aucune). |
id_manufacturer | chaîne | Fabricant ("" si aucun). |
qty | chaîne | Quantité. |
price | chaîne | Prix unitaire TTC catalogue. |
price_discount | chaîne | Prix unitaire TTC réellement payé (remises comprises). |
price_without_tax | chaîne | Prix unitaire HT. |
Deux règles à retenir :
- tous les identifiants et montants sont des chaînes, jamais des nombres ;
- envoyez aussi les paniers vidés (
products: [],amount: "0") : c'est ce qui annule une relance sur un panier abandonné puis vidé.
Vérifier votre intégration
| Contrôle | Attendu |
|---|---|
| Onglet réseau, avant consentement | Aucun appel vers le domaine de tracking |
| Onglet réseau, après consentement | spm.js chargé, suivi du démarrage du tracking sur le même domaine |
| Après un ajout au panier | Une requête part vers le domaine de tracking et répond { "success": true } |
Domaine de tracking first-party
Par défaut, le tracking est servi depuis notre domaine. Sur un front headless (votre site sur www.ma-boutique.com, le tracking sur un domaine tiers), les protections des navigateurs entrent en jeu : Safari, notamment, bloque les cookies tiers, et une partie des paniers peut se perdre silencieusement.
La réponse est un domaine de tracking à votre nom : vous déclarez par exemple t.ma-boutique.com dans Mes domaines, créez l'entrée CNAME indiquée, et nous activons le domaine. À partir de là :
- l'identité visiteur devient first-party → plus de blocage par Safari ou Firefox ;
- tous les appels de tracking partent vers votre propre domaine ;
- votre CMP classe le tracking en first-party, ce qui simplifie sa catégorisation ;
- les liens de vos emails partent du même domaine, bénéfice de délivrabilité au passage.
Une fois le domaine actif, changez simplement l'hôte dans le src du tag, le loader suit.
Navigation SPA
Sur une application monopage (React, Vue, Nuxt…), voici ce qui fonctionne en continu et ce qui ne fonctionne pas :
| État | |
|---|---|
| Identité visiteur, session | Fonctionne : établies au chargement, persistantes |
Panier, via spm('cart', …) | Fonctionne : appelez-la à chaque mutation, quelle que soit la route |
| Widgets et scénarios chargés au démarrage | Fonctionnent |
Ciblage par contexte de page (spm('page')) sur une navigation virtuelle | Non : le contexte n'est lu qu'au chargement complet de document |
En pratique : continuez d'appeler spm('cart', …) à chaque mutation, c'est ce qui porte la relance panier. Les scénarios ciblés sur une URL ou une fiche produit précise se ré-évaluent au prochain chargement complet.
Si votre boutique est une SPA intégrale et que le ciblage par page est central pour vous, contactez-nous : nous travaillons à une prise en charge dédiée.
Étape suivante
→ Référence : terminologie, périmètre cible, diagnostic.