I've read a bunch of articles about overriding the default /woocommerce/ templates and tried implementing the following (which were the best/most relevant that I could find all to no avail):

Essentially, what I would like to accomplish is: load all template files (for archives and posts not just template parts) from ~/wp-content/my-plugin/templates/woocommerce/* UNLESS the files are in my theme (and I don't have to override each file instance in my function) . For instance:

  • ~/wp-content/my-plugin/templates/woocommerce/single-product.php (this seems like it just doesn't want to load via plugin)
  • ~/wp-content/my-plugin/templates/woocommerce/archive-products.php (this seems like it just doesn't want to load via plugin)
  • ~/wp-content/my-plugin/templates/woocommerce-pdf-invoices-packing-slips/* (I also want to be able to override other plugin extension templates just like I would be able to in my child theme)


The friendly folks at SkyVerge sent me the following code, which I tested and confirm that it works for template parts.

// Locate the template in a plugin
function myplugin_woocommerce_locate_template( $template, $template_name, $template_path ) {

    $_template = $template;

    if ( ! $template_path ) {
        $template_path = WC()->template_path();

    $plugin_path = myplugin_plugin_path() . '/templates/';

    // Look within passed path within the theme - this is priority
    $template = locate_template(
            trailingslashit( $template_path ) . $template_name,

    // Modification: Get the template from this plugin, if it exists
    if ( ! $template && file_exists( $plugin_path . $template_name ) ) {
        $template = $plugin_path . $template_name;

    // Use default template
    if ( ! $template ) {
        $template = $_template;

    return $template;
add_filter( 'woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3 );

// Helper to get the plugin's path on the server
function myplugin_plugin_path() {
    // gets the absolute path to this plugin directory
    return untrailingslashit( plugin_dir_path( __FILE__ ) );

The above code works for something like:

  • ~/myplugin/templates/single-product/product-image.php

But does NOT work for:

  • ~/myplugin/templates/single-product.php

Where I'm getting stuck:

  • There are solutions to override bits and pieces of WC templates, but there I've not found / been able to create a solution that does comprehensive overrides (i.e. overriding ability just like a child theme would)
  • I can't seem to find the right combination of filter hooks; single-product.php and archive-product.php seem to be controlled by functions outside the standard WC template functions

Thanks in advance!


In this scenario you can use the following filter wc_get_template_part.

Hook reference link: wc_get_template_part

If you don't know how to use filters read this article wordpress hooks for non developers

  • Hi Syed, Thanks for your reply. I am familiar with hooks and edited my post to include code that I tried using wc_get_template_part ...which did not work – Ryan Dorn Jul 10 '17 at 21:20
  • I think you missed something?? Can you post your code? This is only one hook resolve your problem. – Syed Abuthahir M Jul 11 '17 at 3:59
  • Hi Syed. Thanks for your reply. Unfortunately, I'm not quite sure what you mean. Again, I want my plugin to load ALL woocommerce files from ~/my-plugin/templates/woocommerce – Ryan Dorn Jul 11 '17 at 8:21
function woo_template_replace( $located, $template_name, $args, $template_path, $default_path ) {

if( file_exists( plugin_dir_path(__FILE__) . 'templates/' . $template_name ) ) {
    $located = plugin_dir_path(__FILE__) . 'templates/' . $template_name;

return $located;

function woo_get_template_part( $template , $slug , $name ) {

if( empty( $name ) ) {
    if( file_exists( plugin_dir_path(__FILE__) . "/templates/{$slug}.php" ) ) {
        $template = plugin_dir_path(__FILE__) . "/templates/{$slug}.php";
} else {
    if( file_exists( plugin_dir_path(__FILE__) . "/templates/{$slug}-{$name}.php" ) ) {
        $template = plugin_dir_path(__FILE__) . "/templates/{$slug}-{$name}.php";
return $template;

add_filter( 'wc_get_template' , 'woo_template_replace' , 10 , 5 );

add_filter( 'wc_get_template_part' , 'woo_get_template_part' , 10 , 3 );

You can use this snippet in your plugin root file and place your all woocommerce templates file in templates directory.

Plugin structure for reference

  woo-template-replace (plugin root folder)
     woo-template-replace.php (plugin root file)
     templates (folder)
        single-content.php (woocommerce template file)
        searchform.php (woocommerce template file)
  • Thanks, Syed! Your code does work for some parts of what I want. For instance, using ~/my-plugin/templates/single-product/product-image.php does work, for instance. However, ~/my-plugin/templates/single-product.php does not work (I'm guessing that this would have to be hooked into single_template or something else). I've updated my post a bit to reflect newer information. – Ryan Dorn Jul 11 '17 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.