WordPress est né comme plateforme de blogs, mais il y a longtemps qu'il a cessé d'être seulement cela : aujourd'hui, il gère des portfolios, des agences immobilières, des académies, des annuaires d'entreprises et des boutiques entières. La pièce qui rend possible cette polyvalence sont les types de publication personnalisés de WordPress : des types de contenu personnalisés qui coexistent avec les articles et les pages, mais avec leur propre nom, leurs propres champs, leurs propres URL et leur propre section dans le tableau de bord. Si vous avez déjà essayé de gérer des « projets », des « recettes » ou des « cours » à l'aide d'articles normaux et de catégories, vous savez à quelle vitesse cela se transforme en chaos. Dans ce guide complet, vous apprendrez ce qu'est exactement un Type de Publication Personnalisé (CPT), quand il est judicieux de le créer et quand non, comment l'enregistrer avec un code PHP complet et correct, comment lui ajouter ses propres taxonomies, comment l'afficher dans votre thème et quelles implications cela a pour le SEO. En terminant, vous pourrez structurer n'importe quel projet avec la solidité d'un développeur professionnel.
Que sont les types de publication personnalisés de WordPress
Dans WordPress, tout contenu est techniquement un « article » : les articles de blog (post), les pages (page), les pièces jointes de la médiathèque (attachment), les révisions ou les menus de navigation. Tous sont enregistrés dans la même table de la base de données (wp_posts) et se distinguent par la valeur de la colonne post_type. Un type de publication personnalisé n'est rien d'autre qu'une nouvelle valeur dans cette colonne, enregistrée par vous, avec ses propres règles : quelles caractéristiques il prend en charge (éditeur, image mise en avant, extrait), comment il est nommé dans le menu, quelle URL ont ses éléments et s'il apparaît ou non dans les résultats de recherche.
Exemples classiques où les types de publication personnalisés de WordPress brillent :
- Portfolio : projets avec image, client et technologie utilisée.
- Immobilier : propriétés avec prix, surface et emplacement.
- Académie : cours et leçons avec durée et niveau.
- Restaurant : plats avec allergènes et prix.
- Événements : avec date, lieu et capacité.
En fait, vous les utilisez déjà sans le savoir : les produits WooCommerce sont un CPT appelé product, et les formulaires de presque n'importe quel plugin sont également enregistrés comme leurs propres types de contenu.
Quand créer un CPT (et quand ne pas le faire)
La question clé : ce contenu est-il conceptuellement distinct d'un article de blog ? Si la réponse est oui (il est logique de le lister séparément, avec ses propres archives et sa propre structure), il est candidat à un CPT. Si vous voulez seulement regrouper des articles par thème, l'outil correct sont les catégories et les étiquettes habituelles.
| Situation | Solution adéquate |
|---|---|
| Séparer le blog par thématiques | Catégories |
| Fiches de produits, cours, biens immobiliers… | Type de publication personnalisé |
| Marquer des articles avec des mots-clés isolés | Étiquettes |
| Classer un CPT (genre d'un livre, zone d'un bien immobilier) | Taxonomie personnalisée |
| Données spécifiques de chaque élément (prix, date, ISBN) | Champs personnalisés (post meta) |
Une autre décision préalable : code ou plugin ? Des plugins comme Custom Post Type UI ou Pods permettent d'enregistrer des CPT depuis le panneau sans écrire de PHP, et sont parfaitement valides. En contrepartie, ils génèrent une dépendance : si le plugin est désactivé, le contenu n'est pas supprimé mais disparaît du tableau de bord. L'enregistrement par code, que nous allons voir maintenant, est plus léger, portable et contrôlable, et c'est ainsi que le font tous les thèmes et plugins professionnels.
Comment enregistrer un type de publication personnalisé avec du code
Tout tourne autour d'une fonction : register_post_type(), qui doit être exécutée sur le hook init. Ceci est un enregistrement complet et commenté pour un CPT de portfolio, prêt à l'emploi :
<?php
function biblioweb_registrar_cpt_proyecto() {
$labels = array(
'name' => 'Proyectos',
'singular_name' => 'Proyecto',
'menu_name' => 'Porfolio',
'add_new' => 'Añadir nuevo',
'add_new_item' => 'Añadir nuevo proyecto',
'edit_item' => 'Editar proyecto',
'new_item' => 'Nuevo proyecto',
'view_item' => 'Ver proyecto',
'search_items' => 'Buscar proyectos',
'not_found' => 'No se han encontrado proyectos',
'not_found_in_trash' => 'No hay proyectos en la papelera',
'all_items' => 'Todos los proyectos',
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'menu_position'=> 20,
'menu_icon' => 'dashicons-portfolio',
'rewrite' => array( 'slug' => 'proyectos', 'with_front' => false ),
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions', 'custom-fields' ),
'show_in_rest' => true, // Necesario para el editor de bloques y la REST API.
'taxonomies' => array(),
);
register_post_type( 'proyecto', $args );
}
add_action( 'init', 'biblioweb_registrar_cpt_proyecto' );
Passons en revue les arguments qui génèrent le plus de doutes :
public: danstrue, le CPT a ses propres URL, apparaît dans le tableau de bord et est visible. Pour le contenu interne (par exemple, des témoignages qui ne sont affichés qu'intégrés), on peut affiner avecpublicly_queryableyexclude_from_search.has_archive: crée la page d'archive danstudominio.com/proyectos/avec la liste de tous les éléments.rewrite: définit le slug des URL.with_front => falseévite d'hériter des préfixes de la structure des permaliens (comme/blog/biblioweb.comsupports: quelles boîtes apparaissent dans l'éditeur. Si votre CPT n'a pas besoin d'éditeur de texte, supprimez-le et le formulaire sera plus propre.show_in_rest: indispensable danstruesi vous souhaitez utiliser Gutenberg avec ce CPT ou le consommer depuis l'API REST.menu_icon: n'importe quelle icône de la bibliothèque Dashicons, ou le chemin vers un SVG personnalisé.
Un avertissement critique : après avoir enregistré ou modifié un CPT, visitez Ajustes → Enlaces permanentes et cliquez sur « Enregistrer les modifications ». Ce geste régénère les règles de réécriture ; si vous ne le faites pas, les nouvelles URLs renverront une erreur 404 et vous perdrez un bon moment à chercher une erreur qui n'est pas dans votre code.
Où le placer ? Dans un plugin propre ou dans un gestionnaire de snippets comme WPCode, que nous avons analysé en profondeur ici. Évitez le functions.php du thème : un CPT est une fonctionnalité, pas un design, et doit survivre à un changement de thème.
Taxonomies personnalisées : classer votre nouveau contenu
Les catégories et étiquettes standard appartiennent aux articles. Pour classer un CPT, il est correct d'enregistrer des taxonomies propres avec register_taxonomy(). En poursuivant avec le portfolio, créons une taxonomie « Type de projet » :
<?php
function biblioweb_registrar_taxonomia_tipo() {
$labels = array(
'name' => 'Tipos de proyecto',
'singular_name' => 'Tipo de proyecto',
'search_items' => 'Buscar tipos',
'all_items' => 'Todos los tipos',
'edit_item' => 'Editar tipo',
'add_new_item' => 'Añadir nuevo tipo',
);
register_taxonomy(
'tipo_proyecto',
array( 'proyecto' ),
array(
'labels' => $labels,
'hierarchical' => true, // true = como categorías; false = como etiquetas.
'rewrite' => array( 'slug' => 'tipo-proyecto' ),
'show_in_rest' => true,
)
);
}
add_action( 'init', 'biblioweb_registrar_taxonomia_tipo' );
Le paramètre hierarchical décide du comportement : dans true fonctionne comme les catégories (avec hiérarchie parent-enfant et cases à cocher) ; dans false, comme les étiquettes (texte libre). Chaque terme génère automatiquement sa propre page d'archive : tudominio.com/tipo-proyecto/diseno-web/.
Comment afficher les custom post types dans votre thème
WordPress résout la présentation via la hiérarchie des modèles. Pour notre CPT proyecto cherchera, dans cet ordre :
single-proyecto.phppour la fiche individuelle (si elle n'existe pas, utilisezsingle.phpbiblioweb.comarchive-proyecto.phppour la liste (si elle n'existe pas, utilisezarchive.phpet ensuiteindex.phpbiblioweb.comtaxonomy-tipo_proyecto.phppour les archives de la taxonomie.
Si votre thème est à blocs ou si vous utilisez un constructeur de pages, vous pourrez normalement assigner des modèles au CPT depuis son interface propre. Et pour les listes personnalisées dans n'importe quel modèle ou shortcode, la requête se fait avec WP_Query:
<?php
$proyectos = new WP_Query( array(
'post_type' => 'proyecto',
'posts_per_page' => 6,
'tax_query' => array(
array(
'taxonomy' => 'tipo_proyecto',
'field' => 'slug',
'terms' => 'diseno-web',
),
),
) );
if ( $proyectos->have_posts() ) :
while ( $proyectos->have_posts() ) : $proyectos->the_post();
the_title( '<h3>', '</h3>' );
the_post_thumbnail( 'medium' );
endwhile;
wp_reset_postdata();
endif;
N'oubliez jamais wp_reset_postdata() après une boucle personnalisée : restaurez la requête principale et évitez les effets secondaires étranges sur le reste de la page. La référence complète de tous les arguments disponibles se trouve dans la documentation officielle des types de publication de developer.wordpress.org.
Champs personnalisés : les données qui complètent la fiche
Un CPT définit le « conteneur », mais les données spécifiques (prix, client, date de livraison) vivent dans des champs personnalisés (post meta). Vous pouvez les gérer de trois manières : avec la boîte native de champs personnalisés (spartiate mais fonctionnelle), avec du code via register_post_meta() y get_post_meta(), ou avec des plugins spécialisés comme Advanced Custom Fields (ACF) ou Meta Box, qui génèrent des interfaces d'édition confortables avec validation et types de champs avancés. Pour les projets sérieux, la combinaison CPT par code + ACF pour les champs est probablement le standard de l'industrie.
<?php
// Registrar un campo y exponerlo en la REST API:
register_post_meta( 'proyecto', 'cliente', array(
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
) );
// Leerlo en la plantilla:
$cliente = get_post_meta( get_the_ID(), 'cliente', true );
SEO et custom post types : ce que vous devez vérifier
Un CPT bien conçu est une bénédiction pour le SEO : il génère des archives propres, des URLs sémantiques et une structure claire. Mais il convient de revoir quatre points :
- Sitemap : vérifiez que votre plugin SEO inclut le nouveau type de contenu dans le sitemap XML. Tant Yoast que Rank Math, dont nous avons analysé la version gratuite, détectent les CPT publics et permettent de les activer ou de les exclure par type.
- Indexation sélective : si le CPT est un contenu de support (témoignages, blocs réutilisables), marquez-le comme non indexable ou enregistrez-le directement avec
public => false. - Slug avec intention :
/proyectos/en dit plus que/cpt_portfolio/. Le slug de réécriture est une décision SEO, et le modifier après implique des redirections. - Contenu dans l'archive : la page d'archive générée automatiquement est généralement une simple liste ; valoriser une page avec son propre texte d'introduction peut faire la différence pour positionner le mot-clé principal du type de contenu.
Questions fréquentes
Que se passe-t-il avec le contenu si je désactive le plugin qui enregistre le CPT ?
Rien n'est supprimé : les éléments restent dans la base de données. Ils cessent simplement d'être affichés dans le tableau de bord et leurs URLs renvoient une erreur 404, car WordPress ne reconnaît plus ce type de contenu. En réactivant l'enregistrement (plugin ou snippet), tout réapparaît intact. C'est pourquoi il est important de maintenir l'enregistrement dans quelque chose d'indépendant du thème.
Custom post type ou catégories ? Je ne sais toujours pas lequel utiliser
Utilisez des catégories lorsque vous souhaitez organiser des articles de blog qui partagent le même format. Utilisez un CPT lorsque le contenu a sa propre nature : champs différents, modèle différent et sens en tant que section indépendante du site web. Un indice pratique : si vous vous surprenez à vouloir masquer ces « articles » du blog principal, il est presque certain qu'ils devraient être un custom post type.
Combien de custom post types puis-je créer ?
Il n'y a pas de limite technique pertinente : tous partagent la table wp_posts et le coût d'enregistrement de chaque type est minime. La limite raisonnable est organisationnelle : si vous dépassez six ou huit types, vérifiez si certains ne devraient pas être en réalité des taxonomies ou des champs d'un même type. Réservez des noms avec un préfixe (par exemple bw_proyecto) si vous distribuez votre code, pour éviter les collisions avec d'autres plugins.
Pourquoi mes custom post types donnent-ils une erreur 404 ?
Dans 95 % des cas, à cause des règles de réécriture : WordPress n'a pas encore « appris » les nouvelles URLs. Allez à Ajustes → Enlaces permanentes et enregistrez sans rien changer. Si cela persiste, vérifiez que public soit true, que le slug de réécriture n'entre pas en conflit avec une page existante et que l'enregistrement s'exécute dans le hook init à chaque chargement, pas seulement à l'activation.
Conclusion
Les custom post types de WordPress sont l'outil qui transforme un blog en un véritable CMS sur mesure : portfolios, catalogues, répertoires ou académies, chaque contenu avec sa structure, ses URLs et sa place dans le tableau de bord. La recette professionnelle tient en trois étapes : enregistrer le type avec register_post_type() dans le hook init (et enregistrer les permaliens), le classer avec des taxonomies propres via register_taxonomy(), et compléter les fiches avec des champs personnalisés. À partir de là, la hiérarchie des modèles et WP_Query vous donnent un contrôle total sur la façon dont tout est affiché. Commencez par un seul type de contenu réel de votre projet, enregistrez-le par code dans un snippet ou votre propre plugin, et vérifiez sur le tableau de bord ce que change la gestion de « projets » réels au lieu d'articles déguisés. Cette clarté structurelle, vous l'apprécierez, vos clients l'apprécieront et Google l'appréciera.