WordPress – Champs personnalisés : aller plus loin que les contenus classiques
Quand on installe WordPress, on découvre rapidement ses bases : le titre, le contenu principal, l’extrait, parfois une image mise en avant. Ce modèle convient à beaucoup de situations simples. Mais dès qu’on veut aller un peu plus loin, ça coince. Où mettre une date précise, un code interne, une note invisible, une couleur personnalisée ? Dans le texte ? Dans le titre ? Dans un champ de catégorie détourné ?
La tentation est forte de bricoler avec ce qu’on a. Pourtant, WordPress propose depuis ses débuts un outil puissant mais discret : les champs personnalisés (ou custom fields). Ils n’apparaissent pas toujours à l’écran, mais ils sont là, prêts à être utilisés.
Ces champs permettent d’associer à chaque article une ou plusieurs données structurées, invisibles pour le lecteur mais exploitées facilement en PHP, en JavaScript, ou même dans des requêtes Ajax. On peut les afficher, les styliser, les conditionner ou les transmettre à un module. C’est la base de toute une logique de contenus enrichis. Et que l’on parte sur un petit site vitrine ou un projet complexe, comprendre et utiliser les champs personnalisés permet de ne pas tordre WordPress pour faire ce qu’il n’est pas censé faire.
Pourquoi ne pas tout mettre dans l’article ?
Lorsqu’on gère un site, on a vite besoin d’ajouter des informations pratiques : une date d’événement, un lieu, un tarif, un statut interne… La solution la plus immédiate consiste à les insérer directement dans le texte. Cela fonctionne. Au début.
Mais cette méthode a des limites. Si l’on veut ensuite trier des articles par tarif, afficher uniquement ceux situés dans une région, ou simplement mettre à jour une information sans toucher au contenu, tout devient compliqué.
En stockant ces données dans le corps de l’article, on les noie dans le texte libre. On ne peut pas les interroger facilement en base, ni les réutiliser dans une API, ni les styliser sans parsing complexe.
En revanche, si chaque information est placée dans un champ identifié, elle devient exploitable. Elle peut être affichée à part, formatée automatiquement, recherchée, filtrée, triée. On passe d’un contenu “figé” à un système de données dynamiques. Et c’est là que WordPress commence à se comporter comme un outil modulaire, souple, évolutif.
Où les trouve-t-on, et comment les activer ?
Sur une installation WordPress fraîche, les champs personnalisés n’apparaissent pas par défaut dans l’interface de l’éditeur. Ce n’est pas qu’ils ont disparu : ils sont simplement masqués. Dans l’éditeur classique, il suffit de cliquer sur Options de l’écran (en haut à droite de la page), puis de cocher la case “Champs personnalisés”. Dans l’éditeur Gutenberg, il faut ouvrir le menu à trois points, choisir Préférences > Panneaux, et activer le module correspondant.

Une fois visibles, les champs apparaissent sous l’éditeur. On peut y ajouter un champ par son nom, puis lui attribuer une valeur librement. Cela peut être un texte, un chiffre, une URL, une couleur…

