Développement

Hooks WooCommerce : le guide complet des actions et filtres en 2026

Publié le 7 May 2026 — 10 min de lecture
En bref

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, utilisez 999. Pour s’exécuter avant une extension qui hook à 10, utilisez 9.
  • $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 1 alors que le hook en passe 3, 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_Query sur shop_orderwc_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 officielledeveloper.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 plugingrep -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

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.

W
Rédigé par
WebEngine
Développeur web freelance à Paris spécialisé WordPress, WooCommerce et SEO technique depuis 2010. 24 avis vérifiés · Note 5/5. Chaque site livré atteint un score PageSpeed mobile supérieur à 90.

Un projet en tête ?

Devis gratuit sous 48h, sans engagement.

Demander un devis gratuit