PS PrestaShop Intermédiaire

Smart Offers — Documentation complète

Tout ce qu'il faut savoir pour configurer et exploiter le module Smart Offers sur PrestaShop 8 et 9 : les quatre types d'offres groupées, le moteur d'ajout automatique au panier et la procédure de migration.

Mis à jour Version du module 2.0.0

Smart Offers est un module compatible PrestaShop 8 et 9 qui permet de créer des offres groupées 1+1, packs en gros, packs multi-produits et offres au choix, avec ajout automatique des produits offerts au panier et présentation soignée sur la fiche produit.

Aperçu

Smart Offers couvre les quatre formats d’offres groupées les plus utilisés en e-commerce dans un seul module, sans configuration complexe. Le moteur évalue le panier à chaque modification, ajoute automatiquement les produits offerts dès que les conditions sont remplies, et crée une règle de panier qui rend ces unités gratuites. L’expérience client est immédiate et lisible.

En bref : Le marchand crée une offre en moins d’une minute via une interface visuelle, le client voit le cadeau apparaître automatiquement dans son panier avec un indicateur clair, et le tracking interne permet une révocation propre si le client retire un déclencheur en cours de session.

Compatibilité PrestaShop 8 et 9

Depuis la version 2.0.0, un seul fichier ZIP couvre PrestaShop 8.0 à 9.x. Il n’y a pas de branche séparée à choisir au téléchargement : le module détecte la version de la boutique à l’exécution et adapte ses appels aux API qui ont changé entre les deux générations.

Élément PrestaShop 8 PrestaShop 9
Version PHP requise 7.4 à 8.3 8.1 à 8.3
Schéma de base de données Identique, six tables ps_dfoffers_*
Hooks utilisés Identiques
Configuration des offres Identique, migration transparente
Les différences d’API sont regroupées dans une seule classe interne, DfOfferCompat. Si vous surchargez du code du module dans un projet sur mesure, c’est le seul fichier à consulter pour comprendre les branchements de version.

Installation

  1. Téléchargez le fichier dfoffers-vX.Y.Z.zip depuis votre espace client DataFirefly
  2. Dans le back office PrestaShop, allez dans Modules → Gestionnaire de modules
  3. Cliquez sur le bouton Uploader un module en haut de la page
  4. Glissez-déposez le fichier ZIP ou cliquez pour le sélectionner
  5. L’installation est automatique : les tables sont créées, les hooks enregistrés, et un nouvel onglet Catalogue → Offres groupées apparaît dans le menu
Aucune dépendance externe n’est requise. Le module utilise les classes natives de PrestaShop (Cart, CartRule, Product) et n’ajoute rien à votre composer.json.

Les quatre types d’offres

1+1 sur le même produit

Le format viral du buy-one-get-one : le client achète une unité d’un produit et reçoit gratuitement une autre unité du même produit. Vous configurez :

  • Un seul produit (qui sert à la fois de déclencheur et de récompense)
  • La quantité à acheter pour déclencher l’offre (généralement 1)
  • La quantité offerte (généralement 1)

Exemple typique : « Pour 1 paire de chaussettes achetée, la deuxième est offerte. » Quand le client ajoute la paire à son panier, le moteur en ajoute automatiquement une seconde et applique une remise égale au prix unitaire.

Achetez X, recevez Y offerts (produits différents)

Format de bundle : plusieurs produits déclencheurs distincts doivent être présents dans le panier pour que l’offre s’active, et un ou plusieurs produits différents sont alors offerts. Vous configurez :

  • La liste des produits déclencheurs avec leur quantité respective
  • La liste des produits offerts avec leur quantité respective

Exemple typique : « Pour l’achat conjoint d’une crème de jour et d’un sérum, recevez un échantillon de masque offert. » Le moteur vérifie que tous les déclencheurs sont présents avant d’activer l’offre.

Choix parmi des déclinaisons

Format de composition libre : vous définissez un ensemble de produits ou de déclinaisons candidates parmi lesquelles le client compose son lot. Le moteur identifie automatiquement les unités les moins chères du panier comme étant les unités offertes, ce qui correspond à l’interprétation commerciale standard du buy-N-get-M.

  • La liste des produits ou déclinaisons candidats
  • Le nombre d’unités à acheter dans cet ensemble
  • Le nombre d’unités offertes (les moins chères)

Exemple typique : « 3 t-shirts achetés parmi notre sélection, le moins cher est offert. » Le client compose son lot, le moteur ne touche pas à son panier mais applique la remise sur les unités les moins chères.

Pack en gros

