Every element on a single product page, breadcrumb, gallery, title, price, add-to-cart, tabs, related products, is placed there by a hook with a default function attached. Knowing the full sequence is what makes it possible to insert, remove, or reorder anything without touching a template file.
The Code
This is the full sequence, in firing order, straight from WooCommerce’s content-single-product.php template, with the default functions and their priorities:
// Page wrapper
do_action( 'woocommerce_before_main_content' ); // woocommerce_breadcrumb - 20
do_action( 'woocommerce_before_single_product' ); // woocommerce_output_all_notices - 10
// Left column: gallery
do_action( 'woocommerce_before_single_product_summary' );
// woocommerce_show_product_sale_flash - 10
// woocommerce_show_product_images - 20
// Right column: summary
do_action( 'woocommerce_single_product_summary' );
// woocommerce_template_single_title - 5
// woocommerce_template_single_rating - 10
// woocommerce_template_single_price - 10
// woocommerce_template_single_excerpt - 20
// woocommerce_template_single_add_to_cart - 30
// woocommerce_template_single_meta - 40
// woocommerce_template_single_sharing - 50
// WC_Structured_Data::generate_product_data() - 60
// Below the summary
do_action( 'woocommerce_after_single_product_summary' );
// woocommerce_output_product_data_tabs - 10
// woocommerce_upsell_display - 15
// woocommerce_output_related_products - 20
// Page wrapper close
do_action( 'woocommerce_after_main_content' ); // closing wrapper divs - 10
do_action( 'woocommerce_sidebar' ); // woocommerce_get_sidebar - 10
Here’s a practical example using two of these hooks together, adding a shipping estimate note right after the price, before the add-to-cart button:
add_action( 'woocommerce_single_product_summary', 'fixelar_shipping_note', 25 );
function fixelar_shipping_note() {
echo '<p class="fixelar-shipping-note">' .
esc_html__( 'Estimated delivery: 3-5 business days.', 'woocommerce' ) .
'</p>';
}
Priority 25 places it after price (10) and excerpt (20), but before add-to-cart (30).
Where to Put This Code
Custom hook functions like the shipping note example go in your child theme’s functions.php, or in a snippets plugin like Code Snippets. Never edit these hooks by modifying WooCommerce’s own template files directly, and never place custom code in a parent theme, since either approach gets wiped out on the next update.
If you need to remove a default function instead of adding one, you need its exact original priority. remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 ); only works with that exact 20. A mismatched priority means WordPress can’t find the function to remove, and it silently keeps running.
How to Read This Map
Each do_action() call is a spot where WooCommerce lets you inject content. The functions listed under each one with a number are what WooCommerce hooks in by default, and that number is the priority: lower numbers run first.
woocommerce_single_product_summary is the one you’ll touch most often, since it’s where title, price, and add-to-cart all live. Adding your own function here with a priority between two existing numbers, like 25 between price (10-20 range) and add-to-cart (30), inserts your content at a specific point in that sequence without disturbing anything else.
The distinction between woocommerce_before_single_product_summary and woocommerce_single_product_summary trips people up. The first wraps the gallery column. The second wraps the entire right-hand summary column, title through structured data. Content added to the wrong one usually ends up in the wrong visual location entirely, not just the wrong order.
Real Use Cases
Adding a trust badge or urgency message near the add-to-cart button. A priority just below 30 (add-to-cart) places a “only 3 left” or “ships today” message right where a shopper’s attention already is.
Reordering the summary to put reviews above the add-to-cart button. Reordering woocommerce_template_single_rating to a lower priority than title moves the star rating higher, useful for stores where social proof drives more conversions than immediate price visibility.
Removing product sharing icons that nobody uses. remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_sharing', 50 ); cleans up a feature many stores don’t need, without disabling anything else.
Injecting a custom size guide or FAQ block right after the tabs. Using woocommerce_after_single_product_summary with a priority higher than 20 (related products) puts custom content at the very bottom of the page, after everything WooCommerce renders by default.
Common Issues
My content shows up in the wrong location. Double-check which hook you used. woocommerce_before_single_product_summary and woocommerce_single_product_summary look similar in name but wrap completely different sections of the page.
remove_action() isn’t removing the default function. The priority number must match exactly what’s listed above. A common mistake is guessing 10 for everything instead of checking the actual default.
Content appears twice. This is often a leftover from an earlier theme customization or plugin that already added similar content to the same hook. Search your child theme’s functions.php for the same hook name before adding a new one.
Changes work on some products but not others. If your theme overrides content-single-product.php in its own folder, the theme’s version of that file, not WooCommerce’s default, determines whether these exact hooks even exist in that location. Check for a theme override first.
If your store needs the product page laid out and tested against your actual theme and plugins, not just copied from a generic tutorial, that’s exactly the kind of work Fixelar handles as part of our WooCommerce custom development services. We map your specific hook stack before touching anything.