Accueil

Référence développeur · WordPress

Websource Newsletter pour WordPress — référence développeur

Bloc, code court, fonctions PHP, filtres, actions, routes REST, tables, format d'export et variables CSS de l'extension Websource Newsletter.

Version 1.1.0 · WordPress 6.4+, WooCommerce 8+ (facultatif), PHP 7.4 à 8.5 · Mis à jour le 09/10/2026

Guide utilisateur

Cette extension existe aussi pour : PrestaShop

Vue d'ensemble

  • Espace de noms Websource\Newsletter, classes dans src/ (chargeur PSR-4 maison, pas de Composer).
  • Capacité requise pour l'administration et les routes REST protégées : manage_options (filtre websource_newsletter_capability).
  • Fonctionne sans WooCommerce ; seul le code promo de bienvenue en dépend (VoucherService::available()).
  • CSS (wsx-newsletter) et JavaScript (wsx-newsletter, différé, sans jQuery) chargés seulement quand un formulaire est rendu.
ClasseRôle
PluginAmorçage, conteneur de services, rendu du formulaire, code court, bloc, section de paquet de thème.
SettingsOption unique, assainissement, textes par défaut, version du consentement, clé secrète.
Schema, RepositoryTables, requêtes préparées, statistiques, limitation de débit.
SubscriptionServiceInscription, confirmation, désinscription, effacement, renvoi, import, synchronisation avec le compte.
MailService, VoucherServiceE-mails (wp_mail, HTML + texte), code promo WooCommerce.
PrivacyExportateur, effaceur et texte de politique pour les outils de confidentialité de WordPress.
Front\Endpoints, Front\Placements, Front\AccountSyncRoutes REST et pages publiques, emplacements automatiques, case des comptes.
Admin\AdminPage, Admin\SubscribersTableÉcran Newsletter (abonnés, réglages, import / export).
Domain\*AntiSpam, TokenService, EmailValidator, ConsentRecord, CsvReader, CsvWriter, Status (sans dépendance à WordPress).

Données

