ITSkillsCenter
WordPress

Guide complet : Les Custom Post Types WordPress

10 min de lecture

Les Custom Post Types WordPress : au-delà des articles et pages

Par défaut, WordPress propose 2 types de contenu : les articles (blog) et les pages (contenu statique). Mais si vous gérez des biens immobiliers, un catalogue de produits, des témoignages, des événements ou un portfolio, vous avez besoin de types de contenu personnalisés (Custom Post Types — CPT). Les CPT sont la fonctionnalité qui transforme WordPress d’un simple blog en un véritable CMS capable de gérer n’importe quel type de données.

1. Quand créer un Custom Post Type

Créez un CPT quand votre contenu :

  • A une structure différente des articles classiques (champs spécifiques)
  • Doit être filtré et recherché indépendamment
  • A besoin de son propre template d’affichage
  • N’entre pas naturellement dans les catégories du blog

Exemples concrets

Type de site CPT recommandés
Agence immobilière Biens, Agents, Témoignages
Restaurant Menu (plats), Événements, Réservations
Agence web Portfolio, Services, Équipe, Témoignages
École/Formation Cours, Formateurs, Sessions
ONG Projets, Rapports, Partenaires
E-commerce (hors WooCommerce) Produits, Commandes, Avis

2. Créer un CPT manuellement (functions.php)

Voici un exemple complet pour un CPT « Service » destiné à une agence web sénégalaise :

// Enregistrer le CPT "Service"
add_action('init', function() {
    register_post_type('service', [
        'labels' => [
            'name'               => 'Services',
            'singular_name'      => 'Service',
            'add_new'            => 'Ajouter un service',
            'add_new_item'       => 'Ajouter un nouveau service',
            'edit_item'          => 'Modifier le service',
            'new_item'           => 'Nouveau service',
            'view_item'          => 'Voir le service',
            'search_items'       => 'Rechercher un service',
            'not_found'          => 'Aucun service trouvé',
            'not_found_in_trash' => 'Aucun service dans la corbeille',
            'all_items'          => 'Tous les services',
            'menu_name'          => 'Services',
        ],
        'public'             => true,
        'has_archive'        => true,
        'rewrite'            => ['slug' => 'services', 'with_front' => false],
        'supports'           => ['title', 'editor', 'thumbnail', 'excerpt', 'page-attributes'],
        'menu_icon'          => 'dashicons-portfolio',
        'menu_position'      => 5,
        'show_in_rest'       => true, // Active Gutenberg et l'API REST
        'publicly_queryable' => true,
        'capability_type'    => 'post',
    ]);
});

// IMPORTANT : après avoir ajouté ce code, allez dans
// Réglages → Permaliens et cliquez "Enregistrer"
// pour régénérer les règles de réécriture

Explication des paramètres clés

Paramètre Valeur Effet
public true Visible sur le site et dans l’admin
has_archive true Crée une page d’archive à /services/
rewrite [‘slug’ => ‘services’] URL : votresite.com/services/nom-du-service
supports tableau Fonctionnalités de l’éditeur (titre, contenu, image…)
show_in_rest true Compatible Gutenberg et API REST
menu_icon dashicons-* Icône dans le menu admin

3. Taxonomies personnalisées

Les taxonomies organisent vos CPT comme les catégories et tags organisent les articles :

// Taxonomie hiérarchique (comme les catégories)
add_action('init', function() {
    register_taxonomy('type_service', 'service', [
        'labels' => [
            'name'          => 'Types de service',
            'singular_name' => 'Type de service',
            'search_items'  => 'Rechercher un type',
            'all_items'     => 'Tous les types',
            'edit_item'     => 'Modifier le type',
            'add_new_item'  => 'Ajouter un type',
        ],
        'hierarchical' => true,  // true = catégories, false = tags
        'rewrite'      => ['slug' => 'type-service'],
        'show_in_rest' => true,
        'show_admin_column' => true, // Colonne dans la liste admin
    ]);
    
    // Ajouter des termes par défaut
    $types = ['Développement web', 'Design graphique', 'SEO', 
              'Marketing digital', 'Formation', 'Maintenance'];
    foreach ($types as $type) {
        if (!term_exists($type, 'type_service')) {
            wp_insert_term($type, 'type_service');
        }
    }
});

// Taxonomie plate (comme les tags)
add_action('init', function() {
    register_taxonomy('technologie', 'service', [
        'labels' => [
            'name'          => 'Technologies',
            'singular_name' => 'Technologie',
        ],
        'hierarchical' => false,
        'rewrite'      => ['slug' => 'tech'],
        'show_in_rest' => true,
    ]);
});

