Hooks: actions and filters
A hook is a named point in WooCommerce code to which you attach your own functions. There are two kinds: an action does something at the right moment, a filter changes a value and returns it. Almost every shop customization starts with the question of which hook to attach to.
An action
An action is attached with add_action(). Add to includes/storefront.php:
// wp-content/plugins/acme-shop/includes/storefront.php
add_action('woocommerce_thankyou', function (int $orderId) {
echo '<p>We will call you within an hour.</p>';
});WooCommerce fires the woocommerce_thankyou hook on the Order received page and passes the order number. Place a test order — the paragraph appears below the order details. An action returns nothing: it prints text, sends an email, writes to the database.
A filter
A filter is attached with add_filter(). It receives a value, changes it and must return it:
// wp-content/plugins/acme-shop/includes/storefront.php
add_filter('woocommerce_product_single_add_to_cart_text', function (string $text): string {
return 'Buy';
});On the product page the Add to cart button is now called Buy. If you forget return, the button is left without text.
Priority and arguments
add_action() and add_filter() have two more parameters: the priority and the number of arguments.
// wp-content/plugins/acme-shop/includes/storefront.php
add_filter('woocommerce_get_price_html', function (string $html, WC_Product $product): string {
return $product->is_on_sale() ? $html . ' <small>sale</small>' : $html;
}, 20, 2);Priority 20 means run after the standard functions: the default is 10, and a smaller number runs earlier. The number 2 says the function takes two arguments — without it WordPress passes only the first. Products on sale get the word sale next to the price.
Detaching someone else's function
An attached function can be removed — with the same name and priority:
// wp-content/plugins/acme-shop/includes/storefront.php
add_action('init', function () {
remove_action('woocommerce_before_shop_loop', 'woocommerce_result_count', 20);
});The line Showing 1–12 of 40 results disappears from the catalog page. Functions must be removed after WooCommerce has attached them, so the call is wrapped in the init hook.
How to find a hook
| Way | How |
|---|---|
| Template | Open a file in woocommerce/templates/ and look for do_action( |
| Code search | Look for apply_filters( near the value you need |
| Documentation | The hook reference on developer.woocommerce.com |
| The Query Monitor plugin | Shows the hooks fired on the current page |
For example, templates/single-product/add-to-cart/simple.php has do_action('woocommerce_before_add_to_cart_button') before the button — so your block before the button is attached to that hook.
Frequent hooks
| Hook | Kind | Where it fires |
|---|---|---|
woocommerce_before_shop_loop | action | Above the product list |
woocommerce_single_product_summary | action | The right column of the product page |
woocommerce_thankyou | action | The Order received page |
woocommerce_get_price_html | filter | The product price HTML |
loop_shop_per_page | filter | Products per catalog page |
Common mistake
echo is written in a filter instead of return. The text is printed in a random place on the page — wherever the filter was called — and the value itself becomes empty. An action prints, a filter returns: the function name, add_action or add_filter, always tells you which is required.