Un thème fonctionne parfaitement sur l’environnement de développement, où il a été activé normalement depuis l’écran Apparence > Thèmes. Une fois déployé en production par copie directe des fichiers via SSH, en remplaçant un dossier de thème déjà actif par sa nouvelle version, certains réglages attendus au premier lancement n’apparaissent jamais : pas de page d’accueil statique créée automatiquement, pas de menu par défaut assigné, pas de widgets préconfigurés dans la barre latérale.
Ce comportement n’est pas un bug de WordPress, ni un problème propre au thème : il découle directement de la façon dont le hook after_switch_theme est déclenché, et des conditions précises qui doivent être réunies pour qu’il s’exécute.
Ce que fait réellement after_switch_theme
Le hook d’action after_switch_theme s’exécute uniquement lorsque WordPress détecte un changement du thème actif, opération qui se produit normalement via la fonction switch_theme(), elle-même appelée par l’écran d’activation des thèmes dans l’administration. De nombreux thèmes utilisent ce hook pour créer une page d’accueil par défaut, assigner un menu, ou définir des réglages initiaux propres au premier lancement :
add_action( 'after_switch_theme', function () {
if ( ! get_option( 'mon_theme_page_accueil_creee' ) ) {
$page_id = wp_insert_post( [
'post_title' => 'Accueil',
'post_status' => 'publish',
'post_type' => 'page',
] );
update_option( 'show_on_front', 'page' );
update_option( 'page_on_front', $page_id );
update_option( 'mon_theme_page_accueil_creee', true );
}
} );
Pourquoi une copie de fichiers ne déclenche jamais ce hook
WordPress détermine le thème actif via l’option template et stylesheet, stockées en base de données. Remplacer les fichiers d’un thème par une nouvelle version, sans jamais modifier ces options en base, ne constitue pas un changement de thème actif du point de vue de WordPress : le thème « actif » reste, à ses yeux, exactement le même qu’avant la copie, puisque son identifiant de dossier n’a pas changé. Le hook after_switch_theme ne s’exécute que lorsque switch_theme() est appelée, ce qui n’arrive jamais dans ce scénario de déploiement.

Reproduire le comportement attendu sans passer par l’écran d’activation
Pour les projets déployés systématiquement par copie de fichiers plutôt que par activation manuelle, la solution consiste à ne pas dépendre uniquement de after_switch_theme pour l’initialisation critique, mais à prévoir une vérification indépendante, déclenchée à chaque chargement de l’administration :
add_action( 'admin_init', function () {
if ( ! get_option( 'mon_theme_page_accueil_creee' ) ) {
// Même logique d'initialisation que dans after_switch_theme.
}
} );
Cette vérification, bien que légèrement moins élégante qu’un hook dédié, garantit que l’initialisation s’exécute quel que soit le mode de déploiement utilisé, tant que l’option de contrôle n’a pas encore été enregistrée.
Une commande WP-CLI pour forcer le déclenchement
Sur un environnement où le thème a déjà été copié sans jamais passer par une activation en bonne et due forme, il est possible de forcer artificiellement le déclenchement du hook en réactivant le thème via WP-CLI, ce qui appelle bien switch_theme() en interne :
wp theme activate mon-theme
Cette commande produit exactement le même effet qu’un clic sur le bouton d’activation dans l’administration, y compris le déclenchement de after_switch_theme, même si le thème était déjà considéré comme actif juste avant.
Un hook qui dépend d’un changement d’état plutôt que d’un simple chargement de fichier ne se déclenche jamais par accident ; encore faut-il connaître précisément la condition qui le déclenche pour ne pas compter dessus à tort.
En résumé
Un déploiement par copie directe de fichiers, courant sur les hébergements sans pipeline automatisé, ne déclenche jamais after_switch_theme, puisque ce hook dépend d’un véritable changement d’option en base de données via switch_theme(). Prévoir une vérification de repli via admin_init, ou réactiver explicitement le thème avec WP-CLI après un déploiement, évite qu’une initialisation critique passe silencieusement à la trappe.