Ces données ne s’affichent nulle part sur le site, à moins qu’on ne les appelle manuellement dans le thème ou une extension. C’est ce qui fait leur force : elles sont là, discrètes, mais prêtes à être utilisées de façon ciblée.
C’est aussi une bonne raison de soigner leur nommage dès le départ. On évite les noms vagues comme info
ou valeur
, au profit de date_evenement
, tarif_public
, pem_main_color
… Cela facilite la lecture, la maintenance, et l’évolutivité du code.
Un conseil utile : préfixer les noms de vos champs, par exemple avec pem_
dans le cas des projets Puce & Média. Cela permet d’éviter toute collision avec des noms déjà utilisés en interne par WordPress, par des plugins tiers ou des outils de mise en page. Un champ titre
peut entrer en conflit ; un champ pem_titre_secondaire
ne le fera jamais.
Exploiter un champ dans un thème
Une fois un champ personnalisé saisi dans l’interface, encore faut-il le faire apparaître à l’écran. Par défaut, WordPress n’affiche rien de ce qui est stocké dans ces champs, à moins qu’on le lui demande explicitement dans le thème.
La fonction de base est simple :
$valeur = get_post_meta(get_the_ID(), 'nom_du_champ', true);
On lui passe l’ID de l’article (souvent get_the_ID()
quand on est dans la boucle), le nom exact du champ, et un troisième paramètre fixé à true
pour récupérer une seule valeur (et non un tableau).
Par exemple, si on a créé un champ nommé pem_lieu_evenement
, on peut l’afficher ainsi :
echo get_post_meta(get_the_ID(), 'pem_lieu_evenement', true);
Cela peut se faire n’importe où dans le thème : dans une boucle d’article, dans une sidebar, dans une fiche projet… Ce champ devient alors une donnée dynamique que l’on peut styliser, filtrer, comparer, transformer.
En l’utilisant avec des conditions, on peut aussi choisir d’afficher un élément seulement si le champ existe, ou changer l’apparence d’un bloc selon sa valeur. On entre dans une logique modulaire, où chaque champ ajoute une brique à la construction de la page.
Générer du style à partir d’un champ personnalisé
Les champs personnalisés ne servent pas qu’à afficher des données textuelles. Ils peuvent aussi piloter le style d’un article, sa couleur dominante, ses mises en forme, ou son comportement graphique. C’est particulièrement utile quand on veut conserver un thème unique, tout en donnant à chaque contenu une identité visuelle propre.
Prenons un exemple concret. Supposons que nous ayons un champ appelé pem_main_color
, qui contient une couleur hexadécimale comme #ff214f
. Plutôt que de la réinjecter à chaque fois dans le HTML, on peut générer automatiquement une variable CSS réutilisable via :root
.
Voici une fonction à ajouter dans le fichier functions.php
de votre thème ou thème enfant :
function pem_style_inline_color() {
if (!is_singular()) return;
$color = get_post_meta(get_the_ID(), 'pem_main_color', true);
if (!$color) return;
echo '<style>:root { --pem-color: ' . esc_attr($color) . '; }</style>';
}
add_action('wp_head', 'pem_style_inline_color');
Elle injecte une ligne CSS dans le <head>
de la page, comme ceci :
:root { --pem-color: #ff214f; }
Il suffit alors, dans le fichier CSS du thème enfant, d’utiliser cette variable :
.pem-title h2, .pem-title h3 {
color: var(--pem-color);
}
.pem-page-content a:hover {
background-color: var(--pem-color);
color: #fff;
}
Ce principe permet d’éviter de dupliquer des styles pour chaque projet, tout en conservant un design cohérent et personnalisable. Et comme la valeur est extraite d’un champ, elle peut être modifiée sans jamais toucher au code.
Afficher un bloc conditionnel selon une valeur
WordPress permet d’intégrer automatiquement certains contenus externes à partir d’une simple URL, grâce au mécanisme de contenus intégrés oEmbed. Cela concerne notamment les vidéos YouTube, Vimeo, Dailymotion, mais aussi les tweets, cartes, playlists, etc.
La fonction clé de cette intégration est wp_oembed_get()
. Elle tente de transformer une URL en code HTML embarqué, par exemple un lecteur vidéo ou une iframe, si le domaine est reconnu et pris en charge par WordPress.
Dans un cas typique, on souhaite afficher une vidéo dans un article uniquement si une URL est fournie dans un champ personnalisé pem_video_url
. Voici comment procéder proprement, dans un modèle comme single.php
, à l’intérieur d’un <article>
.
<article class="pem-article">
<header class="pem-header">
<h1><?php the_title(); ?></h1>
</header>
<?php
// Récupération du champ personnalisé
$video_url = get_post_meta(get_the_ID(), 'pem_video_url', true);
// Si l'URL est présente, on tente de générer un lecteur intégré
if (!empty($video_url)) {
$embed = wp_oembed_get($video_url);
echo '<section class="pem-section pem-video">';
echo '<h2>Vidéo de présentation</h2>';
// Si l'intégration oEmbed fonctionne, on l'affiche
if ($embed) {
echo $embed;
}
// Sinon, on affiche un lien de repli cliquable
else {
echo '<p><a href="' . esc_url($video_url) . '" target="_blank">Voir la vidéo</a></p>';
}
echo '</section>';
}
?>
<section class="pem-content">
<?php the_content(); ?>
</section>
</article>
Ce bloc est parfaitement intégré dans la structure HTML du thème, et garde l’affichage propre :
- aucun HTML injecté au mauvais endroit,
- aucune vidéo vide,
- un lien de secours si oEmbed échoue.
Ce principe peut être réutilisé pour afficher une citation audio, une carte interactive, un post Instagram ou même une playlist Spotify. Il suffit que l’URL soit prise en charge par le système oEmbed de WordPress.
Et si nous n’avons pas accès au Template, fût il un Child Template ?
Parfois, le template ne prévoit pas de zone explicite pour accueillir ce contenu. Plutôt que de dupliquer ou surcharger le thème, on peut s’appuyer sur un repère HTML stable (une classe comme .pem-content
) pour insérer dynamiquement la vidéo dans le DOM.
Voici une approche alternative, injectée depuis wp_footer
, qui ajoute la vidéo juste avant le contenu principal :
function pem_inject_video_if_needed() {
if (!is_singular()) return;
$video_url = get_post_meta(get_the_ID(), 'pem_video_url', true);
$embed = wp_oembed_get($video_url);
if ($embed) {
echo '<script>
document.addEventListener("DOMContentLoaded", function() {
var target = document.querySelector(".pem-content");
if (target) {
var video = document.createElement("div");
video.className = "pem-video";
video.innerHTML = ' . json_encode($embed) . ';
target.parentNode.insertBefore(video, target);
}
});
</script>';
}
}
add_action("wp_footer", "pem_inject_video_if_needed");
Cette méthode a plusieurs avantages :
- aucune modification du thème n’est nécessaire,
- il suffit de s’assurer que la classe repère
.pem-content
soit bien présente dans le post, - l’intégration est donc proprement encadrée dans une structure HTML existante,
- le script s’exécute uniquement si le champ personnalisé
pem_video_url
est présent, et si l’embed est valide.
On peut l’adapter pour d’autres contenus conditionnels : citation, galerie, iframe, PDF, encart d’alerte… Il suffit que le thème contienne un point d’ancrage identifiable, et que le contenu reste bien formé.
Vers une logique modulaire plus avancée
Une fois qu’on a pris l’habitude d’utiliser les champs personnalisés, il devient naturel d’aller plus loin. Ce ne sont plus de simples compléments au contenu : ce sont des briques de logique qui peuvent structurer l’ensemble d’un site.
On peut par exemple créer des types de contenu personnalisés (ou custom post types) : pour gérer des projets, des événements, des communes, des membres d’équipe… Chacun avec ses propres champs spécifiques, et une interface de saisie adaptée.
On peut aussi relier ces champs à des fonctions JavaScript, à des appels AJAX, ou à des gabarits conditionnels. Une valeur numérique peut piloter un graphique, une variable CSS, une carte interactive, ou même des filtres de recherche.
Certaines extensions, comme Advanced Custom Fields (ACF) ou Pods, permettent de créer ces structures sans écrire une ligne de code. Mais le cœur du système reste le même : une donnée, bien nommée, bien stockée, bien exploitée.
Ce n’est pas réservé aux développeurs aguerris. C’est un moyen de modulariser un projet progressivement, sans surcharger WordPress, et sans casser la logique de contenu. Et cela peut se faire à notre rythme, champ par champ, besoin par besoin.
Charger dynamiquement des ouvrages depuis un champ personnalisé
Un champ personnalisé peut aussi servir à alimenter une requête AJAX pour enrichir un article. Sur le site Puce & Média, nous l’utilisons notamment pour proposer, en bas de certains articles, une liste d’ouvrages associés à la thématique traitée.
Prenons un exemple concret : dans un champ pem_mots_cles_ouvrages
, on saisit des mots-clés comme
accessibilité, handicap, numérique
Ce champ ne s’affiche pas en tant que tel. Mais il sert à déclencher une requête côté JavaScript, qui interroge un script PHP via admin-ajax.php
. Ce script interroge ensuite une base de données d’ouvrages, et renvoie une liste au format JSON.
Un conteneur dans le pied de page (ou ailleurs dans le modèle) est prévu pour recevoir les résultats :
document.addEventListener("DOMContentLoaded", function () {
let motsCles = document.querySelector('[data-pem-mots-cles]');
if (!motsCles) return;
fetch('/wp-admin/admin-ajax.php?action=pem_get_ouvrages&mots=' + encodeURIComponent(motsCles.dataset.pemMotsCles))
.then(response => response.json())
.then(liste => {
let container = document.querySelector("#pem-ouvrages");
if (!container) return;
liste.forEach(item => {
let bloc = document.createElement("div");
bloc.className = "ouvrage";
bloc.innerHTML = `
<h3>${item.titre}</h3>
<p><em>${item.auteur}</em></p>
<img src="${item.couverture}" alt="">
<p>${item.description}</p>
<p><a href="${item.lien}" target="_blank">Voir l’ouvrage</a></p>
`;
container.appendChild(bloc);
});
});
});
Et côté PHP, on associe ce traitement à une action wp_ajax_pem_get_ouvrages
, avec une fonction qui va interroger la base (MySQL ou autre) et renvoyer un tableau JSON.
<section class="aller-plus-loin">
<h2>Aller plus loin</h2>
<!-- repeat: .ouvrage -->
<div class="ouvrage accessibilite" id="<!-- id de l’ouvrage -->">
<img src="<!-- chemin de l’image de couverture -->" alt="<!-- texte alternatif -->">
<h3><!-- titre de l’ouvrage --></h3>
<h4><!-- nom de l’auteur --></h4>
<p><!-- description ou résumé de l’ouvrage --></p>
<ul>
<li><a href="<!-- lien vers l’éditeur ou la fiche principale -->" target="_blank"><!-- nom de l’éditeur --><span class="hu-external"></span></a></li>
<li><a href="<!-- lien vers un partenaire, un revendeur ou une source alternative -->" target="_blank">Partenaire<span class="hu-external"></span></a></li>
</ul>
</div>
<!-- /repeat -->
</section>
Ce système permet de charger des ressources complémentaires en fonction de ce que contient l’article, sans alourdir la page initiale. Il est possible de mettre à jour cette base indépendamment, d’y ajouter des métadonnées, des liens vers des catalogues, ou même des QR codes.
Et tout cela repose sur un simple champ textuel bien utilisé, qui agit comme déclencheur d’un enrichissement dynamique du contenu.
On peut voir cette mécanique en action à la fin de l’article “Qu’entend-on par accessibilité ?” . Le champ pem_mots_cles_ouvrages
est invisible pour le lecteur, mais il permet d’adapter le contenu complémentaire à chaque article, de façon automatisée et évolutive.
Conclusion
Les champs personnalisés ne sont pas réservés aux usages avancés : ils apportent, dès les premiers projets, une souplesse précieuse pour structurer, enrichir et adapter un site WordPress. Qu’ils pilotent un affichage, un style, une logique conditionnelle ou une requête distante, ils permettent de séparer clairement le contenu, la présentation et la logique.
Et ce n’est qu’un début. On pourra demain les combiner à des types de contenus personnalisés, des interfaces Ajax, ou des structures synchronisées entre plusieurs modules. À chaque besoin, un champ peut devenir une passerelle.