4. Champs personnalisés avec ACF

Les CPT deviennent vraiment puissants avec des champs personnalisés. Advanced Custom Fields (ACF) est l’outil standard :

  1. Installez ACF depuis Extensions → Ajouter
  2. Allez dans ACF → Groupes de champs → Ajouter
  3. Créez un groupe « Détails du service »
  4. Condition d’affichage : « Type de publication = Service »

Champs recommandés pour un CPT « Service »

Champ Type ACF Usage
Prix à partir de Number Montant en FCFA
Durée estimée Text « 2-4 semaines »
Icône Select ou Image Icône visuelle du service
Points clés Repeater Liste de bénéfices
Portfolio associé Relationship Lier aux réalisations
CTA texte Text « Demander un devis »
CTA lien URL Lien WhatsApp ou formulaire

Afficher les champs ACF dans le template

// Dans single-service.php
<?php get_header(); ?>

<article class="service-detail">
  <div class="service-detail__hero">
    <?php if (has_post_thumbnail()) : ?>
      <img src="<?php the_post_thumbnail_url('large'); ?>" 
        alt="<?php the_title_attribute(); ?>" class="service-detail__image">
    <?php endif; ?>
    
    <div class="service-detail__info">
      <h1><?php the_title(); ?></h1>
      
      <?php if ($prix = get_field('prix')) : ?>
        <p class="service-price">
          À partir de <strong><?php echo number_format($prix, 0, ',', ' '); ?> FCFA</strong>
        </p>
      <?php endif; ?>
      
      <?php if ($duree = get_field('duree_estimee')) : ?>
        <p class="service-duration">Durée : <?php echo esc_html($duree); ?></p>
      <?php endif; ?>
    </div>
  </div>
  
  <div class="service-detail__content">
    <?php the_content(); ?>
  </div>
  
  <!-- Points clés (champ Repeater) -->
  <?php if (have_rows('points_cles')) : ?>
    <div class="service-features">
      <h2>Ce qui est inclus</h2>
      <ul>
        <?php while (have_rows('points_cles')) : the_row(); ?>
          <li><?php the_sub_field('point'); ?></li>
        <?php endwhile; ?>
      </ul>
    </div>
  <?php endif; ?>
  
  <!-- CTA -->
  <?php $cta_link = get_field('cta_lien'); ?>
  <?php if ($cta_link) : ?>
    <div class="service-cta">
      <a href="<?php echo esc_url($cta_link); ?>" class="btn-primary">
        <?php echo esc_html(get_field('cta_texte') ?: 'Demander un devis'); ?>
      </a>
    </div>
  <?php endif; ?>
  
  <!-- Réalisations associées -->
  <?php $portfolio = get_field('portfolio_associe'); ?>
  <?php if ($portfolio) : ?>
    <div class="service-portfolio">
      <h2>Réalisations dans ce domaine</h2>
      <div class="portfolio-grid">
        <?php foreach ($portfolio as $project) : ?>
          <a href="<?php echo get_permalink($project->ID); ?>" class="portfolio-item">
            <?php echo get_the_post_thumbnail($project->ID, 'medium'); ?>
            <h3><?php echo esc_html($project->post_title); ?></h3>
          </a>
        <?php endforeach; ?>
      </div>
    </div>
  <?php endif; ?>
</article>

<?php get_footer(); ?>

5. Créer un CPT sans code : plugins

Custom Post Type UI (CPT UI)

Si vous ne voulez pas toucher au code, CPT UI (gratuit) offre une interface pour créer des CPT et taxonomies :

  1. Installez CPT UI depuis Extensions → Ajouter
  2. CPT UI → Ajouter un type de publication
  3. Remplissez le slug, les labels et les options
  4. Cliquez « Ajouter le type de publication »

Avantage : pas de code. Limite : si vous désactivez le plugin, les CPT disparaissent du menu (les données restent en base). Le code dans functions.php est plus durable.

6. Templates de CPT

WordPress utilise la hiérarchie de templates pour afficher les CPT :

// Page individuelle d'un service :
single-service.php      → Template spécifique
single.php              → Fallback générique

// Archive (liste de tous les services) :
archive-service.php     → Template spécifique
archive.php             → Fallback générique

// Taxonomie :
taxonomy-type_service.php  → Template par taxonomie
taxonomy.php               → Fallback
archive.php                → Fallback générique

Archive personnalisée (archive-service.php)

<?php get_header(); ?>

