Architecture
websource-cartrecovery.php fichier principal : constantes, chargeur PSR-4, compatibilité HPOS, amorçage
src/Plugin.php amorçage (inerte sans WooCommerce), planification, routes REST
src/Settings.php réglages (option wsx_cartrecovery_settings), secret de signature
src/Store.php tables, requêtes, statistiques
src/Tracker.php suivi des paniers, capture de l'adresse, attribution des commandes
src/Runner.php passage planifié : éligibilité, envoi, idempotence
src/Scheduler.php logique de séquence (pure)
src/Eligibility.php règles d'éligibilité (pures)
src/MessageBuilder.php construction d'une relance
src/Mail/ MailRenderer (5 gabarits), Palette, DefaultTexts, Mailer
src/Voucher.php code promo automatique
src/TokenSigner.php jetons HMAC-SHA256
src/Front.php, Restorer.php liens publics, restauration du panier
src/RestorePlanner.php plan de restauration (pur)
src/Privacy.php export et effacement RGPD
src/Admin.php, Cli.php administration, WP-CLI
src/Block.php bloc et code court
Espace de noms : Websource\CartRecovery. Préfixes : options wsx_cartrecovery_*, tables wsx_cartrecovery_*, classes CSS wscr-*.
Les commandes sont lues et écrites uniquement par l'API de WooCommerce (wc_get_order, wc_get_orders, métadonnées d'objet) : stockage HPOS et stockage historique sont pris en charge.
Bloc et code court
| Élément | Nom | Attributs |
|---|---|---|
| Bloc « Rappel de panier (Websource) » | websource/cart-reminder | title (texte, défaut « Garder mon panier »), button (texte, défaut « Recevoir mon panier ») |
| Code court | [websource_cart_reminder title="…" button="…"] | mêmes attributs |
Rendu serveur : formulaire form.wscr-form (adresse e-mail, case de consentement, bouton). Rien n'est affiché pour un client connecté, ni quand l'extension ou la capture d'adresse est désactivée.
Emplacements automatiques : sur les pages Panier et Commande, assets/front.js détecte le champ e-mail (#billing_email du paiement classique, #email du paiement par blocs) et ajoute la case de consentement input[name="wscr_consent"]. Les fichiers ne sont chargés que sur ces pages, et seulement quand une adresse peut être capturée.
Liens publics
| URL | Jeton | Effet |
|---|---|---|
/?wsx_cr=recover&t=<jeton> | type r : relance l, panier c, expiration | Restaure le panier puis redirige (302) vers le panier ou la commande. |
/?wsx_cr=unsubscribe&t=<jeton> | type u : panier k | Désinscrit l'adresse. &undo=1 annule. |
/?wsx_cr=open&t=<jeton> | type o : relance l | Pixel d'ouverture (GIF 1 × 1), si activé. |
Format du jeton : base64url(JSON) . "." . base64url(HMAC-SHA256). Le JSON ne contient que des identifiants numériques. Limitation de débit par adresse IP : 60 restaurations et 40 désinscriptions par 10 minutes. Réponses en noindex, nofollow, sans cache.
Capture de l'adresse (AJAX WooCommerce) :
POST /?wc-ajax=wsx_cr_capture
nonce=<wsxCartRecovery.nonce>&email=marie@exemple.fr&consent=1&firstname=Marie
→ {"ok":true}
Réponses d'erreur : 403 (jeton de formulaire invalide), 429 (trop de demandes ou capture désactivée), {"ok":false,"error":"consent"} (consentement requis et absent : rien n'est enregistré).
Hooks et filtres
Actions
| Action | Paramètres | Moment |
|---|---|---|
wsx_cartrecovery_run | — | Passage planifié (Action Scheduler, groupe websource-cartrecovery, toutes les 10 minutes). |
wsx_cartrecovery_reminder_sent | array $cart, int $step, string $status, int $logId | Après l'envoi (ou la capture) d'une relance. |
wsx_cartrecovery_restored | array $cart, array $result | Après la restauration d'un panier. |
wsx_cartrecovery_recovered | WC_Order $order, int $cartId, int $logId | Une commande est attribuée à une relance. |
wsx_cartrecovery_unsubscribed | string $email | Après une désinscription. |
Filtres
| Filtre | Paramètres | Rôle |
|---|---|---|
wsx_cartrecovery_skip_reason | ?string $reason, array $cart, Settings $settings | Raison du refus d'une relance (null = éligible). Renvoyez une chaîne pour exclure un panier. |
wsx_cartrecovery_mail_context | array $ctx, array $cart, int $step | Données de l'e-mail (prénom, produits, URL, code promo…). |
wsx_cartrecovery_theme_colors | array $colors | Palette du thème : primary, secondary, accent, ink, line, page_bg, surface. |
wsx_cartrecovery_message_html | string $html, string $title, string $text, string $undoUrl | Page affichée pour un lien invalide, expiré, ou après désinscription. |
Exemple : ne jamais relancer les adresses d'un domaine.
add_filter('wsx_cartrecovery_skip_reason', function ($reason, array $cart) {
return substr($cart['email'], -13) === '@exemple.test' ? 'internal_address' : $reason;
}, 10, 2);
Exemple : prévenir un outil externe quand un panier est récupéré.
add_action('wsx_cartrecovery_recovered', function (WC_Order $order, int $cartId, int $logId) {
error_log(sprintf('Panier %d récupéré : commande %d, %s', $cartId, $order->get_id(), $order->get_total()));
}, 10, 3);
Raisons de refus possibles : no_email, status_<statut>, optout, customer_ordered_since, empty, below_minimum, no_consent, no_optin, not_due, already_claimed.
Routes REST
Espace de noms : websource-cartrecovery/v1.
| Méthode | Chemin | Accès | Rôle |
|---|---|---|---|
| GET, POST | /run | jeton token ou manage_woocommerce | Lance un passage. |
| GET | /stats | manage_woocommerce | Statistiques. |
Paramètres de /run : token (jeton de l'onglet Tâche planifiée et démo), dry_run (booléen : ne fait que compter), limit (0 à 500 e-mails).
GET /wp-json/websource-cartrecovery/v1/run?token=<jeton>&dry_run=1
→ {"sent":0,"captured":0,"failed":0,"skipped":0,"purged":0,"locked":false,"disabled":false,"dry_run":true}
Sans jeton valide : 401.
Paramètre de /stats : days (1 à 365, défaut 30).
GET /wp-json/websource-cartrecovery/v1/stats?days=30
→ {"days":30,"last_run":1791484140,
"totals":{"tracked":10,"active":3,"recovered":1,"sent":6,"failed":0,"opened":0,"clicked":3,"converted":1,
"revenue":[{"currency":"EUR","amount":"146.610000","orders":"1"}],"optouts":0},
"daily":{"2026-10-08":{"sent":6,"recovered":1}}}
WP-CLI
wp websource-cartrecovery run [--dry-run] [--force] [--limit=<nombre>]
--dry-run liste ce qui serait envoyé, --force passe même si l'extension est désactivée, --limit plafonne le nombre d'e-mails.
Variables CSS
| Variable du thème | Repli | Utilisation |
|---|---|---|
--color-brand-600 | #0f766e | Bouton du formulaire, case cochée, contour de focus. |
--color-ink | #14282b | Texte. |
--color-line | #d9e6e4 | Bordures. |
--color-surface | #fff | Fond du formulaire. |
--radius-xl, --radius-2xl | 1rem, 1.5rem | Arrondis. |
--wst-card-shadow | none | Ombre du formulaire. |
Les e-mails n'utilisent pas de variables CSS (styles en ligne) : leurs couleurs viennent de l'onglet Modèles d'e-mail ou de l'option wsx_theme_config de Websource Theme Config.
Fonctions publiques
| Appel | Rôle |
|---|---|
Settings::load(): Settings, ->get(string $key), ->with(array $raw)->save() | Lecture et modification des réglages. |
(new Runner())->run(array $options): array | Lance un passage (dry_run, force, limit, now). |
(new Runner())->sendNow(int $cartId): array | Envoie la prochaine relance d'un panier. |
Tracker::sync(): void | Enregistre le panier de la session en cours. |
Tracker::snapshot(): array | Copie du panier en cours (items, coupons, total). |
MessageBuilder::build(array $cart, int $step, int $logId, Settings $s, ?array $voucher, int $now): array | Construit une relance (subject, html, text). |
Restorer::restore(array $items, array $coupons, string $voucher, bool $autoApply): array | Reconstruit un panier dans la session en cours. |
Scheduler::dueStep(int $lastActivity, int $now, array $sentAt, Settings $s): ?int | Relance due pour un panier. |
Settings::signer(): TokenSigner, ->sign(), ->verify(), ->emailHash() | Jetons et empreinte d'adresse. |
(new Store())->stats(int $since), ->daily(int $days, int $now) | Statistiques. |
Données enregistrées
| Emplacement | Contenu |
|---|---|
Table {prefix}wsx_cartrecovery_carts | Paniers suivis : session, client, adresse, prénom, langue, devise, origine, consentement, contenu (JSON), total, dernière activité, statut, code promo, commande récupérée. |
Table {prefix}wsx_cartrecovery_log | Relances : panier, étape, objet, statut, copie du panier, e-mail capturé, clics, ouverture, commande. Clé unique (panier, étape). |
Table {prefix}wsx_cartrecovery_optout | Désinscriptions : empreinte HMAC de l'adresse (irréversible). |
Option wsx_cartrecovery_settings | Réglages. |
Option wsx_cartrecovery_secret | Secret de signature (jamais affiché). |
Option wsx_cartrecovery_last_run | Date du dernier passage. |
Métadonnée utilisateur wsx_cr_consent | Consentement d'un client connecté. |
Métadonnées de commande _wsx_cr_done, _wsx_cr_recovered | Commande déjà traitée ; panier récupéré. |
Codes promo WSCR-… | Codes créés par l'extension. |
Les dates sont en UTC. La désinstallation supprime les tables, les options, les codes promo WSCR- et la tâche planifiée.
Écarts par rapport au module PrestaShop
- Pas de multiboutique (une installation WordPress = une boutique).
- WooCommerce garde le panier dans la session : l'extension conserve sa propre copie du panier (table
carts) au lieu de relire le panier natif. Le panier restauré est reconstruit dans la session du visiteur. - Textes des relances : une seule version, traduite par Polylang ou WPML ; les textes par défaut suivent la langue du panier. Le module PrestaShop stocke un texte par langue.
- Le « déclenchement opportuniste » n'existe pas comme option : la tâche passe par Action Scheduler (WP-Cron), qui fonctionne déjà sur le trafic.
- « Clients avec compte : optin partenaires » devient « clients qui ont coché la case de consentement » (WooCommerce n'a pas de champ optin).
- Le message de restauration utilise les avis de WooCommerce au lieu d'un toast ; pas de rappel dans le tiroir du panier Websource.
- Les e-mails capturés sont gardés dans la table des relances, pas dans des fichiers.
- L'aperçu des modèles utilise les réglages enregistrés (pas d'aperçu avant enregistrement).
- Bloc et code court « Rappel de panier » ajoutés.