Table des matières :
- SMS conversationnel : où commence la prospection et où s’arrête le “transactionnel”
- Opt-in SMS : collecte valide, preuve opposable et granularité (marketing vs service)
- Mentions STOP : mécanisme de retrait, droit d’opposition et pièges d’implémentation
- Implémentation PrestaShop (8.1/9.1, PHP 8.2+) : modèle de données, hooks, webhooks
- RGPD “dur” : minimisation, conservation, sous-traitance, sécurité et traçabilité
- Qualité produit et exploitation : tests, observabilité, et conformité qui tient en prod
SMS conversationnel : où commence la prospection et où s’arrête le “transactionnel”
Le terme SMS conversationnel recouvre en pratique deux flux distincts : (1) des notifications liées à l’exécution d’un contrat (statut de commande, livraison, SAV) et (2) des échanges à finalité commerciale (relance panier, upsell, codes promo) qui, eux, basculent dans la prospection. D’un point de vue conformité, ce n’est pas le canal “conversationnel” qui compte mais la finalité et la base légale. La frontière est souvent franchie quand on “profite” d’un message SAV pour injecter une offre (« -10% sur votre prochain achat »). Techniquement, vous devez donc tracer la finalité au niveau message, pas seulement au niveau campagne.
Pour rendre cette frontière opérationnelle, raisonnez “contenu dominant” + “moment” + “attente raisonnable” du client :
- Dominant transactionnel : “Votre colis est en cours de livraison” (utile, attendu, rattaché à une commande).
- Dominant marketing : “-15% jusqu’à minuit” (incitation à l’achat, pas nécessaire au contrat).
- Zone grise (à traiter comme marketing si doute) : “Votre commande est prête. Au fait, découvrez notre nouvelle collection.” Le deuxième morceau n’est pas nécessaire à l’exécution du contrat.
Mini-scénario (typique e-commerce) : vous gérez un incident transport. Vous envoyez : “Désolé, livraison décalée de 24h.” Dans le même fil, ajouter “Pour nous excuser : -10% sur votre prochaine commande” fait basculer le message dans la prospection. Même si l’intention est “commerciale bienveillante”, côté conformité vous mélangez deux finalités (SAV + promotion) et vous vous exposez à (1) l’absence de base légale marketing, (2) l’absence de mention STOP si votre process ne l’ajoute que sur les campagnes.
En Europe, le SMS marketing est soumis à un double cadre : RGPD (données personnelles, consentement, sécurité, droits) et ePrivacy (règles spécifiques à la prospection électronique). Côté RGPD, la base légale la plus robuste pour du SMS promotionnel reste le consentement (article 6(1)(a)), avec des obligations fortes de preuve et de retrait. L’article 7(1) du RGPD est explicite : « Lorsque le traitement est fondé sur le consentement, le responsable du traitement doit être en mesure de démontrer que la personne concernée a donné son consentement au traitement de ses données à caractère personnel. » (RGPD, art. 7(1), source : EUR-Lex).
Deux conséquences concrètes côté produit :
- Vous devez étiqueter chaque SMS (au minimum
servicevsmarketing) au niveau du template / event métier, car la conformité se joue au message. - Vous devez pouvoir prouver, pour un numéro donné, ce qui a été envoyé, pourquoi, et sur quelle base (consentement, contrat, etc.). Sans cette capacité, le “conversationnel” devient un angle mort : on discute avec le client, mais on ne sait plus qualifier juridiquement les envois.
Enfin, le “conversationnel” implique souvent un canal bidirectionnel (réponses clients) et donc de nouveaux risques : stockage de contenus libres, PII “accidentelles” (adresse, IBAN, infos santé), et besoin de modération/filtrage. Sur PrestaShop, rien dans le cœur ne vous protège contre ces dérives : vous devez imposer des règles d’acceptation, de rétention et d’accès à ces messages comme vous le feriez pour un formulaire de contact.
Pour cadrer la partie bidirectionnelle, pensez dès le départ à trois garde-fous simples :
- Filtrage : bloquer/masquer automatiquement certains patterns (IBAN, emails, URLs) dans les logs si vous n’en avez pas besoin.
- Contrôle d’accès : limiter l’affichage des inbound SMS aux profils back-office strictement nécessaires (support, DPO, admin technique), avec traçabilité.
- Règles de réponse : ne jamais déclencher un message “automatique” ambigu (ex. une relance marketing) après une interaction SAV, sans requalification explicite et sans vérifier l’opt-in marketing.
Opt-in SMS : collecte valide, preuve opposable et granularité (marketing vs service)
Un opt-in SMS conforme n’est pas juste une case cochée. Il doit être libre, spécifique, éclairé et univoque (voir considérant 32 du RGPD sur “l’acte positif clair”, même source EUR-Lex). Concrètement, évitez les opt-ins groupés (“email + SMS”) : vous perdez la spécificité et vous compliquez la preuve. Implémentez au minimum deux consentements : sms_service (notifications) et sms_marketing (prospection). Le second doit être désactivé par défaut.
Sur le terrain, la granularité évite deux problèmes fréquents :
- Support bloqué par erreur : un client veut les notifications de livraison mais refuse les promos. Si tout est fusionné, votre équipe “coupe tout” et se retrouve à gérer plus de tickets (“je n’ai pas reçu le code livreur”).
- Marketing envoyé par défaut : des boutiques considèrent à tort que “si le client a donné son numéro, on peut envoyer”. Ce raccourci est précisément ce que la notion d’opt-in vise à empêcher en prospection.
La preuve ne se limite pas au fait que la case était cochée : vous devez pouvoir reconstituer le contexte. Stockez à l’instant T : numéro (ou une version normalisée), identifiant client, date/heure UTC, source (checkout, compte client, pop-in), langue, version du texte d’information, IP, user-agent, identifiant boutique (multistore) et, si possible, un hash d’intégrité. L’objectif est de pouvoir produire un “audit trail” en cas de contrôle ou de litige (“je n’ai jamais demandé ça”). Ne pas tracer la version du texte d’opt-in est une erreur classique : quand votre wording change, vous ne savez plus ce que l’utilisateur a accepté.
Checklist “preuve d’opt-in opposable” (utile pour vos specs et pour le DPO) :
| Élément à tracer | Pourquoi c’est utile | Exemple |
|---|---|---|
phone_e164 |
dédoublonnage + preuve sur le bon numéro | +33612345678 |
purpose |
spécificité du consentement | marketing |
status + horodatage |
prouver le moment et l’état | opt_in à 2026-06-03T09:12:00Z |
source |
prouver le parcours (checkout vs pop-in) | checkout |
text_version |
prouver le contenu accepté | optin_sms_v3_fr |
id_shop |
multiboutique / marques | 1 |
| IP + user-agent (si pertinent) | aider en cas de contestation | IP v4/v6 |
| empreinte/hash | intégrité et non-altération | hash du contexte |
Astuce produit : si vous gérez plusieurs pays / langues, versionnez non seulement le texte, mais aussi la langue (ou la locale) et la page où l’opt-in a été collecté. En cas de litige, c’est souvent le détail qui permet de répondre rapidement (“opt-in collecté sur checkout FR, version v3, le 12/04, depuis IP …”).
Le “double opt-in” n’est pas systématiquement exigé pour le SMS comme il peut l’être par politique interne sur l’email, mais il est utile pour réduire les opt-ins frauduleux (numéro saisi d’un tiers) et les erreurs de saisie. En pratique : (1) collecte du numéro, (2) envoi d’un OTP, (3) activation du consentement uniquement après validation. C’est aussi une mesure de minimisation des coûts : vous évitez d’envoyer des campagnes sur des numéros invalides. Attention : un OTP est un traitement à finalité “sécurité/validation”, ne le recyclez pas pour du marketing.
Point d’attention souvent sous-estimé : l’UX de l’opt-in doit éviter toute ambiguïté. Exemple de wording robuste (à adapter avec votre DPO) : “J’accepte de recevoir des offres et promotions par SMS. Je peux me désinscrire à tout moment en répondant STOP.” L’intérêt n’est pas marketing, il est probatoire : vous rattachez la promesse (offres) au mécanisme de retrait (STOP), ce qui réduit les contestations.
Mentions STOP : mécanisme de retrait, droit d’opposition et pièges d’implémentation
Sur le plan juridique, votre “STOP” est l’implémentation opérationnelle de deux règles RGPD : le retrait du consentement (art. 7(3) : « La personne concernée a le droit de retirer son consentement à tout moment. ») et l’opposition à la prospection (art. 21(2) : « Lorsque des données à caractère personnel sont traitées à des fins de prospection, la personne concernée a le droit de s’opposer à tout moment au traitement des données à caractère personnel la concernant à de telles fins de prospection. ») — source : EUR-Lex. Techniquement, la conséquence est non négociable : un opt-out doit être pris en compte immédiatement, pas “à la prochaine synchro”.
En pratique, “immédiatement” doit être interprété comme : dès réception du message entrant (ou du callback provider), vous devez empêcher tout nouvel envoi marketing vers ce MSISDN, y compris via des jobs déjà en queue. Concrètement :
- mettez l’opt-out dans une table consultée avant envoi,
- et, si vous avez une file (queue), prévoyez un mécanisme d’annulation ou de re-check au moment d’exécuter le job (sinon vous avez un délai incompressible).
Le piège principal en SMS conversationnel est la diversité des retours. Les utilisateurs ne répondent pas uniquement “STOP” : vous verrez stop, Stop, STOP SMS, unsubscribe, ARRET, ou un message contenant STOP au milieu. Implémentez un parseur robuste : normalisation Unicode, trim, uppercasing, suppression des accents, détection par regex sur mots entiers. Conservez la preuve du STOP (contenu brut + timestamp + identifiant message entrant + MSISDN) mais limitez la rétention (cf. section rétention). Et surtout : ne renvoyez pas automatiquement un message marketing “pour confirmer” si l’utilisateur vient d’opt-out.
Deux bonnes pratiques simples pour réduire le risque “STOP non compris” :
- Liste de mots-clés : supportez au minimum STOP / ARRET / UNSUBSCRIBE (en fonction de vos marchés) et documentez-le (utile pour le support).
- Tolérance au bruit : si un utilisateur répond “stop svp” ou “STOP!!!”, cela doit être interprété comme un STOP.
Deuxième piège : votre prestataire SMS. Selon que vous utilisez un short code, un émetteur alphanumérique, ou un numéro long, la gestion des réponses et STOP dépend des opérateurs et de l’API (webhooks, callbacks, DLR). Certains providers proposent un “opt-out automatique” au niveau compte, mais ce mécanisme est rarement aligné avec votre segmentation interne (par boutique, par marque, par finalité). Dans un contexte PrestaShop multi-boutiques, il est généralement plus sûr de traiter les messages entrants via webhook et de réconcilier l’opt-out dans votre base, sinon vous aurez des divergences (le provider bloque, votre SI pense que le client est opt-in).
Dernier point (très opérationnel) : vos équipes marketing aiment parfois “raccourcir” les SMS. Assurez-vous que la mention STOP soit intégrée dans vos templates marketing de façon systématique (par exemple via un footer ajouté côté code), pour éviter qu’une campagne parte sans mécanisme de retrait visible. C’est le genre d’erreur qui n’apparaît qu’une fois… mais qui coûte cher en plaintes et en réputation.
Implémentation PrestaShop (8.1/9.1, PHP 8.2+) : modèle de données, hooks, webhooks
Contexte cible : PrestaShop 8.1+ et 9.1, PHP 8.2/8.3, MySQL/MariaDB. Prérequis : accès au code du module, accès HTTPS public pour recevoir des webhooks, et sauvegarde BDD avant migration (les schémas de consentement impactent des données personnelles). Le cœur de PrestaShop ne fournit pas de couche native “consentement par canal” suffisamment fine pour le SMS ; vous devez donc ajouter vos tables et vous brancher sur les bons hooks.
Un schéma minimaliste mais exploitable côté module :
CREATE TABLE ps_sms_consent (
id_sms_consent INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
id_customer INT UNSIGNED NULL,
phone_e164 VARCHAR(20) NOT NULL,
purpose ENUM('service','marketing') NOT NULL,
status ENUM('opt_in','opt_out') NOT NULL,
legal_basis ENUM('consent','contract','legitimate_interest') NOT NULL,
text_version VARCHAR(64) NULL,
source VARCHAR(32) NOT NULL,
ip VARBINARY(16) NULL,
user_agent VARCHAR(255) NULL,
id_shop INT UNSIGNED NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
UNIQUE KEY uniq_consent (phone_e164, purpose, id_shop)
);
CREATE TABLE ps_sms_inbound (
id_sms_inbound BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
provider_msg_id VARCHAR(128) NULL,
phone_e164 VARCHAR(20) NOT NULL,
body TEXT NOT NULL,
received_at DATETIME NOT NULL,
raw_payload JSON NULL,
id_shop INT UNSIGNED NOT NULL
);
Points clés : (1) stockez le téléphone en E.164 (ex. +336…) pour éviter les doublons, (2) séparez “service” vs “marketing”, (3) legal_basis vous permet de justifier l’envoi (ex. SMS de livraison basé sur contrat), (4) text_version évite l’impasse juridique du “consentement sans texte”. Sur la collecte, branchez-vous typiquement sur des formulaires custom (compte client) et sur le tunnel de commande. Sur l’envoi “service”, hookez actionValidateOrder (confirmation) et les événements transporteurs si vous avez une intégration logistique.
Pour fiabiliser la collecte, pensez aussi à couvrir les moments où le numéro apparaît “hors checkout” :
- création de compte (si vous collectez le téléphone),
- ajout/modification d’adresse (le téléphone est souvent rattaché à l’adresse),
- import client (ERP/CRM) : attention, un import ne crée pas un consentement par magie ; tagguez la source et la base légale.
Côté webhook, exposez un endpoint Symfony (PrestaShop 8/9) ou un front controller sécurisé. Validez la signature HMAC fournie par le prestataire, logguez le payload brut, puis appliquez une transaction : insert inbound, détection STOP, mise à jour ps_sms_consent en opt_out pour purpose='marketing' (voire 'service' si votre politique l’exige). Exemple de logique (pseudo-code) :
$body = normalize($request->get('Body'));
$msisdn = toE164($request->get('From'));
storeInbound($msisdn, $request);
if (isStopKeyword($body)) {
upsertConsent($msisdn, 'marketing', 'opt_out');
// Optionnel : répondre une confirmation neutre.
}
Ne réutilisez pas ps_customer.phone de manière naïve : dans PrestaShop, le téléphone est souvent porté par ps_address (et peut varier par adresse). En pratique, gardez votre référence “numéro SMS” dans votre propre table et liez-le à id_customer quand c’est possible. Sinon, vous vous exposez à envoyer un SMS à un numéro recyclé dans une ancienne adresse.
Deux précisions d’architecture qui évitent des incidents :
- Idempotence : un provider peut renvoyer un webhook (retry). Utilisez
provider_msg_id(quand disponible) ou une empreinte du payload pour ne pas traiter deux fois le même STOP. - Priorité STOP : si vous avez des envois en file, faites un dernier check “opt-out ?” juste avant l’appel API d’envoi. C’est souvent ce dernier verrou qui empêche des messages marketing de partir après un STOP reçu quelques secondes plus tôt.
RGPD “dur” : minimisation, conservation, sous-traitance, sécurité et traçabilité
Le SMS conversationnel force à traiter des données à caractère personnel à plusieurs niveaux : numéro, contenu, métadonnées (timestamp, IP) et parfois identifiants de commande. Appliquez la minimisation : ne stockez pas plus que nécessaire, et ne stockez pas “juste au cas où”. Par exemple, pour prouver un opt-in, le contenu complet de l’OTP n’a aucun intérêt ; pour prouver un STOP, le message entrant peut être conservé, mais vous pouvez ensuite ne garder qu’un indicateur “STOP reçu” + hash du contenu après une courte période.
La conservation doit être explicitée et automatisée (cron). Exemple réaliste : inbound/outbound conservés 90 jours pour débogage et contestations, puis purge/agrégation ; preuves de consentement conservées tant que la relation commerciale est active + délai de prescription interne (à définir avec votre DPO). Implémentez une tâche planifiée qui supprime ps_sms_inbound.raw_payload avant suppression totale, pour réduire la surface de risque. Sur la partie BDD, prévoyez des index et des purges (sinon vous recréez les mêmes problèmes que les tables de logs), à relier à votre routine globale de maintenance (voir aussi : Base de données PrestaShop : routine de maintenance et nettoyage automatisé).
Un tableau de conservation (à adapter à votre contexte) aide à aligner tech, support et DPO :
| Donnée | Utilité | Durée indicative | Action automatisée |
|---|---|---|---|
Inbound SMS (body) |
preuve STOP + support | 90 jours | purge |
Payload brut (raw_payload) |
debug webhook | 7–30 jours | purge partielle rapide |
| Statuts d’envoi (DLR) | preuve d’acheminement | 90 jours | purge |
Consentement (ps_sms_consent) |
preuve opt-in/opt-out | relation active + politique interne | conservation + historisation minimale |
| Logs applicatifs | sécurité / audit | selon politique SI | redaction PII + rotation |
Côté sécurité, traitez votre module SMS comme une brique d’intégration externe : secret API en variables d’environnement, rotation, limitation IP si possible, WAF sur l’endpoint webhook, et journalisation exploitable (sans fuite de PII). L’article 32 du RGPD impose des mesures “appropriées” ; concrètement, votre endpoint webhook doit refuser toute requête non signée, et votre backoffice doit contrôler finement les permissions (qui peut exporter les numéros ?). Pour une approche plus large (API backoffice, WAF, SIEM), recoupez avec : Sécurité PrestaShop : protéger API backoffice, WAF et journalisation SIEM et Audit RGPD PrestaShop : 88 points de contrôle pour boutiques.
Enfin, contractualisez correctement la sous-traitance : votre provider SMS est un sous-traitant au sens RGPD. Exigez un DPA (accord de traitement), clarifiez les transferts hors UE, la rétention chez le provider et les mécanismes de sécurité. Si votre webhook stocke tout “en clair” et que le provider conserve aussi 12 mois de logs, vous doublez le risque sans gain. Documentez ces points dans votre registre de traitements et, si l’analyse de risque le justifie (volume, sensibilité, automatisation), déclenchez une AIPD/DPIA.
Pratique : dans le DPA, vérifiez explicitement (1) où sont traitées les données (région), (2) la durée de conservation des logs chez le prestataire, (3) les conditions de restitution/suppression à la fin du contrat, (4) la gestion des sous-traitants ultérieurs. Ce sont des points qui impactent directement votre propre politique de rétention et vos réponses en cas d’exercice de droits.
Qualité produit et exploitation : tests, observabilité, et conformité qui tient en prod
Une conformité SMS qui marche en prod, c’est d’abord des tests. Automatisez des tests unitaires sur la normalisation E.164 (libphonenumber), sur la détection STOP (cas, accents, phrases), et sur l’upsert de consentement multi-boutiques. En préprod, simulez les webhooks du provider avec des payloads réels (DLR, inbound, erreurs) et forcez des scénarios “sales” (numéros invalides, encodage UCS-2, messages tronqués). Un bug classique : un STOP reçu en UCS-2 non décodé, non détecté, et donc non appliqué.
Ajoutez aussi quelques tests “métier” (très rentables) :
- Non-régression “finalité” : un template service ne doit jamais inclure un bloc promo (même par erreur de merge).
- Vérification mention STOP : tout SMS taggé
marketingdoit contenir la mention de désinscription (via un test sur le rendu final). - Couverture multi-boutique : un STOP reçu sur une boutique doit mettre à jour exactement le périmètre défini (ex. une boutique vs tout le groupe), et vous devez être capable de l’expliquer.
Ensuite, mettez de l’observabilité. Vous devez pouvoir répondre à : combien de SMS marketing envoyés alors que le client est opt-out ? combien de STOP traités en > 1 minute ? quel taux d’erreur 4xx/5xx sur les webhooks ? Sans métriques, vous “pensez” être conforme. Exposez des compteurs (Prometheus) et des traces (OpenTelemetry) autour des envois, des callbacks et des mises à jour BDD. Si votre boutique a déjà une stack de monitoring, alignez les logs SMS sur les mêmes règles de redaction PII.
Un set minimal de KPI (exploitables par support + tech) :
- STOP processing delay (p95) : temps entre réception inbound et opt-out effectif.
- Opt-out violations : envois marketing bloqués après vérification opt-out (devrait être ≈0).
- Inbound parsing errors : messages non décodés / payload rejeté.
- Webhook auth failures : requêtes non signées (signal d’attaque ou de mauvaise conf).
Enfin, ne négligez pas les impacts performance : l’envoi synchrone depuis un hook de commande est une mauvaise idée si l’API SMS ralentit. Mettez en queue (RabbitMQ/Redis/DB) et traitez en worker, sinon vous dégradez le checkout et vous introduisez des timeouts PHP-FPM. Sur ce sujet, les mêmes logiques que l’optimisation backend s’appliquent (TTFB, I/O, latence vers des APIs externes) — voir : TTFB PrestaShop : réduire le Time To First Byte sous 200 ms. Un SMS conforme mais qui casse le tunnel de commande reste un échec d’ingénierie.
En synthèse opérationnelle : (1) finalité tracée par message, (2) consentement prouvable et versionné, (3) STOP traité en temps réel, (4) sécurité de l’endpoint webhook, (5) rétention maîtrisée, (6) tests + métriques. Si vous n’avez qu’un seul “opt-in” global et aucune preuve exploitable, vous êtes en dette technique ET juridique — et PrestaShop, sans module dédié, ne vous sauvera pas.




