Hooks WooCommerce : le guide complet des actions et filtres en 2026
Le guide pratique des hooks WooCommerce en 2026 : actions vs filtres, hooks par tunnel (catalogue, panier, checkout, e-mail), migration HPOS et anti-patterns à éviter.
Les hooks WooCommerce sont la clé de toute personnalisation propre d’une boutique WordPress. À condition de comprendre la différence entre actions et filtres, de connaître les hooks essentiels par tunnel (catalogue, fiche produit, panier, checkout, e-mail) et d’éviter les anti-patterns les plus fréquents — modifier le core WooCommerce ou surcharger des templates pour des broutilles. Voici le guide pratique des hooks WooCommerce en 2026, avec exemples de code qui tournent en production.
Actions vs filtres : la distinction qui change tout
Une action exécute du code à un moment donné
Elle ne retourne rien, elle agit. Exemple : envoyer une notification Slack quand une commande est passée, ajouter un champ dans la fiche produit admin, déclencher une synchro ERP au paiement réussi.
add_action('woocommerce_thankyou', function ($order_id) {
$order = wc_get_order($order_id);
wp_remote_post('https://hooks.slack.com/services/XXX', [
'body' => json_encode([
'text' => sprintf('Nouvelle commande #%d : %s', $order_id, $order->get_total())
]),
]);
}, 10, 1);
Un filtre transforme une donnée et la retourne
Il doit retourner la valeur (modifiée ou non), sinon WooCommerce reçoit null et affiche du vide. Exemple : modifier le prix affiché, changer le texte d’un bouton, filtrer les méthodes de paiement disponibles.
add_filter('woocommerce_product_single_add_to_cart_text', function ($text) {
return 'Commander maintenant';
});
Le piège classique : confondre les deux
L’erreur n°1 des débutants : utiliser add_action sur un hook qui est en fait un filtre, ou inversement. Conséquence : la modification est ignorée silencieusement. Règle pratique : si le nom du hook contient _text, _get_, _class, _args, c’est presque toujours un filtre. Si c’est _after, _before, _complete, _processed, c’est presque toujours une action.
L’anatomie complète d’add_action et add_filter
add_action(string $hook, callable $callback, int $priority = 10, int $args = 1);
add_filter(string $hook, callable $callback, int $priority = 10, int $args = 1);
- $priority — ordre d’exécution. Plus le chiffre est bas, plus tôt c’est exécuté. Défaut
10. Pour s’assurer de passer en dernier, utilisez999. Pour s’exécuter avant une extension qui hook à10, utilisez9. - $args — nombre d’arguments que reçoit le callback. Beaucoup de hooks WooCommerce passent plusieurs arguments (commande + ancien statut + nouveau statut, par exemple). Si vous mettez
1alors que le hook en passe3, vous n’aurez pas accès aux 2 derniers.
Les hooks essentiels du catalogue
Trier ou filtrer les produits affichés en boucle
// Cache les produits en rupture de stock dans les boucles
add_filter('woocommerce_product_query', function ($query) {
$query->set('meta_query', [
[
'key' => '_stock_status',
'value' => 'outofstock',
'compare' => '!=',
],
]);
return $query;
});
Modifier le HTML d’une carte produit dans une boucle
// Ajoute un badge "nouveau" sur les produits créés < 30 jours
add_action('woocommerce_before_shop_loop_item_title', function () {
global $product;
$created = strtotime($product->get_date_created());
if ($created > strtotime('-30 days')) {
echo '<span class="badge-new">Nouveau</span>';
}
}, 8); // priority 8 pour passer avant l'image
Forcer le tri par défaut sur “popularity”
add_filter('woocommerce_default_catalog_orderby', function () {
return 'popularity';
});
Les hooks essentiels de la fiche produit
La page produit est composée d’une série de hooks d’action que WooCommerce déclenche dans un ordre précis. Connaître l’ordre permet d’insérer du contenu sans toucher aux templates :
| Hook | Position | Priorité par défaut |
|---|---|---|
woocommerce_before_single_product |
Tout en haut | — |
woocommerce_before_single_product_summary |
Avant la galerie | — |
woocommerce_single_product_summary |
Bloc résumé (titre, prix, description) | 5, 10, 20, 30, 40 |
woocommerce_before_add_to_cart_form |
Juste avant le formulaire | — |
woocommerce_after_add_to_cart_button |
Sous le bouton “Ajouter au panier” | — |
woocommerce_after_single_product_summary |
Onglets, produits liés | 10, 20 |
woocommerce_after_single_product |
Tout en bas | — |
Ajouter une mention “Livraison gratuite” sous le bouton d’ajout
add_action('woocommerce_after_add_to_cart_button', function () {
echo '<p class="shipping-promo">✓ Livraison gratuite dès 50 €</p>';
});
Retirer la description courte (le bloc excerpt)
remove_action('woocommerce_single_product_summary',
'woocommerce_template_single_excerpt', 20);
Insérer une fiche technique entre les onglets
add_filter('woocommerce_product_tabs', function ($tabs) {
$tabs['fiche_technique'] = [
'title' => 'Fiche technique',
'priority' => 25,
'callback' => function () {
global $product;
echo wpautop($product->get_meta('_fiche_technique'));
},
];
return $tabs;
});
Les hooks essentiels du panier et du checkout
Modifier le prix d’un produit dans le panier
// Applique -10 % aux clients connectés depuis > 1 an
add_action('woocommerce_before_calculate_totals', function ($cart) {
if (is_admin() && !defined('DOING_AJAX')) return;
if (!is_user_logged_in()) return;
$registered = strtotime(wp_get_current_user()->user_registered);
if ($registered > strtotime('-1 year')) return;
foreach ($cart->get_cart() as $item) {
$price = $item['data']->get_price();
$item['data']->set_price($price * 0.9);
}
}, 20, 1);
Ajouter un champ personnalisé au checkout
// 1) Affichage
add_action('woocommerce_after_order_notes', function ($checkout) {
woocommerce_form_field('numero_tva', [
'type' => 'text',
'label' => 'Numéro de TVA intracommunautaire',
'required' => false,
], $checkout->get_value('numero_tva'));
});
// 2) Sauvegarde
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
if (!empty($_POST['numero_tva'])) {
update_post_meta($order_id, '_numero_tva',
sanitize_text_field($_POST['numero_tva']));
}
});
// 3) Affichage dans l'admin
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
$tva = $order->get_meta('_numero_tva');
if ($tva) echo '<p><strong>TVA :</strong> ' . esc_html($tva) . '</p>';
});
Filtrer les méthodes de paiement selon le panier
// Désactive PayPal si panier > 1000 € (limite anti-fraude)
add_filter('woocommerce_available_payment_gateways', function ($gateways) {
if (WC()->cart->total > 1000 && isset($gateways['ppcp-gateway'])) {
unset($gateways['ppcp-gateway']);
}
return $gateways;
});
Forcer un message d’erreur custom sur le checkout
add_action('woocommerce_checkout_process', function () {
if (empty($_POST['numero_tva']) && WC()->cart->total > 500) {
wc_add_notice('Numéro de TVA obligatoire au-dessus de 500 €.', 'error');
}
});
Les hooks de cycle de vie d’une commande
Une commande WooCommerce traverse plusieurs statuts (pending → processing → completed, ou failed, ou refunded). Chaque transition déclenche un hook utile.
| Hook | Quand | Cas d’usage typique |
|---|---|---|
woocommerce_checkout_order_processed |
Commande créée (avant paiement) | Numéro interne, lock stock |
woocommerce_payment_complete |
Paiement réussi | Webhook vers ERP, e-mail interne |
woocommerce_thankyou |
Affichage page de remerciement | Tracking conversion (GA4, Meta) |
woocommerce_order_status_changed |
Tout changement de statut | Notif Slack, log audit |
woocommerce_order_status_completed |
Commande complétée | Demande d’avis, programme fidélité |
woocommerce_order_refunded |
Remboursement | Annulation comptable, retour stock |
Synchroniser une commande payée vers un ERP
add_action('woocommerce_payment_complete', function ($order_id) {
$order = wc_get_order($order_id);
$payload = [
'order_id' => $order_id,
'customer' => $order->get_billing_email(),
'total' => $order->get_total(),
'items' => array_map(function ($item) {
return [
'sku' => $item->get_product()->get_sku(),
'qty' => $item->get_quantity(),
];
}, $order->get_items()),
];
wp_remote_post('https://erp.example.com/api/orders', [
'headers' => ['Content-Type' => 'application/json'],
'body' => wp_json_encode($payload),
'timeout' => 8,
]);
});
Les hooks d’e-mails
WooCommerce envoie une dizaine d’e-mails transactionnels (commande reçue, traitement, expédition, remboursement, mot de passe oublié). Chaque e-mail expose des hooks pour customiser le contenu sans toucher aux templates.
Ajouter un mot personnalisé après le récap commande
add_action('woocommerce_email_after_order_table', function ($order, $sent_to_admin) {
if ($sent_to_admin) return;
echo '<p>Merci de votre confiance ! Suivez-nous sur Instagram @maboutique</p>';
}, 10, 2);
Modifier le sujet d’un e-mail
// Personnalise le sujet de l'e-mail "commande complétée"
add_filter('woocommerce_email_subject_customer_completed_order', function ($subject, $order) {
return sprintf('🎉 Votre commande #%d est en route', $order->get_id());
}, 10, 2);
Désactiver complètement un e-mail
add_filter('woocommerce_email_classes', function ($emails) {
unset($emails['WC_Email_Customer_Note']); // désactive les notes client
return $emails;
});
Les hooks méconnus mais puissants
woocommerce_product_get_price — modifier dynamiquement les prix
Plus propre que de modifier le prix dans le panier (s’applique aussi aux flux Google Shopping, aux exports CSV, aux APIs).
add_filter('woocommerce_product_get_price', function ($price, $product) {
if (is_user_logged_in() && in_array('vip', wp_get_current_user()->roles)) {
return $price * 0.85;
}
return $price;
}, 10, 2);
woocommerce_rest_prepare_product_object — enrichir l’API REST
// Ajoute un champ "stock_synced_at" dans la réponse REST des produits
add_filter('woocommerce_rest_prepare_product_object', function ($response, $product) {
$response->data['stock_synced_at'] = $product->get_meta('_stock_synced_at');
return $response;
}, 10, 2);
woocommerce_admin_order_actions — boutons d’action custom dans la liste des commandes
add_filter('woocommerce_admin_order_actions', function ($actions, $order) {
if ($order->get_status() === 'processing') {
$actions['print_label'] = [
'url' => admin_url('admin-ajax.php?action=print_label&order=' . $order->get_id()),
'name' => 'Imprimer étiquette',
'action' => 'print',
];
}
return $actions;
}, 10, 2);
Les anti-patterns à fuir
1. Modifier directement les fichiers de WooCommerce
Toute modification dans wp-content/plugins/woocommerce/ sera écrasée à la prochaine mise à jour. Utilisez systématiquement les hooks ou la surcharge de templates dans votre thème.
2. Surcharger un template alors qu’un hook existe
Surcharger un template (themes/votre-theme/woocommerce/single-product.php) crée une dette technique : à chaque montée de version WooCommerce, vous devez vérifier que votre template ne diverge pas du nouveau. Si un hook fait l’affaire, préférez-le toujours.
3. Hooker à priorité 10 sans réfléchir
Quand plusieurs extensions hookent la même action à la même priorité, l’ordre devient imprévisible. Adoptez la convention : 5 pour “très tôt”, 10 pour “défaut”, 20 pour “après les défauts”, 50+ pour “très tard”.
4. Oublier de retirer un hook qui ne doit s’exécuter qu’une fois
Pour les hooks à exécution unique, utilisez remove_action ou un flag dans une option WordPress :
add_action('init', function () {
if (get_option('migration_v2_done')) return;
do_migration();
update_option('migration_v2_done', true);
});
5. Faire des requêtes lourdes dans des hooks frontend
Un hook sur woocommerce_before_shop_loop_item_title qui fait une requête SQL est exécuté pour chaque produit affiché. Sur une boutique avec 60 produits par page, c’est 60 requêtes ajoutées. Utilisez le cache WP Object Cache (Redis) ou pré-calculez les données dans des metas produits.
Migration HPOS : ce qui change pour vos hooks
Depuis WooCommerce 8.2, les commandes peuvent être stockées dans des tables custom (HPOS — High-Performance Order Storage) au lieu de wp_posts. Les hooks restent compatibles, mais les fonctions get_post_meta($order_id) ne fonctionnent plus. Adaptez :
get_post_meta($order_id, '_key')→$order->get_meta('_key')update_post_meta($order_id, ...)→$order->update_meta_data(...)+$order->save()WP_Querysurshop_order→wc_get_orders([ ... ])
Le passage à HPOS divise par 5 à 10 le temps de réponse de la liste des commandes admin sur les boutiques avec 50k+ commandes.
Outils pour explorer les hooks
- Documentation officielle — developer.woocommerce.com liste tous les hooks par version.
- Plugin Query Monitor — affiche les hooks déclenchés sur la page courante avec leurs callbacks et priorités.
- Plugin Hookr — explorateur visuel des hooks disponibles avec leurs paramètres.
- Source du plugin —
grep -r "do_action(" wp-content/plugins/woocommerce/reste l’outil le plus fiable pour repérer un hook absent de la doc.
Quand confier vos développements WooCommerce à un expert ?
Trois indicateurs typiques où l’autoformation atteint sa limite :
- Vous avez 5+ extensions tierces qui rentrent en conflit et personne ne sait quel hook casse quoi.
- Votre boutique dépasse 5 000 produits et les pages admin commandes deviennent inutilisables (passage HPOS, optimisation index DB).
- Vous avez besoin d’intégrer un ERP, un PIM, ou un système de facturation et la logique dépasse les capacités d’extensions clé-en-main.
Notre expert WooCommerce à Paris intervient sur ces trois axes en mission ponctuelle (audit + plan d’action) ou en suivi mensuel.
Aller plus loin avec WooCommerce
- Agence WooCommerce — boutiques sur mesure
- Développeur WooCommerce à Paris
- Optimiser WooCommerce : guide performance 2026
- Tunnel de vente WooCommerce : 10 leviers conversion
Questions fréquentes — Hooks WooCommerce en 2026
Quelle est la différence entre un hook WordPress et un hook WooCommerce ?
Aucune sur le plan technique : WooCommerce utilise le système d’action/filtre WordPress natif. La distinction est seulement sémantique : on parle de “hook WooCommerce” pour désigner un hook préfixé woocommerce_* ou défini par l’extension. Les fonctions add_action / add_filter / remove_action sont identiques.
Où placer le code de mes hooks ?
Trois bons endroits, par ordre de qualité : 1) un plugin custom (recommandé), 2) un fichier inclus depuis functions.php du thème enfant, 3) directement dans functions.php. Évitez Code Snippets et autres plugins de “bouts de code” pour la production : leur traçabilité Git est nulle.
Comment savoir quel hook utiliser pour un besoin précis ?
Trois techniques : 1) installer Query Monitor et regarder les hooks déclenchés sur la page concernée, 2) grep -r "do_action(" wp-content/plugins/woocommerce/ avec un terme métier (ex: “checkout”), 3) consulter la documentation code reference qui liste les hooks par fichier.
Mes modifications via hooks ne s’appliquent pas, pourquoi ?
Cinq causes les plus fréquentes : 1) action utilisée à la place d’un filtre (ou inverse), 2) priorité trop basse, écrasée par un hook plus tardif, 3) le filtre ne retourne pas la valeur, 4) le hook n’est en fait pas déclenché sur la page actuelle (Query Monitor le confirme), 5) un cache d’objet Redis qui sert une version mémorisée — purgez-le.
Combien de hooks WooCommerce existe-t-il en 2026 ?
Plus de 1 200 hooks d’actions et 800 hooks de filtres recensés dans la version 9.x. Personne ne les utilise tous : les développeurs expérimentés en utilisent une trentaine de manière récurrente, les autres se découvrent au cas par cas selon le besoin métier.
Les hooks fonctionnent-ils avec Block Editor (Gutenberg) côté front WooCommerce ?
Partiellement. Les blocs WooCommerce (Cart Block, Checkout Block lancés en 2022) utilisent React côté client et n’écoutent pas tous les hooks PHP traditionnels. Pour customiser le Cart/Checkout block, il faut soit utiliser les filtres dédiés __experimentalRegisterCheckoutFilters, soit revenir au shortcode [woocommerce_checkout] qui reste pleinement hookable. Le choix dépend de votre stratégie : les blocs sont plus rapides et accessibles, les shortcodes plus customisables côté backend.