Format B2B et écoulement de stock : pour chaque lot de X unités achetées d’un produit, le client reçoit Y unités gratuites d’un autre produit. Vous configurez :

  • Le produit déclencheur avec la quantité de palier (par exemple 10)
  • Le produit offert avec la quantité offerte (par exemple 20)

Exemple typique : « Pour 10 bouteilles de vin achetées, 2 verres offerts. » Pratique pour les fournisseurs qui veulent pousser un produit complémentaire ou écouler un stock dormant en l’attachant à un produit qui se vend bien.

Créer votre première offre

Depuis le back office, allez dans Catalogue → Offres groupées puis cliquez sur Nouvelle offre.

Étape 1 : choisir le type

Quatre cartes visuelles vous présentent les types disponibles avec une courte description. Cliquez sur celle qui correspond à votre opération commerciale. Le formulaire s’adapte automatiquement et ne montre que les champs pertinents pour ce type.

Étape 2 : nommer et badger l’offre

Renseignez :

  • Nom de l’offre (obligatoire) : c’est ce que verra le client dans la bannière. Disponible en cinq langues.
  • Texte du badge (optionnel, 64 caractères max) : court message qui s’affiche dans la pill en haut de la bannière (par exemple 1+1 OFFERT, OFFRE SPÉCIALE, BLACK FRIDAY).
  • Couleur du badge : six presets DataFirefly disponibles plus un sélecteur de couleur libre. La couleur sert pour la bannière fiche produit ET pour la pastille cadeau côté panier.

Étape 3 : ajouter les produits déclencheurs

Cliquez sur Ajouter un produit déclencheur. Une modale de recherche s’ouvre avec un champ qui interroge votre catalogue en direct (recherche débrayée à 250 ms après la dernière frappe). Tapez un nom, une référence ou un EAN ; les résultats apparaissent immédiatement.

Cliquez sur le produit pour l’ajouter. Si le produit a des déclinaisons, les variantes apparaissent comme boutons sous le résultat, cliquez sur celle qui vous intéresse pour l’ajouter directement. Précisez la quantité requise dans le champ qui apparaît à droite de la ligne.

Étape 4 : ajouter les produits offerts

Même procédure pour les produits offerts. Cette section est masquée pour le type Choix parmi des déclinaisons, puisque les déclinaisons servent à la fois de candidats et de récompenses.

Étape 5 : règles spécifiques

  • Cumulable : si activé, l’offre s’applique plusieurs fois pour chaque lot déclencheur. Sans cumul, l’offre s’applique une seule fois quel que soit le nombre d’unités. Désactivé par défaut pour protéger vos marges.
  • Pour le type Choix parmi des déclinaisons, deux champs supplémentaires apparaissent : combien d’unités le client doit acheter, et combien sont offertes.

Étape 6 : activation

  • Dates de validité : laissez vides pour une offre permanente. Renseignez la date de début ou de fin pour automatiser l’activation. Depuis la 2.0.0, une date illisible est rejetée au lieu d’être enregistrée au 1er janvier 1970, et la date de fin doit être postérieure à la date de début.
  • Priorité : si plusieurs offres peuvent s’appliquer simultanément, celle avec la priorité la plus basse est évaluée en premier.
  • Statut : interrupteur on/off, par défaut activé. Pratique pour désactiver temporairement une offre sans la supprimer.

Étape 7 : boutiques (si multi-boutique)

Cochez les boutiques sur lesquelles l’offre doit être disponible. Ne rien cocher revient à activer l’offre sur toutes les boutiques.

Comment fonctionne le moteur d’ajout automatique

Le moteur s’accroche au hook PrestaShop actionCartSave et s’exécute à chaque modification du panier (ajout, retrait, changement de quantité, fusion lors de la connexion).

  1. Il récupère toutes les offres actives pour la boutique courante
  2. Pour chaque offre, il calcule la quantité payée de chaque produit déclencheur (quantité totale du panier moins ce que le moteur a déjà auto-ajouté lors d’une évaluation précédente)
  3. Il évalue si les conditions de l’offre sont remplies
  4. Si oui, il ajoute les produits offerts manquants au panier via Cart::updateQty
  5. Il crée ou met à jour une règle de panier (CartRule) avec une remise fixe TTC égale à la valeur des unités offertes
  6. Il enregistre dans la table ps_dfoffers_cart_auto les unités qu’il a ajoutées, pour pouvoir les distinguer des unités que le client a ajoutées lui-même
Le moteur protège contre les boucles infinies : Cart::updateQty rejoue le hook actionCartSave, mais une garde statique dans le module empêche la récursion.

