Attention les intégrations avec GTM créent du CLS sur votre site.
Ceci n'est pas spécifiques à JOIN Stories, mais pour toute intégration dans le DOM via un Tag Manager.
Prérequis
Avant de commencer, récupérez ces informations dans votre back-office JOIN :
1. Nom de domaine
Votre domaine JOIN (format : votre-marque.join-stories.com)
2. Alias du widget
L'identifiant de votre widget (ex: homepage, products, pdp)
Type de widget
JOIN propose deux types de widgets. Choisissez celui qui correspond à votre besoin :
Widget Standard
Affiche le même contenu pour tous les visiteurs d'une page. Usage : page d'accueil, page catégorie, landing page
Widget Product Page
Affiche un contenu spécifique selon le produit consulté. Usage : fiche produit (PDP)
Intégration via Google Tag Manager
Le widget doit être injecté dynamiquement à un emplacement spécifique de votre page.
Avec GTM, vous ne créez pas le conteneur en HTML. Le conteneur est créé dynamiquement en JavaScript et inséré après un élément cible de votre choix.
Widget Standard avec GTM
(function () {
// Configuration
var domainName = "votre-marque.join-stories.com";
var alias = "votre-alias";
var divId = "join-widget";
var targetSelector = ".product-info"; // ⬅️ Sélecteur CSS de l'élément cible
// Récupérer l'élément cible
var target = document.querySelector(targetSelector);
if (!target) {
console.warn("JOIN: Élément cible non trouvé");
return;
}
// Créer le conteneur dynamiquement
var container = document.createElement("div");
container.id = divId;
container.style.display = "block";
// Insérer le conteneur après l'élément cible
target.parentNode.insertBefore(container, target.nextSibling);
// Charger le widget
var script = document.createElement("script");
script.src = "https://" + domainName + "/widgets/" + alias + "/index.js";
script.setAttribute("data-join-widget-id", divId);
script.setAttribute("data-join-widget-alias", alias);
script.setAttribute("type", "text/javascript");
container.appendChild(script);
})();
Widget Product Page avec GTM
(function () {
// Configuration
var productId = "VOTRE_PRODUCT_ID"; // ⬅️ À récupérer dynamiquement
var alias = "votre-alias";
var domainName = "votre-marque.join-stories.com";
var divId = "join-widget-pdp";
var targetSelector = ".product-form__quantity"; // ⬅️ Sélecteur CSS
// Récupérer l'élément cible
var target = document.querySelector(targetSelector);
if (!target) {
console.warn("JOIN: Élément cible non trouvé");
return;
}
// Créer le conteneur dynamiquement
var container = document.createElement("div");
container.id = divId;
container.style.display = "block";
// Insérer le conteneur après l'élément cible
target.parentNode.insertBefore(container, target.nextSibling);
// Charger le widget avec fallback
var baseUrl = "https://" + domainName + "/widgets/" + alias;
var script = document.createElement("script");
script.setAttribute("src", baseUrl + "/" + productId + ".js");
script.setAttribute("type", "text/javascript");
script.setAttribute("data-join-widget-id", divId);
script.setAttribute("data-join-widget-alias", alias);
script.onerror = function () {
script.remove();
var fallback = document.createElement("script");
fallback.setAttribute("src", baseUrl + "/index.js");
fallback.setAttribute("type", "text/javascript");
fallback.setAttribute("data-join-widget-id", divId);
fallback.setAttribute("data-join-widget-alias", alias);
document.head.appendChild(fallback);
};
document.head.appendChild(script);
})();
Points importants
Sélecteur CSS (targetSelector)
Choisissez un élément stable qui existe toujours sur la page
Exemples courants :
.product-info: bloc d'informations produit.product-form__quantity: sélecteur de quantité.product-description: description du produit#add-to-cart-button: bouton d'ajout au panier
Position d'insertion
target.nextSibling : insère le widget après l'élément cible
Pour insérer avant :
target.parentNode.insertBefore(container, target)
Déclencheur GTM recommandé
Type : DOM Ready ou Window Loaded
Cela garantit que l'élément cible existe avant l'exécution du script
Style (optionnel)
Ajoutez du CSS pour personnaliser l'affichage du widget :
<style> #join-widget { margin: 20px 0; min-height: 114px; width: 100%; } /* Hauteur adaptée sur écrans larges */ @media (min-aspect-ratio: 3/4) { #join-widget { min-height: 283px; } } </style>
Pour GTM, ajoutez ces styles dans une balise HTML personnalisée ou directement dans votre thème.
Exemple 3 : Widget Product Page (GTM)
(function () {
// Configuration
var productId = {{Page.ProductId}}; // ⬅️ Variable GTM
var alias = "pdp";
var domainName = "ma-boutique.join-stories.com";
var divId = "join-widget-pdp";
var targetSelector = ".product-form__quantity";
// Récupérer l'élément cible
var target = document.querySelector(targetSelector);
if (!target) {
console.warn("JOIN: Élément cible non trouvé");
return;
}
// Créer le conteneur
var container = document.createElement("div");
container.id = divId;
container.style.display = "block";
container.style.margin = "20px 0";
container.style.minHeight = "114px";
container.style.width = "100%";
// Insérer après l'élément cible
target.parentNode.insertBefore(container, target.nextSibling);
// Charger le widget
var baseUrl = "https://" + domainName + "/widgets/" + alias;
var script = document.createElement("script");
script.setAttribute("src", baseUrl + "/" + productId + ".js");
script.setAttribute("type", "text/javascript");
script.setAttribute("data-join-widget-id", divId);
script.setAttribute("data-join-widget-alias", alias);
script.onerror = function () {
script.remove();
var fallback = document.createElement("script");
fallback.setAttribute("src", baseUrl + "/index.js");
fallback.setAttribute("type", "text/javascript");
fallback.setAttribute("data-join-widget-id", divId);
fallback.setAttribute("data-join-widget-alias", alias);
document.head.appendChild(fallback);
};
document.head.appendChild(script);
})();
Données d'audience (optionnel)
Pour transmettre des données de segmentation à JOIN :
// Ajouter AVANT loadWidget() window.sendAudienceData = function(data) { window.jDataLayer = window.jDataLayer || []; window.jDataLayer.push({ type: "audience", data: data }); }; // Exemple : envoyer le segment utilisateur sendAudienceData({ segment: "premium", source: "abtasty" });