<section class="services-archive">
  <h1>Nos Services</h1>
  
  <!-- Filtres par type -->
  <div class="service-filters">
    <a href="<?php echo get_post_type_archive_link('service'); ?>" 
      class="filter-btn active">Tous</a>
    <?php 
    $types = get_terms(['taxonomy' => 'type_service', 'hide_empty' => true]);
    foreach ($types as $type) : ?>
      <a href="<?php echo get_term_link($type); ?>" 
        class="filter-btn"><?php echo esc_html($type->name); ?></a>
    <?php endforeach; ?>
  </div>
  
  <div class="services-grid">
    <?php while (have_posts()) : the_post(); ?>
      <div class="service-card">
        <?php if (has_post_thumbnail()) : ?>
          <img src="<?php the_post_thumbnail_url('medium'); ?>" 
            alt="<?php the_title_attribute(); ?>" loading="lazy">
        <?php endif; ?>
        <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
        <p><?php the_excerpt(); ?></p>
        <?php if ($prix = get_field('prix')) : ?>
          <span class="price">À partir de <?php echo number_format($prix, 0, ',', ' '); ?> FCFA</span>
        <?php endif; ?>
        <a href="<?php the_permalink(); ?>" class="btn-secondary">En savoir plus →</a>
      </div>
    <?php endwhile; ?>
  </div>
  
  <?php the_posts_pagination(); ?>
</section>

<?php get_footer(); ?>

7. Requêtes WP_Query sur les CPT

// Afficher les 6 derniers services sur la page d'accueil
$services = new WP_Query([
    'post_type'      => 'service',
    'posts_per_page' => 6,
    'orderby'        => 'menu_order',
    'order'          => 'ASC',
]);

if ($services->have_posts()) :
    while ($services->have_posts()) : $services->the_post();
        // Afficher chaque service
    endwhile;
    wp_reset_postdata();
endif;

// Filtrer par taxonomie
$services_dev = new WP_Query([
    'post_type' => 'service',
    'tax_query' => [
        [
            'taxonomy' => 'type_service',
            'field'    => 'slug',
            'terms'    => 'developpement-web',
        ],
    ],
]);

// Filtrer par champ ACF (meta_query)
$services_abordables = new WP_Query([
    'post_type'  => 'service',
    'meta_query' => [
        [
            'key'     => 'prix',
            'value'   => 100000,
            'compare' => '<=',
            'type'    => 'NUMERIC',
        ],
    ],
    'orderby'  => 'meta_value_num',
    'meta_key' => 'prix',
    'order'    => 'ASC',
]);

8. Exposer le CPT dans l’API REST

// Avec show_in_rest => true dans register_post_type,
// votre CPT est accessible via l'API REST :

// GET tous les services :
// https://votresite.com/wp-json/wp/v2/service

// GET un service spécifique :
// https://votresite.com/wp-json/wp/v2/service/123

// Exposer les champs ACF dans l'API REST :
add_action('rest_api_init', function() {
    register_rest_field('service', 'prix', [
        'get_callback' => function($post) {
            return get_field('prix', $post['id']);
        },
    ]);
    
    register_rest_field('service', 'duree', [
        'get_callback' => function($post) {
            return get_field('duree_estimee', $post['id']);
        },
    ]);
});

9. Bonnes pratiques CPT

  • Nommage : le slug du CPT doit être court, en minuscules, sans accents (ex: service, pas nos-services-professionnels)
  • Pas de conflit : évitez les slugs réservés par WordPress : post, page, attachment, revision, nav_menu_item
  • Flush des permaliens : après chaque ajout/modification de CPT, allez dans Réglages → Permaliens et sauvegardez
  • Préfixez vos CPT : utilisez un préfixe pour éviter les conflits avec les plugins (ex: itsc_service)
  • Code dans un plugin : placez le code CPT dans un plugin (mu-plugin) plutôt que dans functions.php — cela dissocie les données du thème. Si vous changez de thème, vos CPT restent
// Créer un mu-plugin : wp-content/mu-plugins/custom-post-types.php
<?php
/**
 * Plugin Name: Custom Post Types
 * Description: CPT personnalisés pour le site
 */

// Tout le code register_post_type et register_taxonomy ici
// Les mu-plugins sont chargés automatiquement, avant les autres plugins

Les Custom Post Types sont la fonctionnalité la plus puissante de WordPress pour créer des sites sur mesure. Combinés avec ACF pour les champs personnalisés et des templates dédiés, ils permettent de gérer n’importe quel type de contenu structuré sans aucun plugin lourd.

#avancé #custom post type #taxonomie
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 350.000 FCFA
Parlons de Votre Projet
Publicité

Articles Similaires