ÉlémentContenu
Table {prefix}wsx_newsletter_subscribersid, user_id, email (unique), status (pending, confirmed, unsubscribed), source, locale, token_hash (SHA-256 du jeton de confirmation), token_expires, date_mail, consent_date, consent_text, consent_version, consent_locale, voucher_code, date_add, date_upd, date_confirm, date_unsub. Dates en UTC.
Table {prefix}wsx_newsletter_throttleip_hash (HMAC-SHA-256 de l'adresse IP avec la clé secrète), date_add. Purgée après 24 h par l'évènement quotidien wsx_newsletter_daily.
Option wsx_newsletter_settingsTous les réglages (voir « Réglages »). Chargée automatiquement.
Option wsx_newsletter_consent_versionVersion courante du texte de consentement (entier ≥ 1).
Option wsx_newsletter_secretClé secrète (64 caractères hexadécimaux) : signature du tampon anti-spam, jeton de désinscription, empreinte IP.
Option wsx_newsletter_db_versionVersion du schéma.
Méta utilisateur wsx_newsletter_optin1 ou 0, miroir de l'abonnement du compte.
Cookie wsnl_popupPosé par le script quand la fenêtre a été ouverte ou après une inscription réussie.

Aucune adresse IP n'est enregistrée en clair. Le jeton de confirmation n'est conservé que sous forme d'empreinte et est effacé à la confirmation.

Réglages

CléTypeDéfautLimites
double_optinbooléentrue
token_hoursentier481 à 720
min_delayentier30 à 60 secondes
rate_maxentier51 à 100 par heure
placementsliste["before_footer"]before_footer, footer, home
custom_hookchaîne""nom d'action : ^[a-zA-Z_][a-zA-Z0-9_./-]{2,63}$
signup_fieldbooléentrue
voucher_enabledbooléenfalse
voucher_typechaînepercentpercent, amount
voucher_valuedécimal0100 au plus en pourcentage
voucher_daysentier301 à 365
voucher_mindécimal0
popup_enabledbooléenfalse
popup_modechaînedelaydelay, exit
popup_delayentier103 à 300 secondes
popup_daysentier71 à 365
title, intro, popup_title, popup_introchaîne""250 caractères, sans balise
consentchaîne""1 000 caractères, sans balise
policy_urlchaîneprivacyprivacy, post:ID, /chemin, http(s)://…
keep_databooléentrue

Un texte vide prend la valeur par défaut traduite. {shop} est remplacé par le nom du site.

Bloc Gutenberg websource/newsletter

Rendu serveur (block.json, apiVersion 3, éditeur sans build). Catégorie Widgets. Alignements large et pleine largeur.

AttributTypeDéfautRôle
layoutchaînecardcard (carte) ou inline (bandeau sur une ligne).
showIntrobooléentrueAffiche le texte d'introduction.
alignchaînewide ou full.
classNamechaîneClasses CSS supplémentaires.
<!-- wp:websource/newsletter {"layout":"inline","showIntro":false} /-->

Code court [websource_newsletter]

AttributDéfautRôle
layoutcardcard ou inline.
intro10, no, false ou off masque l'introduction.
classClasses CSS supplémentaires.
[websource_newsletter layout="inline" intro="0"]

Fonctions publiques

// Renvoie le HTML du formulaire. Options : layout (card|inline), intro (bool), class, source.
echo websource_newsletter_form(['layout' => 'inline']);

// Inscrit une adresse pour un visiteur qui a donné un consentement explicite (formulaire maison).
// Renvoie 'accepted', 'invalid' ou 'consent'. La double confirmation s'applique si elle est activée.
$result = websource_newsletter_subscribe('prenom.nom@example.test', true, 'api');

websource_newsletter_subscribe() enregistre le texte de consentement courant du site : ne l'appelez que si ce texte a réellement été présenté et accepté.

Emplacements automatiques

EmplacementThème à blocsThème classique
before_footer (bandeau)Avant la partie de modèle du pied de page (render_block sur core/template-part).Action get_footer.
footer (carte)Avant </footer> de la partie de modèle.Action wp_footer (priorité 1), donc après le pied de page du thème.
home (carte)Avant </main> sur la page d'accueil.Action loop_end de la requête principale, sur la page d'accueil.
Action libreAction nommée dans custom_hook.Idem.
Fenêtrewp_footer (priorité 20), hors panier et commande.Idem.

Un thème peut placer lui-même le formulaire en déclenchant do_action('websource_before_footer') ou do_action('websource_footer'). Chaque emplacement n'est rendu qu'une fois par page.

Gabarits surchargeables

Copiez un gabarit de templates/ dans <thème>/websource-newsletter/ : form.php, fields.php, popup.php, result.php. Les variables sont dans $wsnl (ou $wsnl_result pour result.php).

Pages publiques

AdresseRôle
POST /?wsx_newsletter=subscribeInscription sans JavaScript. Champs : wsx_email, wsx_consent, wsx_stamp, wsx_source, website (champ piège). Affiche une page de résultat.
GET /?wsx_newsletter=confirm&id=<id>&token=<jeton>Confirme l'inscription. Réponses : confirmée, déjà confirmée, lien expiré, lien non valide.
GET /?wsx_newsletter=unsubscribe&id=<id>&token=<jeton>Affiche la page avec le bouton Me désinscrire (ne désinscrit pas).
POST sur la même adresse avec wsx_unsubscribe=1 ou List-Unsubscribe=One-ClickDésinscrit (RFC 8058).

Ces pages envoient X-Robots-Tag: noindex, nofollow, Referrer-Policy: no-referrer et les en-têtes anti-cache.

Routes REST

Espace de noms websource-newsletter/v1.

POST /subscribe

Publique par conception (formulaire ouvert à tous les visiteurs), protégée par le champ piège, le tampon signé, le délai minimal et la limitation de débit.

ParamètreTypeRôle
emailchaîneAdresse à inscrire.
consentbooléenCase cochée.
stampchaîneValeur du champ caché wsx_stamp du formulaire.
websitechaîneChamp piège, doit rester vide.
sourcechaînesite, popup, home, footer, before_footer, block, shortcode, hook, widget.
curl -X POST https://example.test/wp-json/websource-newsletter/v1/subscribe \
  -H 'Content-Type: application/json' \
  -d '{"email":"prenom.nom@example.test","consent":true,"stamp":"1791572911.fc19…","website":"","source":"site"}'
{"success":true,"message":"Merci ! Un e-mail vient de vous être envoyé : cliquez sur le lien pour confirmer votre inscription.","field":""}

La réponse est toujours en HTTP 200 avec Cache-Control: no-store. En cas d'erreur, success vaut false et field vaut email, consent ou une chaîne vide. La réponse est identique que l'adresse soit déjà connue ou non.

GET /stats

Capacité requise. Sans authentification : 401.

{"status":{"pending":2,"confirmed":3,"unsubscribed":1},"vouchers":0,"total":6}

GET /subscribers

Capacité requise.

ParamètreTypeDéfautRôle
statuschaîne""pending, confirmed, unsubscribed ou vide.
searchchaîne""Partie d'adresse.
pageentier1
per_pageentier251 à 100.
curl -H 'X-WP-Nonce: <nonce>' --cookie '<cookies de session>' \
  'https://example.test/wp-json/websource-newsletter/v1/subscribers?status=confirmed&per_page=1'
[{"id":7,"user_id":0,"email":"prenom.nom@example.test","status":"confirmed","source":"before_footer","locale":"fr_FR","date_mail":"2026-10-09 19:19:41","consent_date":"2026-10-09 19:19:41","consent_text":"J’accepte de recevoir la newsletter de …","consent_version":1,"consent_locale":"fr_FR","voucher_code":null,"date_add":"2026-10-09 19:19:41","date_upd":"2026-10-09 19:19:41","date_confirm":"2026-10-09 19:19:41","date_unsub":null}]

En-têtes X-WP-Total et X-WP-TotalPages. token_hash et token_expires ne sont jamais renvoyés.

DELETE /subscribers/<id>

Capacité requise. Efface l'abonné et sa preuve de consentement.

{"deleted":true}

Abonné inconnu : 404, code wsx_newsletter_not_found.

Filtres

FiltreParamètresRôle
websource_newsletter_capability$capabilityCapacité exigée (défaut manage_options).
websource_newsletter_form_view$view, $optionsDonnées transmises au gabarit du formulaire.
websource_newsletter_template$file, $nameFichier de gabarit utilisé (form, fields, popup, result).
websource_newsletter_show_placements$showfalse masque les emplacements automatiques et la fenêtre sur la page courante.
websource_newsletter_spam_verdict$verdict, $emailVerdict anti-spam (ok, honeypot, too_fast, bad_stamp, rate_limited) : point d'accroche pour un captcha.
websource_newsletter_client_ip$ipAdresse du visiteur pour la limitation de débit (derrière un proxy, renvoyer l'adresse transmise).
websource_newsletter_mail$mail, $type, $subscriberE-mail avant envoi : subject, html, text, headers ; $type vaut confirm ou welcome.
websource_newsletter_voucher_prefix$prefix, $subscriberPréfixe du code promo (défaut WELCOME, 12 caractères au plus).
websource_theme_export$sectionsAjoute la section newsletter à un paquet de thème.
// Derrière Cloudflare : limiter le débit sur l'adresse réelle du visiteur.
add_filter('websource_newsletter_client_ip', static function ($ip) {
    return isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_CF_CONNECTING_IP'])) : $ip;
});

Actions

ActionParamètresMoment
websource_newsletter_subscribed$rowDemande d'inscription enregistrée (pas encore confirmée si la double confirmation est active).
websource_newsletter_confirmed$row, $voucherInscription confirmée ; $voucher vaut null ou ['code', 'text', 'until'].
websource_newsletter_unsubscribed$rowDésinscription (ligne avant modification).
websource_newsletter_erased$emailAbonné effacé.
websource_newsletter_before_voucher_save$coupon, $subscriberDernier ajustement du WC_Coupon avant enregistrement.
websource_theme_import$sectionsApplique la section newsletter d'un paquet de thème.
websource_before_footer, websource_footerÀ déclencher par un thème pour accueillir le formulaire.
// Envoyer chaque abonné confirmé à un outil d'envoi.
add_action('websource_newsletter_confirmed', static function (array $row): void {
    mon_outil_ajouter_contact($row['email'], $row['locale']);
});

Outils de confidentialité

  • Exportateur websource-newsletter (wp_privacy_personal_data_exporters) : groupe « Abonnement à la newsletter » avec l'adresse, le statut, l'origine, la langue, la date, le texte et la version du consentement, les dates d'inscription, de confirmation et de désinscription, le code promo.
  • Effaceur websource-newsletter (wp_privacy_personal_data_erasers) : supprime la ligne de l'abonné, remet la méta du compte à 0, supprime le code promo de bienvenue non utilisé (ou retire la restriction d'adresse d'un code déjà utilisé).
  • Texte proposé dans Réglages > Confidentialité > Guide de politique.

Export CSV et JSON

CSV (séparateur ;, UTF-8 avec BOM, cellules commençant par =, +, -, @ neutralisées) :

email;status;source;lang;consent_date;consent_version;consent_text;date_add;date_confirm;date_unsub;voucher_code

JSON des réglages d'affichage (section newsletter, version 1). Une page est désignée par @type:slug, jamais par identifiant.

{
  "plugin": "websource-newsletter",
  "section": "newsletter",
  "version": 1,
  "data": {
    "placements": ["before_footer"],
    "custom_hook": "",
    "signup_field": true,
    "popup_enabled": false,
    "popup_mode": "delay",
    "popup_delay": 10,
    "popup_days": 7,
    "title": "",
    "intro": "",
    "consent": "",
    "policy_url": "privacy",
    "popup_title": "",
    "popup_intro": ""
  }
}

Jamais exportés ni importés : abonnés, clé secrète, version du consentement, code promo, anti-spam. Un texte de consentement différent à l'import augmente la version.

Variables CSS

Le formulaire lit les variables du thème avec une valeur de repli. Surchargez les variables --wsnl-* sur .wsnl.

VariableLue depuisRepli
--wsnl-bg--wst-surface, --color-surface#fff
--wsnl-ink--wst-ink, --color-ink#14282b
--wsnl-line--wst-line, --color-line#d9e6e4
--wsnl-accent--wst-brand-fill, --color-brand-fill, --color-brand-600#0f766e
--wsnl-accent-ink--wst-brand-on, --color-brand-on#fff
--wsnl-link--wst-brand-text, --color-brand-text#0b5f58
--wsnl-radius--wst-radius-2xl, --radius-2xl1.5rem
--wsnl-field-radius--wst-radius-xl, --radius-xl1rem
--wsnl-shadow--wst-card-shadownone

Classes : .wsnl, .wsnl--card, .wsnl--inline, .wsnl--placed, .wsnl--at-before-footer, .wsnl--at-footer, .wsnl--at-home, .wsnl--at-custom, .wsnl--popup, .wsnl-popup (<dialog>). Le bandeau passe en deux colonnes quand le formulaire lui-même dépasse 52 rem (requête de conteneur).

Polylang et WPML

Les textes saisis (title, intro, consent, popup_title, popup_intro) sont déclarés par pll_register_string (groupe « Websource Newsletter ») et wpml-config.xml. L'e-mail est envoyé dans la langue enregistrée avec l'abonné quand elle est installée sur le site.

Désinstallation

uninstall.php supprime l'évènement planifié. Si keep_data est décoché, il supprime aussi les deux tables, les quatre options et les métas utilisateur wsx_newsletter_optin et wsx_newsletter_per_page.