Configurer le suivi des conversions Google Tag Manager dans PrestaShop
Guide complet pour intégrer Google Tag Manager dans PrestaShop : installation GTM, balises Smarty {literal}, suivi e-commerce et erreurs courantes à éviter.
En bref : Pour intégrer Google Tag Manager dans PrestaShop, le snippet JavaScript nécessite des balises {literal} dans les templates Smarty tandis que le snippet noscript n'en a pas besoin. Privilégiez un module avec les hooks displayHeader et displayAfterBodyOpeningTag pour une intégration maintenable qui survit aux mises à jour du thème.
Pourquoi le suivi des conversions est indispensable
Sans suivi des conversions, piloter une boutique PrestaShop revient à naviguer sans instruments. Google Tag Manager (GTM) est devenu l'outil de référence pour centraliser tous vos scripts de tracking — Google Ads, Meta Pixel, GA4 — sans toucher au code à chaque modification.
Pourtant, l'intégration de GTM dans PrestaShop pose des problèmes spécifiques liés au moteur de templates Smarty. Cet article couvre les erreurs les plus fréquentes et la méthode propre pour une intégration fiable.
Méthode d'intégration de Google Tag Manager
Étape 1 : le snippet JavaScript (head)
Le premier extrait GTM doit être placé le plus haut possible dans la balise de votre thème. Dans PrestaShop, le fichier cible est généralement :
- **PrestaShop 1.7 / 8.x** : `themes/votre-theme/templates/_partials/head.tpl`
<!-- Google Tag Manager -->
<script>{literal}(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');{/literal}</script>
<!-- End Google Tag Manager -->
Étape 2 : le snippet noscript (body)
Le second extrait doit être inséré juste après l'ouverture de la balise . Le fichier cible :
- **PrestaShop 1.7 / 8.x** : `themes/votre-theme/templates/layouts/layout-both-columns.tpl` (ou le layout principal de votre thème)
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
Attention : ce snippet noscript ne contient aucune variable JavaScript ni accolade. Il ne nécessite donc pas de balises {literal}. L'ajouter inutilement ne cassera rien, mais c'est une surcharge syntaxique inutile.
Le piège des balises `{literal}` dans Smarty
Smarty utilise les accolades { } comme délimiteurs de variables et de fonctions. Or, le code JavaScript en est truffé. Sans précaution, Smarty tente d'interpréter function(){} comme une variable Smarty et génère une erreur de compilation du template.
Quand utiliser `{literal}` ?
La règle est simple :
Erreur fréquente : oublier `{literal}` sur le JavaScript
Si vous collez le snippet JavaScript GTM directement dans un fichier .tpl sans {literal}, Smarty renverra une erreur du type :
Fatal error: Uncaught SmartyCompilerException: Syntax Error in template
La solution est d'encadrer tout le bloc JavaScript :
<script>
{literal}
// Votre code JavaScript ici
(function(w,d,s,l,i){w[l]=w[l]||[];
// ...
});
{/literal}
</script>
Erreur inverse : mettre `{literal}` sur du HTML pur
Si vous encadrez le snippet noscript (qui ne contient que du HTML) avec {literal}, ce n'est pas bloquant mais c'est inutile. En revanche, si ce même bloc devait un jour contenir des variables Smarty (par exemple {$shop_name}), les balises {literal} empêcheraient leur interprétation. Gardez une bonne hygiène : n'utilisez {literal} que là où c'est nécessaire.
Erreur courante : double imbrication de `
Une erreur classique lors du copier-coller est de créer une double imbrication de la balise :
<!-- ❌ INCORRECT : double noscript -->
<noscript><iframe src="<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
</iframe></noscript>
Ce HTML malformé empêche GTM de fonctionner pour les utilisateurs ayant JavaScript désactivé, et peut provoquer des erreurs de validation W3C. Le navigateur tentera de corriger le DOM, mais le résultat sera imprévisible.
La version correcte est simple et propre :
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
Approche recommandée sur PrestaShop 8.x : le module dédié
Sur PrestaShop 8.x, plutôt que de modifier manuellement les templates, la méthode la plus maintenable consiste à utiliser un module qui injecte GTM via les hooks natifs :
- **Hook `displayHeader`** pour le snippet JavaScript
- **Hook `displayAfterBodyOpeningTag`** (disponible depuis PS 1.7.6) pour le snippet noscript
Cette approche présente plusieurs avantages :
- **Survit aux mises à jour du thème** — pas de fichier `.tpl` modifié à re-appliquer
- **Configuration back-office** — l'ID GTM se gère depuis l'admin
- **Compatibilité multi-thème** — fonctionne quel que soit le thème actif
- **Google Tag Assistant** (extension Chrome) : doit afficher votre conteneur GTM comme actif
- **Mode Aperçu GTM** : depuis l'interface GTM, activez le mode debug pour voir les événements en temps réel
- **Console développeur** : tapez `dataLayer` pour inspecter les données poussées
- **Google Analytics 4 > Temps réel** : vérifiez que les conversions remontent
- **Validateur W3C** : assurez-vous que le HTML généré est valide (pas de double `
- [ ] Snippet JS GTM dans le `` avec `{literal}` dans les fichiers `.tpl`
- [ ] Snippet noscript GTM après `` **sans** `{literal}`
- [ ] Pas de double imbrication `
- [ ] DataLayer configuré pour l'événement `purchase`
- [ ] Tests via Tag Assistant et mode Aperçu GTM
- [ ] Validation W3C du HTML de sortie
Exemple minimal de module
// modules/mygtm/mygtm.php
class MyGtm extends Module
{
public function __construct()
{
$this->name = 'mygtm';
$this->version = '1.0.0';
$this->author = 'Alexandre Carette';
parent::__construct();
$this->displayName = $this->l('Google Tag Manager');
}
public function install()
{
return parent::install()
&& $this->registerHook('displayHeader')
&& $this->registerHook('displayAfterBodyOpeningTag');
}
public function hookDisplayHeader($params)
{
$gtmId = Configuration::get('MYGTM_ID');
if (!$gtmId) return '';
return "<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{$gtmId}');</script>";
}
public function hookDisplayAfterBodyOpeningTag($params)
{
$gtmId = Configuration::get('MYGTM_ID');
if (!$gtmId) return '';
return '<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=' . htmlspecialchars($gtmId, ENT_QUOTES) . '" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>';
}
}
Configurer le suivi e-commerce dans GTM
Une fois GTM en place, l'étape suivante est de pousser les données de conversion dans le dataLayer. Voici les événements clés à configurer :
Événement d'achat (page de confirmation)
Dans le template order-confirmation.tpl (ou via un module sur le hook displayOrderConfirmation) :
<script>
{literal}
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'transaction_id': '{/literal}{$order.details.reference}{literal}',
'value': {/literal}{$order.totals.total.amount}{literal},
'currency': '{/literal}{$currency.iso_code}{literal}',
'items': [
{/literal}
{foreach from=$order.products item=product name=products}
{literal}{{/literal}
'item_id': '{$product.reference}',
'item_name': '{$product.name|escape:'javascript'}',
'price': {$product.price},
'quantity': {$product.quantity}
{literal}}{/literal}{if !$smarty.foreach.products.last},{/if}
{/foreach}
{literal}]
}
});
{/literal}
</script>
Notez l'alternance entre {literal} et {/literal} : on sort du mode literal chaque fois qu'on a besoin d'une variable Smarty, puis on y revient pour les accolades JavaScript.
Vérification et débogage
Après intégration, vérifiez systématiquement :
Checklist récapitulative
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Un projet PrestaShop ?
Discutons-en directement.
193 projets livrés
Lire sur le blog

Alexandre Carette
Expert PrestaShop & Architecture E-commerce
Développeur PrestaShop depuis 2014, 193 projets livrés. Je conçois des architectures headless Nuxt + PrestaShop et des outils d'automatisation IA pour les e-commerçants.