Pour la Brasserie du Lavoir, le thème sur mesure devait permettre à la gérante de changer elle-même la couleur d’accent, le texte d’accroche de la page d’accueil et le numéro de téléphone affiché dans l’en-tête, sans toucher au code. Plutôt que d’installer un constructeur de page complet pour trois réglages, l’API Customizer de WordPress suffisait largement — à condition de bien structurer panneaux, sections et contrôles.
Ce tutoriel construit, étape par étape, un panneau de réglages complet avec $wp_customize, en insistant sur deux points souvent négligés : la validation systématique des valeurs saisies, et l’aperçu live par postMessage pour éviter à l’utilisateur d’attendre un rechargement à chaque modification.
Organiser un panneau et ses sections
Tout commence par le crochet customize_register, qui reçoit l’instance de WP_Customize_Manager. On y crée d’abord un panneau dédié, puis des sections à l’intérieur :
function agence_customize_register( $wp_customize ) {
$wp_customize->add_panel( 'agence_panel', array(
'title' => __( 'Réglages Brasserie du Lavoir', 'agence' ),
'priority' => 30,
) );
$wp_customize->add_section( 'agence_section_header', array(
'title' => __( 'En-tête du site', 'agence' ),
'panel' => 'agence_panel',
) );
$wp_customize->add_section( 'agence_section_colors', array(
'title' => __( 'Couleurs', 'agence' ),
'panel' => 'agence_panel',
) );
}
add_action( 'customize_register', 'agence_customize_register' );
Regrouper les réglages dans un panneau nommé selon le projet, plutôt que de les disperser dans les sections génériques déjà présentes, évite à l’utilisateur final de chercher ses options au milieu de celles fournies par le thème parent ou par des extensions.
Un setting, un contrôle, un sanitize_callback

Chaque réglage se déclare en deux temps : le setting, qui stocke la valeur en base, et le control, qui affiche le champ dans l’interface. Le paramètre sanitize_callback n’est pas optionnel dans une implémentation sérieuse : sans lui, n’importe quelle valeur, y compris du code malveillant, peut être enregistrée telle quelle.
$wp_customize->add_setting( 'agence_phone_number', array(
'default' => '02 40 00 00 00',
'sanitize_callback' => 'sanitize_text_field',
'transport' => 'postMessage',
) );
$wp_customize->add_control( 'agence_phone_number', array(
'label' => __( 'Numéro affiché en en-tête', 'agence' ),
'section' => 'agence_section_header',
'type' => 'text',
) );
$wp_customize->add_setting( 'agence_accent_color', array(
'default' => '#c1440e',
'sanitize_callback' => 'sanitize_hex_color',
'transport' => 'postMessage',
) );
$wp_customize->add_control( new WP_Customize_Color_Control(
$wp_customize,
'agence_accent_color',
array(
'label' => __( 'Couleur d\'accent', 'agence' ),
'section' => 'agence_section_colors',
)
) );
Le choix du sanitize_callback dépend toujours de la nature de la donnée : sanitize_text_field pour du texte simple, sanitize_hex_color pour une couleur, absint pour un entier positif, esc_url_raw pour une URL. Utiliser systématiquement sanitize_text_field par facilité, y compris sur un champ URL, laisse passer des valeurs qui ne se comporteront pas comme prévu à l’affichage.
L’aperçu live sans rechargement de page
Par défaut, sans précision de transport, chaque modification dans le Customizer recharge entièrement l’aperçu — lent et frustrant dès qu’on ajuste une couleur par petites touches. En passant 'transport' => 'postMessage' sur le setting, puis en écoutant les changements côté JavaScript, l’aperçu se met à jour instantanément :
( function( $ ) {
wp.customize( 'agence_phone_number', function( value ) {
value.bind( function( newValue ) {
$( '.site-header .phone-number' ).text( newValue );
} );
} );
wp.customize( 'agence_accent_color', function( value ) {
value.bind( function( newValue ) {
document.documentElement.style.setProperty( '--accent-color', newValue );
} );
} );
} )( jQuery );
Ce fichier JavaScript doit être enregistré via customize_preview_init, un crochet distinct de customize_register, sans quoi il ne sera jamais chargé dans le contexte de l’aperçu :
function agence_customize_preview_js() {
wp_enqueue_script(
'agence-customizer-preview',
get_theme_file_uri( 'assets/js/customizer-preview.js' ),
array( 'customize-preview', 'jquery' ),
'1.0',
true
);
}
add_action( 'customize_preview_init', 'agence_customize_preview_js' );
Lire les valeurs côté template
Une fois les réglages enregistrés, il ne reste qu’à les lire avec get_theme_mod() dans les gabarits du thème, en fournissant toujours une valeur par défaut cohérente avec celle déclarée dans le setting :
get_theme_mod( 'agence_phone_number', '02 40 00 00 00' )dansheader.php.get_theme_mod( 'agence_accent_color', '#c1440e' )injecté en CSS inline viawp_add_inline_style().
Un sanitize_callback absent n’est jamais un oubli sans conséquence : c’est une porte ouverte qui finit toujours par être trouvée, tôt ou tard.
Pour aller plus loin
Cette base — panneaux, sections, sanitize_callback rigoureux et postMessage — couvre l’essentiel des besoins d’un thème sur mesure en 2020. Sur des projets plus ambitieux, on pourra explorer les Customize_Partial pour un rafraîchissement sélectif de zones entières sans JavaScript personnalisé. Ce sera l’objet d’un prochain article, une fois quelques projets supplémentaires livrés avec cette approche.