Révocation propre

Si le client retire un produit déclencheur ou réduit sa quantité en dessous du seuil, le moteur réévalue l’offre lors du actionCartSave suivant. Si la condition n’est plus remplie, il retire les unités qu’il avait auto-ajoutées (sans toucher aux unités que le client avait ajoutées lui-même grâce au tracking) et supprime la règle de panier associée.

Affichage sur la fiche produit

Sur chaque fiche produit déclencheuse, une bannière en dégradé s’affiche via le hook displayProductAdditionalInfo. Elle contient :

  • Un badge pill en blanc avec icône cadeau, contenant le texte du badge
  • Le titre de l’offre
  • Un message dynamique qui dépend du type d’offre (« Ajoutez 1 produit, recevez-en 1 gratuit », « Pour 10 unités achetées, 20 unités offertes », etc.)
  • Une grille avec les vignettes cliquables des produits concernés, séparés en deux groupes Achetez / Recevez offert avec un séparateur SVG circulaire entre les deux

La couleur de la bannière reprend celle du badge configurée dans l’offre. Le rendu est responsive : sur mobile, les deux groupes s’empilent verticalement et le séparateur pivote pour pointer vers le bas.

Affichage dans le panier

Depuis la version 1.1.0, deux indicateurs distincts aident le client à identifier les produits offerts dans son panier.

Pastille cadeau sur chaque ligne

Sur chaque ligne du panier qui contient des unités auto-ajoutées par une offre, une petite pastille colorée 🎁 ×N offert apparaît à côté des actions de ligne. La couleur reprend celle du badge de l’offre, et la pastille indique combien d’unités de cette ligne sont gratuites (utile quand une partie de la quantité est payée et l’autre offerte, par exemple sur un 1+1 même produit).

Cette pastille s’affiche via le hook displayCartExtraProductActions, présent dans les thèmes standards de PrestaShop 8 et 9 qui suivent la structure native de cart-detailed-product-line.tpl.

En bas de la grille des produits, un bloc vert récapitule les offres activées dans le panier. Pour chaque offre, le bloc affiche :

  • Le nom de l’offre et son texte de badge (en pill colorée)
  • La liste des produits offerts par cette offre, sous forme de chips visuels avec vignette ronde, nom et quantité
  • Chaque chip est cliquable et renvoie vers la fiche produit du cadeau

Le client peut ainsi vérifier d’un coup d’œil ce qu’il a obtenu gratuitement et grâce à quelle opération commerciale.

Cas particuliers et comportements

Pourquoi le 1+1 sur le même produit est traité spécifiquement

Quand le produit déclencheur est aussi le produit récompense, beaucoup de modules d’offres groupées du marché commettent l’erreur d’identifier l’unité payée du client comme étant déjà l’unité offerte, et appliquent la remise sur cette unité. Au final, le client paie zéro pour une unité au lieu de payer pour une et en recevoir une seconde gratuite.

Smart Offers gère ce cas avec une logique précise : la quantité cible dans le panier vaut quantité payée par le client + quantité récompense. Quand le client ajoute une unité, le moteur en ajoute une seconde pour que le panier contienne deux unités, et la remise s’applique sur la seconde unité uniquement. Le client paie donc le prix d’une unité pour en avoir deux dans son panier.

Cumul des lots (option stackable)

Sans cumul, l’offre s’applique une seule fois quel que soit le nombre de lots déclencheurs présents dans le panier. Si le client achète 5 unités d’un produit avec une offre 1+1 et stackable désactivé, il recevra 1 unité offerte (pas 5).

Avec cumul activé, le moteur multiplie le nombre de lots de récompenses par le nombre entier de lots déclencheurs présents. Pour la même offre 1+1 avec stackable activé et 5 unités au panier, le client recevra 5 unités offertes (panier final : 10 unités, 5 payées).

L’option stackable est désactivée par défaut. Activez-la avec précaution : elle peut entamer significativement vos marges sur les opérations à fort volume.

Stock et indisponibilité

L’ajout des produits offerts au panier passe par Cart::updateQty, qui respecte les règles de stock natives de PrestaShop. Si un produit offert est en rupture et que la boutique n’autorise pas la commande en rupture, l’ajout échoue silencieusement et la remise n’est pas appliquée. La condition reste prête à se déclencher dès le réapprovisionnement.

Plusieurs offres simultanées sur un même panier

Chaque offre génère sa propre règle de panier avec partial_use activé. Cela permet d’empiler plusieurs offres concurrentes sur un même panier sans conflit, et reste compatible avec les codes promo classiques que vos clients peuvent saisir.

