« Marge : 34 % » affiché en toutes lettres sous la référence d’un roulement industriel, sur la fiche produit publique d’un fabricant spécialisé dans les composants mécaniques pour l’agroalimentaire. Le champ n’avait strictement rien à faire sur cette page : il servait uniquement au service commercial interne, pour calculer rapidement une remise possible sans dévoiler la logique de tarification au client final.
Le signalement venait d’un client qui avait consulté le code source de la page par curiosité technique, avant de contacter l’équipe commerciale pour demander pourquoi sa marge de négociation semblait déjà connue d’avance. Voici comment ce diagnostic s’est déroulé, du symptôme jusqu’à la correction.
Symptôme : un champ interne visible dans le code source
Le champ marge_calculee apparaissait dans une balise <meta> personnalisée, générée automatiquement par une fonction censée exposer des informations utiles au référencement. Rien dans l’affichage visuel de la page ne montrait ce champ : seul un examen du code source HTML le révélait, ce qui explique pourquoi le problème était passé inaperçu pendant plusieurs mois.
<meta name="ch-produit-marge_calculee" content="34" />
<meta name="ch-produit-reference_fournisseur" content="RLM-2201-B" />
<meta name="ch-produit-cout_revient" content="128.50" />
Diagnostic : une boucle générique sans liste blanche
La fonction responsable de cette exposition parcourait tous les champs personnalisés du produit, sans distinction entre ce qui était destiné à un usage interne et ce qui pouvait raisonnablement être exposé publiquement. Un développeur précédent avait ajouté cette boucle pour un besoin ponctuel de référencement, sans anticiper que de nouveaux champs internes viendraient s’y ajouter par la suite.
// Code fautif : aucune liste blanche, tout est exposé
add_action( 'wp_head', function () {
if ( ! is_singular( 'produit' ) ) {
return;
}
$champs = get_post_meta( get_the_ID() );
foreach ( $champs as $cle => $valeurs ) {
printf( '<meta name="ch-produit-%s" content="%s" />' . "\n", esc_attr( $cle ), esc_attr( $valeurs[0] ) );
}
} );

Correctif : une liste explicite de champs autorisés
La correction remplace la boucle ouverte par une liste blanche fermée, qui énumère précisément les six champs autorisés à quitter l’administration. Tout nouveau champ interne créé par la suite reste protégé par défaut, puisqu’il faudra l’ajouter explicitement à cette liste pour qu’il devienne visible.
add_action( 'wp_head', function () {
if ( ! is_singular( 'produit' ) ) {
return;
}
$champs_publics = array(
'reference_produit',
'poids_kg',
'materiau',
'norme_conformite',
'delai_fabrication',
'garantie_mois',
);
foreach ( $champs_publics as $cle ) {
$valeur = get_post_meta( get_the_ID(), $cle, true );
if ( '' !== $valeur ) {
printf( '<meta name="ch-produit-%s" content="%s" />' . "\n", esc_attr( $cle ), esc_attr( $valeur ) );
}
}
} );
Prévention : nommer les champs internes sans ambiguïté
Au-delà de la correction immédiate, l’équipe a adopté une convention de nommage qui rend une erreur future plus difficile à commettre silencieusement : tout champ strictement interne commence désormais par le préfixe _interne_, un préfixe qui, combiné à une vérification systématique, exclut automatiquement ces champs de toute boucle générique future.
- Renommage de
marge_calculeeen_interne_marge_calculee, avec migration des données existantes par une commande WP-CLI dédiée. - Ajout d’une vérification systématique
strpos( $cle, '_interne_' ) === 0dans toute fonction générique qui parcourt les champs personnalisés d’un produit. - Revue de toutes les boucles similaires sur le site, un exercice qui a permis de trouver deux autres cas d’exposition moins sensibles mais tout aussi injustifiés.
Vérifier qu’aucune autre fonction ne reproduit l’erreur
Une recherche du terme get_post_meta( $champs ) sans clé précise, dans l’ensemble du thème et des extensions maison, a permis de repérer les autres endroits susceptibles de reproduire le même schéma. C’est une vérification qui mérite d’être répétée après chaque intervention d’un nouveau développeur sur un projet ancien.
Une boucle générique sur des champs personnalisés est pratique à écrire, mais elle expose tout ce qu’on y ajoutera plus tard sans y penser : la liste blanche protège contre l’oubli futur, pas seulement contre l’erreur présente.
En résumé
Ce cas illustre un piège fréquent : une fonction écrite pour un besoin ponctuel et légitime devient, avec le temps et l’ajout de nouveaux champs, une source d’exposition qui n’a jamais été revue. Ce diagnostic ne traite volontairement pas le calcul de marge lui-même, question purement commerciale, mais uniquement la façon dont cette information avait fini par fuiter d’un usage interne vers l’affichage public.