When embarking on a new WooCommerce project, there are many ways to tackle template modification. I’ll go through the most common methods below, and explain the method I use and why I think it’s the best way!

Override a Template File in your Theme

We’ve all done it; create a “woocommerce” folder in your theme folder and copy the relevant template files over.

While this method works well, I still don’t recommend it. WooCommerce regularly update these templates, and your modified version will soon become out of date.

Modify a Template File Directly

Just no. You should never do this! Next time you update WooCommerce, your changes are gone.

Using Actions and Filters

Yes! Now we’re talking.

This is by far the best method of customising your WooCommerce templates. WooCommerce very kindly include a whole load of actions and filters that you can latch onto in order to modify any aspect of the default template files.

At first, it may seem daunting. But fear not! The following guide should get you well on your way.

Finding the Available Actions

There are a lot of them, that’s for sure. The method I use to find out which actions I can use is to literally browse the template files on github. This allows me to use the search to find snippets of text within the files.

The template files display a lot of useful information. Let’s consider the templates/single-product.php template to start with.

<?php
	/**
	 * woocommerce_before_main_content hook.
	 *
	 * @hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
	 * @hooked woocommerce_breadcrumb - 20
	 */
	do_action( 'woocommerce_before_main_content' );
?>

The first action we can see in the file is called via do_action( 'woocommerce_before_main_content' );. Anytime you see this `do_action` function, it’s likely some actions are hooked in at that point.

WooCommerce (and WordPress in general) will often use these actions to add template parts. In the template file you can see that the hooked functions have been clearly labelled for you, along with their priorities.

There are 2 hooked functions on woocommerce_before_main_content, woocommerce_output_content_wrapper and woocommerce_breadcrumb. The priorities (10, 20) simply let you know what order the hooked functions will appear in; 10 being first, 20 being last. 30 would appear after 20, etc.

So this is a great way of finding out what actions are available. Anywhere an action is available, you can output the contents of a custom function. For example, you may want to add a content wrapper (opening and closing div tags) before and after the main content action. You’d use the woocommerce_before_main_content and woocommerce_after_main_content actions. You can also easily remove or move any of the actions that are there, for example, you could remove the breadcrumbs with 1 line of code (see below).

Using One of The Actions

Let’s take our earlier example of adding opening and closing div tags around the main content. You can use this method to modify the layout of the page to match that of your own frontend code.

/**
 * Opening div for our content wrapper
 */
add_action('woocommerce_before_main_content', 'iconic_open_div', 5);

function iconic_open_div() {
    echo '<div class="iconic-div">';
}

/**
 * Closing div for our content wrapper
 */
add_action('woocommerce_after_main_content', 'iconic_close_div', 50);

function iconic_close_div() {
    echo '</div>';
}

So here I have added both the opening and closing div tag. You’d add this to your functions.php (or equivalent) file in your theme.

First of all, we tell our iconic_open_div function to execute on the woocommerce_before_main_content action with a priority of 5. This will output our opening div tag just before the WooCommerce content wrapper.

Then we closed it on the woocommerce_after_main_content action, with a priority of 50 to make sure it comes last.

That’s it! WooCommerce can modify that template all they want, as long as those actions remain in place, our changes will never be lost, and will never cause issues when new functionality is added.

Another example could be that you want to output some text just after your product title in the catalog pages. We’d need to modify the templates/content-product.php template.

Open the file and you will see that woocommerce_template_loop_product_title is hooked to the woocommerce_shop_loop_item_title action. We can hook in just after it, as we can see it has a priority of 10.

/**
 * Add coming soon text after a product title
 */
add_action('woocommerce_shop_loop_item_title', 'iconic_after_title', 15);

function iconic_after_title() {
    echo __('Coming Soon', 'iconic');
}

We could easily take this one step further, and add the text only to the product with an ID of 15. The global $product variable is accessible at this stage.

/**
 * Add coming soon text after a product title
 */
add_action('woocommerce_shop_loop_item_title', 'iconic_after_title', 15);

function iconic_after_title() {
    global $product;

    // exit if the product does not have an ID of 15
    if( $product->id != 15 )
        return;

    echo __('Coming Soon', 'iconic');
}

Removing or Moving an Action

Removing an existing action is simple. Let’s say we wanted to remove the WooCommerce breadcrumbs. Simply add the following to your functions.php file.

/**
 * Remove breadcrumbs
 */
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20);

The first parameter is the action name, the second is the action/function name, and the third is the priority. When removing an action, you need to use the same priority that it was added with.

Using this knowledge, it’s easy to move an action. Let’s move the breadcrumbs to before the opening WooCommerce content wrapper.

/**
 * Remove breadcrumbs
 */
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20);


/**
 * Add breadcrumbs earlier on
 *
 * We know the content wrapper is added at priority 10, so
 * let's add the breadcrumbs before that, at priority 5
 */
add_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 5);

All we did was change the priority. Simple!

Conclusion

As you can see, when using the available hooks to modify your templates, the options are endless. On top of that, it is far safer in terms of future updates, and also for your sanity when coming back to the code at a later date.

Let me know if you use this method on one of your next builds!