WooCommerce comes with several email templates out of the box. It also provides you with a way to register your own emails which are going to be sent on some events. In this tutorial we will learn how to create a new custom WooCommerce Email.

The Main WooCommerce Email Class

To create a custom WooCommerce Email, you should understand the main WC_Email class. You can find it at includes/emails/class-wc-email.php or read it online on GitHub. This class is extending the WC_Settings_API class which is used for any settings related things in WooCommerce.

I won’t go into every possible detail of the WC_Email class (I leave that for the ambitious ones), but there are some of the attributes and methods you might want to know:

  • $title – Email title, used in admin,
  • $description – Email description, used in admin,
  • $heading – Email heading, used in templates,
  • $subject – Email subject,
  • $template_base – the absolute path to the folder where the templates are located,
  • $template_html – the relative path to the HTML email template,
  • $template_plain – the relative path to the plain email template,
  • $recipient – a string of recipient emails,
  • $object – The object for which is the email. This can be a WC_Product, WC_Customer or something else (even our own),
  • $customer_email – if this email is sent to customers.
  • send() – this method is used for sending the email (check the parameters),
  • init_form_fields() – this method is used to register form fields.

Creating a Custom WooCommerce Email

Let’s now jump right into creating a custom WooCommerce Email. If you’re looking to implement this into your own plugin, just replace the paths for your own plugin. I’ll create a new plugin folder custom-wc-email and also a file inside of it custom-wc-email.php.

WooCommerce provides a lot of Customer Emails but your site only sends an email to the administrator or the provided recipient when an order is canceled. Such email is not sent to customers. We will create a custom WooCommerce email that will also notify the customer when an order was canceled.

Let’s create additional folders in our plugin. Create two folders emails and templates. We will also go one more step further and inside of the folder templates create a new folder emails. Then inside of that folder, create another one plain.

The folder templates will hold email templates inside of the subfolder emails. Plain templates will be located under plain.

Registering a Custom WooCommerce Email

To register a custom WooCommerce Email, we will create the main plugin class where we will hook into the WooCommerce emails and define the absolute path to the plugin folder.

For now, your site will not work if you have activated this plugin. That’s because we have yet to create the custom email.

Define the Custom WooCommerce Email

Create a file class-wc-customer-cancel-order.php. This file will contain all the code we will create here. Let’s define the __construct method first.

In the constructor method, we define the default values to attributes. We then hook on two actions where the order can be cancelled. When the order is cancelled, we will call the method trigger.

We are also setting the relative and absolute paths to templates.

Trigger Method

The trigger method is not an inherited method and we need to define it ourselves. This method will accept the Order ID which is passed through the action hooks. We will then get the order and use the billing email as a recipient email.

Overriding the Content Methods

We also need to override the content methods which are used to get the HTML and plain templates.

We are using the function wc_get_template_html where we pass the relative path to the email templates. We also pass the absolute path to the folder where the path to email templates is located. Since the email templates that we are using are copied from the admin cancelled email, we are also passing the required parameters.


The last thing is to define the templates that are going to be used for creating the email content. The first template will be an HTML template. Create a file wc-customer-cancelled-order.php inside templates/emails/.

With this hooks, WooCommerce will fill the required data since the hooks are the same as for the WooCommerce Admin Cancelled email. The plain template will go into templates/emails/plain. We will use the same file name wc-customer-cancelled-order.php.

The Code

Here is the complete code which you can download and test it on your own.

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member


With one custom WooCommerce email (or more) you can enhance the user experience of your plugin. This can be emails on subscriptions, bookings, rentals or anything else. Some solutions won’t require such emails, but with this knowledge you can now enhance the experience of your own clients also or even suggest such custom emails where needed.

Have you ever tried working with custom WooCommerce emails? Do you maybe have an idea where such emails could be also used?

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.


  1. Hello, I followed this guide exactly but cannot get it to work. I didn’t receive an email notice when my order is cancelled. I can see and edit “Cancelled Order to Customer” from WP Admin > WooCommerce > Settings > Emails. I tried disabling the default Cancelled Order notice sent to admins but nothing.

    Has updates to WooCommerce caused a change in how a custom email could be made?


    1. It should work without issues. This might happen if you’re sending to and receiving from the same email (SMTP). Could that be the case?


  2. What if I need to send the email only to the recipients which are added in the backend.

    Because I created a new custom email which needs to be triggered on a form submission. So, I need to send an email notification to the shop manager with form data.


    1. You will retrieve the recipients in the trigger method.


  3. Hi. i suppose it’s “add_filter” in the constructor instead of “add_action” since its a filter and not a hook i.e. add_filter( ‘woocommerce_email_classes’, array( $this, ‘register_email’ ), 90, 1 );


  4. Thanks for the guide! I liked the idea of creating the Custom_WC_Email class to register custom emails but then letting those emails define their own spec inside the WC_Email extension methods.

    One thing to note is that the “woocommerce_email_classes” hook will not run without the core WC_Emails classes loading. If you aren’t doing something that isn’t already a usecase for transactional emails in WC, the class in this example that extends WC_Email won’t load either as WC_Emails is often lazy-loaded. (See https://github.com/woocommerce/woocommerce/issues/19572)

    For example, in our case we are sending a custom email leveraging WC_Email that isn’t even tied to an order or transaction, just a UX step in our site.
    We are able to load WC_Emails by calling WC()->mailer() which will then run the “woocommerce_email_classes” hook.

    Then we can immediately trigger the custom email by running:
    do_action(‘some_custom_email_hook’, $args);

    This could be may more robust by some autoloading helper that would call WC()->mailer() if needed and only when needed by checking if the necessary classes exist at runtime.


  5. Hello,

    The snippet labelled as “class.php” – does this get placed in plugin directory as class.php? or is this to be placed in funtions.php?

    I see the first snippet which is supposed to be placed in file “custom-wc-email.php” is labelled as “plugin.php” in github snippet, so this futher adds to the confusion. Can you please clarify?


    1. Hi Michael, don’t mind the snippet names. Those are just to keep me organized when writing the tutorials. You can put the whole code in the custom-wc-email.php file.


  6. Hi, thank you for the guide. However, I’ve the following error :
    ERROR Please set some HTML first

    I don’t understand because I’ve the same files as you.

    Do you see an issu for that ?

    Thank you


Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.