Architecture technique

Hooks utilisés

  • displayProductAdditionalInfo : bannière sur la fiche produit
  • displayShoppingCartFooter : footer détaillé sur la page panier
  • displayCartExtraProductActions : pastille cadeau sur chaque ligne du panier
  • actionCartSave : moteur d’évaluation et d’ajout automatique
  • actionFrontControllerSetMedia et actionAdminControllerSetMedia : injection des CSS et JS
  • actionObjectProductDeleteAfter : nettoyage automatique des offres référençant un produit supprimé

Depuis la 2.0.0, seuls actionCartSave et actionFrontControllerSetMedia sont considérés comme indispensables à l’installation. Les hooks d’affichage qu’un thème n’implémenterait pas sont journalisés sans faire échouer l’installation.

Tables ajoutées

  • ps_dfoffers_offer : configuration de chaque offre (type, dates, priorité, cumul)
  • ps_dfoffers_offer_lang : nom, badge et description traduits par langue
  • ps_dfoffers_trigger : produits déclencheurs de chaque offre
  • ps_dfoffers_reward : produits récompenses de chaque offre
  • ps_dfoffers_shop : association offre / boutique en multi-boutique
  • ps_dfoffers_cart_auto : tracking des unités auto-ajoutées par panier et par offre, avec l’identifiant de la règle de panier générée

Toutes les tables sont préfixées par le préfixe configuré dans votre installation PrestaShop (ps_ par défaut). Le schéma est identique sur PrestaShop 8 et 9, ce qui rend la migration transparente.

La classe DfOfferCompat

Toutes les différences d’API entre PrestaShop 8 et 9 sont concentrées dans classes/DfOfferCompat.php. Le reste du module ne teste jamais la version de PrestaShop directement. Les points absorbés par cette classe :

  • Lecture des déclinaisons : PrestaShop 9 a retiré l’argument de langue de Product::getAttributeCombinations(), où le premier paramètre est désormais le drapeau booléen de regroupement.
  • URL AJAX du backoffice : sur PrestaShop 9, le couple ajax et action doit transiter par le quatrième argument de getAdminLink(), car le jeton est calculé avant la fusion des paramètres.
  • Réponse JSON : la méthode d’envoi porte volontairement un autre nom que ajaxRender(), dont la signature parente ne doit pas être surchargée.
  • Onglet admin : PrestaShop 9 a introduit des colonnes de traduction supplémentaires, renseignées sous garde pour ne pas créer de propriété dynamique sur PrestaShop 8.

Surcharger les templates dans votre thème

Le CSS du module est isolé sous le préfixe .dfoffers- pour éviter tout conflit avec votre feuille de style. Si vous souhaitez modifier le rendu, copiez les templates depuis /modules/dfoffers/views/templates/hook/ vers /themes/votre-theme/modules/dfoffers/views/templates/hook/ et personnalisez-les. Trois templates sont disponibles :

  • product-banner.tpl : bannière sur la fiche produit
  • cart-offer.tpl : bloc récapitulatif dans le footer panier
  • cart-line-gift.tpl : pastille cadeau inline sur les lignes du panier

Mise à jour du module

Pour mettre à jour vers une nouvelle version, uploadez simplement le nouveau ZIP depuis le Gestionnaire de modules. PrestaShop détecte le changement de version dans config.xml et exécute automatiquement les scripts d’upgrade présents dans /upgrade/upgrade-X.Y.Z.php, qui s’occupent par exemple d’enregistrer de nouveaux hooks ajoutés entre deux versions.

Aucune désinstallation/réinstallation n’est nécessaire entre les versions, et vos offres existantes sont préservées intactes.

Migrer une boutique de PrestaShop 8 vers PrestaShop 9

Le schéma de base de données étant identique, vos offres, vos traductions et vos associations de boutiques passent la migration sans transformation. La procédure recommandée :

  1. Passez le module en 2.0.0 avant de migrer la boutique, pendant qu’elle tourne encore sous PrestaShop 8. La version 2.0.0 fonctionne sur les deux générations, vous réduisez donc le nombre de variables si quelque chose se passe mal.
  2. Migrez la boutique vers PrestaShop 9 selon la procédure officielle PrestaShop.
  3. Rendez-vous dans Conception → Positions et vérifiez que les six hooks du module sont toujours attachés. Une migration peut en perdre.
  4. Si des hooks manquent, réuploadez le ZIP 2.0.0 : le script upgrade-2.0.0.php réenregistre chaque hook absent et purge les lignes de suivi dont le panier a disparu.
