Ajouter un loader lors de la soumission de commande PrestaShop
Comment ajouter un spinner de chargement au clic sur le bouton de commande PrestaShop pour éviter les doubles clics et améliorer l'UX du tunnel d'achat.
En bref : Pour ajouter un loader au tunnel de commande PrestaShop, injectez un script JavaScript (protégé par {literal} en Smarty) qui affiche un overlay au submit du formulaire de paiement et désactive le bouton pour éviter les doubles commandes. En PrestaShop 8.x, privilégiez un module avec le hook actionFrontControllerSetMedia.
Lorsqu'un client clique sur le bouton "Commander" à l'étape finale du checkout PrestaShop, il se passe parfois plusieurs secondes avant la redirection vers la page de confirmation ou la passerelle de paiement. Sans retour visuel, le client peut :
**Double-cliquer** et générer deux commandes identiques
**Quitter la page** en pensant que rien ne se passe
**Perdre confiance** dans la fiabilité de la boutique
Ajouter un spinner (loader) au moment de la soumission est une amélioration UX simple mais redoutablement efficace pour le taux de conversion.
Étape 1 : Identifier le bon fichier template
Dans PrestaShop 1.7 et 8.x, le tunnel de commande est géré par le template :
Voici le point crucial. Dans PrestaShop 1.7/8.x, les templates Smarty nécessitent d'encadrer le JavaScript natif avec les balises {literal} pour éviter que Smarty n'interprète les accolades comme des variables de template.
Ajoutez ce script juste avant la balise
dans votre template checkout.tpl ou via un module :
{literal}
<script>
document.addEventListener('DOMContentLoaded', function() {
var paymentForm = document.querySelector('#payment-confirmation form');
if (!paymentForm) return;
var submitted = false;
paymentForm.addEventListener('submit', function(e) {
// Empêcher le double-clic
if (submitted) {
e.preventDefault();
return false;
}
submitted = true;
// Créer l'overlay loader
var overlay = document.createElement('div');
overlay.className = 'checkout-loader-overlay';
overlay.innerHTML = '<div style="text-align:center;"><div class="spinner"></div><p>Traitement de votre commande en cours...</p></div>';
document.body.appendChild(overlay);
// Désactiver le bouton visuellement
var btn = paymentForm.querySelector('button[type="submit"], input[type="submit"]');
if (btn) {
btn.disabled = true;
btn.style.opacity = '0.6';
}
});
});
</script>
{/literal}
Approche alternative via un module (recommandée en 8.x)
En PrestaShop 8.x, la bonne pratique est d'injecter le JavaScript via un module plutôt que de modifier le template directement. Utilisez le hook actionFrontControllerSetMedia :
Les causes les plus fréquentes d'erreur 500 lors de l'ajout de JavaScript dans un template Smarty sont :
**Accolades non protégées** : Smarty interprète `{` et `}` comme des délimiteurs. Encadrez systématiquement votre JS avec `{literal}...{/literal}`
**Fichier corrompu à l'upload** : Comparez avec une installation vierge de la même version
**Cache Smarty périmé** : Videz le dossier `var/cache/` et recompilez
Comparer avec une installation vierge
En cas de doute sur l'intégrité de vos fichiers, téléchargez la version correspondante de PrestaShop depuis le site officiel et comparez les fichiers du tunnel de commande :
Smarty interprète les accolades { } comme des délimiteurs de variables. Si votre code JavaScript contient des accolades (fonctions, objets, conditions), Smarty tente de les interpréter et génère une erreur. La solution est d'encadrer tout votre bloc JavaScript avec les balises {literal}...{/literal}, qui indiquent à Smarty d'ignorer le contenu. En PrestaShop 8.x, la meilleure approche reste de charger un fichier .js externe via un module et le hook actionFrontControllerSetMedia.
La technique consiste à utiliser un flag JavaScript (une variable booléenne) qui passe à true dès le premier clic. Lors des clics suivants, le formulaire est bloqué via e.preventDefault(). Combinez cela avec la désactivation visuelle du bouton (disabled + opacity réduite) et l'affichage d'un loader pour informer le client que sa commande est en cours de traitement. Côté serveur, PrestaShop dispose également d'un token CSRF qui protège contre les soumissions multiples.
Placez votre script juste avant la balise fermante </body> dans le template checkout.tpl de votre thème. Cette position garantit que le DOM est chargé avant l'exécution. Pour une solution plus propre et compatible avec les mises à jour, créez un module qui utilise le hook actionFrontControllerSetMedia pour enregistrer votre fichier JS avec registerJavascript(). Cela évite de modifier les fichiers du thème directement.
Activez d'abord le mode debug (APP_DEBUG=1 dans .env pour PS 8.x, ou _PS_MODE_DEV_ dans defines.inc.php pour PS 1.7) pour obtenir le message d'erreur exact. Si ce n'est pas suffisant, consultez les logs du serveur web (error.log d'Apache ou Nginx). Les causes les plus courantes sont des accolades JavaScript non protégées par {literal}, un fichier corrompu lors du transfert FTP, ou un cache Smarty obsolète. Comparez vos fichiers avec une installation vierge de la même version pour isoler le problème.
Le loader basé sur l'événement submit du formulaire #payment-confirmation fonctionne avec la majorité des modules de paiement natifs et tiers qui utilisent le flux standard de PrestaShop. Cependant, certains modules de paiement (Stripe, PayPal) redirigent vers une iframe ou une popup externe avant la soumission du formulaire. Dans ce cas, adaptez le sélecteur JavaScript au bouton spécifique du module ou utilisez un MutationObserver pour détecter dynamiquement les changements dans le DOM du checkout.
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.