PrestaShop 9 exige PHP 8.1 au minimum. Vérifiez la version de PHP de votre hébergement avant de lancer la migration : c’est la cause la plus fréquente d’échec, bien avant les modules.

Dépannage

Les produits offerts ne s’ajoutent pas au panier

  1. Videz le cache PrestaShop dans Paramètres avancés → Performance
  2. Vérifiez que le hook actionCartSave contient bien le module dans Conception → Positions
  3. Vérifiez que le produit offert est disponible (pas en rupture si la commande en rupture est interdite, pas désactivé, assigné à la boutique courante)
  4. Consultez Paramètres avancés → Logs en cherchant dfoffers : le moteur trace son exécution à chaque ajout au panier

La remise ne s’applique pas malgré l’ajout du produit

Vérifiez dans les logs la ligne checkValidity qui suit la création de la règle de panier. PrestaShop y indique précisément pourquoi une règle est rejetée (rupture de stock, restriction client, devise différente, etc.).

La pastille cadeau n’apparaît pas sur les lignes du panier

Vérifiez que votre thème implémente bien le hook displayCartExtraProductActions dans cart-detailed-product-line.tpl. Les thèmes Classic de PrestaShop 8 et 9 ainsi que la plupart des thèmes commerciaux le contiennent. Si vous utilisez un thème custom qui ne l’implémente pas, ajoutez la ligne suivante dans votre fichier cart-detailed-product-line.tpl au niveau souhaité :

{hook h='displayCartExtraProductActions' product=$product}

La recherche produit du backoffice ne renvoie rien après une migration en PrestaShop 9

Videz le cache PrestaShop puis rechargez la page de création d’offre. L’URL de l’endpoint de recherche est construite côté serveur au rendu du formulaire ; une page mise en cache avant la migration peut encore porter une ancienne URL. Si le problème persiste, ouvrez la console du navigateur : une réponse 404 sur la requête de recherche indique que l’onglet du module n’a pas été correctement recréé, et une réinstallation du module le corrige sans perdre les offres.

L’installation semble réussir mais aucune offre ne peut être créée

Avant la 2.0.0, un échec de création de table pendant l’installation était silencieux et le module s’affichait comme installé. Depuis la 2.0.0, cette situation fait échouer l’installation avec un message explicite. Si vous rencontrez ce cas sur une ancienne version, vérifiez les droits de l’utilisateur MySQL sur la création de tables, puis désinstallez et réinstallez le module en 2.0.0.

Foire aux questions

Le module est-il compatible avec PrestaShop 9 ?

Oui, depuis la version 2.0.0. Le même fichier ZIP s’installe sur PrestaShop 8.0 comme sur PrestaShop 9.x. Les différences d’API sont absorbées par la classe interne DfOfferCompat, il n’y a donc pas de branche séparée à choisir au téléchargement. Les versions 1.x restaient limitées à PrestaShop 8.0 à 8.99.

Quel est l’impact sur les performances ?

Le moteur exécute une requête SQL par offre active sur la boutique, puis évalue les conditions en mémoire. Sur un catalogue avec une dizaine d’offres actives, l’évaluation complète prend en moyenne moins de cinquante millisecondes. Ce chiffre est identique sur PrestaShop 8 et 9.

Puis-je utiliser le module avec un thème headless ?

Le moteur d’ajout automatique est indépendant du thème et fonctionne pour tout front qui passe par Cart::updateQty ou l’API REST PrestaShop. La bannière fiche produit et la pastille cadeau panier sont des hooks Smarty natifs qui nécessitent un thème classique pour s’afficher. Pour un front headless, vous pouvez exposer les données via une API custom qui interroge directement ps_dfoffers_offer et ps_dfoffers_cart_auto.

Le module gère-t-il les devises multiples ?

Oui. La règle de panier générée pour chaque offre utilise la devise du panier en cours. Si le client change de devise, la règle est régénérée à la valeur correcte au prochain actionCartSave.

Que se passe-t-il si je clique sur Réinitialiser dans le gestionnaire de modules ?

Le module est désinstallé puis réinstallé dans la même requête, ce qui supprime puis recrée les tables : toutes vos offres sont perdues. Depuis la 2.0.0 cette opération recrée correctement les tables, alors que les versions antérieures laissaient la boutique sans tables du tout. Dans les deux cas, sauvegardez avant de réinitialiser.

Cette page vous a-t-elle été utile ?

Toujours bloqué ? Contactez le support