WooCommerce introduced a new class-based implementation for emails. Now, add your own custom email types to WooCommerce. I’ll create a sample custom email that’s sent when an order with expedited shipping is received. A lot of larger sites disable new order emails if they receive a lot of orders, but most will still want to be aware of orders that need to be shipped immediately. Feel free to skip to the completed plugin if you want to simply use it as a base for your own custom email.

1st Step: Add a folder to your site’s wp-content/plugins directory named woocommerce-expedited-order-email. Fire up your favorite text editor or IDE and then create a blank PHP file named woocommerce-expedited-order-email.php. Now add this code to the file and save:

<?php
/**
 * Plugin Name: WooCommerce Custom Expedited Order Email
 * Plugin URI: https://godaddy.com/garage/how-to-add-a-custom-woocommerce-email/
 * Description: Demo plugin for adding a custom WooCommerce email that sends admins an email when an order is received with expedited shipping
 * Author: GoDaddy
 * Author URI: http://godaddy.com
* Version: 0.1 * * License: GNU General Public License v3.0 * License URI: http://www.gnu.org/licenses/gpl-3.0.html * */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

If this is your first time attempting this, congratulations on successfully crafting your inaugural WordPress plugin. We won’t delve further into the intricacies of plugin development in the remainder of this article. If you’re eager to explore this topic in greater detail, your best starting point is “Writing a Plugin” in the WP Codex. To bring your creation to life, navigate to the Plugins page in the WordPress admin and activate your plugin. Hooray, it’s alive! Regrettably, it doesn’t perform any functions just yet. Deactivate the plugin and continue reading to learn more.

WooCommerce loads all the default emails inside the WC_Emails class. These class names are run through a the woocommerce_email_classes filter, which allows us to add our own custom email class, or even remove default ones that aren’t needed. We’re going to add a custom one using a simple function:

/**
 *  Add a custom email to the list of emails WooCommerce should load
 *
 * @since 0.1
 * @param array $email_classes available email classes
 * @return array filtered available email classes
 */
function add_expedited_order_woocommerce_email( $email_classes ) {

    // include our custom email class
    require( 'includes/class-wc-expedited-order-email.php' );

    // add the email class to the list of email classes that WooCommerce loads
    $email_classes['WC_Expedited_Order_Email'] = new WC_Expedited_Order_Email();

    return $email_classes;

}
add_filter( 'woocommerce_email_classes', 'add_expedited_order_woocommerce_email' );

Step 2: Add this code to your woocommerce-expedited-order-email.php after the above section. This simply adds our custom email class to the list of emails that WooCommerce loads. Note that if you tried to activate and run the plugin, you’ll get a fatal error because we haven’t actually created our custom email class yet. If you don’t quite understand how this works, read this article on using filters.

Now the real fun begins! We’re going to build our custom email class that will handle the actual email content as well as the trigger for when it should be sent. Create a new folder named includes inside the existing woocommerce-expedited-order-email folder and add a new blank PHP file named class-wc-expedited-order-email.php. Add this code which will act as a very basic skeleton:

<?php

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * A custom Expedited Order WooCommerce Email class
 *
 * @since 0.1
 * @extends WC_Email
 */
class WC_Expedited_Order_Email extends WC_Email {


} // end WC_Expedited_Order_Email class

Step 3: This code creates a simple email class that extends the abstract WC_Email, which gives us access to all of the parent email class methods & members. We’ll override some of them to make the class specific to our needs. Note that the following code should all go inside the class we just created above. Let’s start with the constructor:

/**
     * Set email defaults
     *
     * @since 0.1
     */
    public function __construct() {

        // set ID, this simply needs to be a unique name
        $this->id = 'wc_expedited_order';

        // this is the title in WooCommerce Email settings
        $this->title = 'Expedited Order';

        // this is the description in WooCommerce email settings
        $this->description = 'Expedited Order Notification emails are sent when a customer places an order with 3-day or next day shipping';

        // these are the default heading and subject lines that can be overridden using the settings
        $this->heading = 'Expedited Shipping Order';
        $this->subject = 'Expedited Shipping Order';

        // these define the locations of the templates that this email should use, we'll just use the new order template since this email is similar
        $this->template_html  = 'emails/admin-new-order.php';
        $this->template_plain = 'emails/plain/admin-new-order.php';

        // Trigger on new paid orders
        add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
        add_action( 'woocommerce_order_status_failed_to_processing_notification',  array( $this, 'trigger' ) );

        // Call parent constructor to load any other defaults not explicity defined here
        parent::__construct();

        // this sets the recipient to the settings defined below in init_form_fields()
        $this->recipient = $this->get_option( 'recipient' );

        // if none was entered, just use the WP admin email as a fallback
        if ( ! $this->recipient )
            $this->recipient = get_option( 'admin_email' );
    }

This configuration establishes the email parameters and includes a title and description that will appear under WooCommerce > Settings > Emails. It also specifies a default heading and subject for the email and outlines the templates employed during email transmission. Many of these default settings mirror those of the standard new order email. To complete the setup, it defines the triggers for when the email should be dispatched. In our case, we’re simply sending the email when an order transitions from the “pending” or “failed” status to the “processing” status. Let’s now implement the “trigger” method, which is responsible for actually sending the email.

/**
     * Determine if the email should actually be sent and setup email merge variables
     *
     * @since 0.1
     * @param int $order_id
     */
    public function trigger( $order_id ) {

        // bail if no order ID is present
        if ( ! $order_id )
            return;

        // setup order object
        $this->object = new WC_Order( $order_id );

        // bail if shipping method is not expedited
        if ( ! in_array( $this->object->get_shipping_method(), array( 'Three Day Shipping', 'Next Day Shipping' ) ) )
            return;

        // replace variables in the subject/headings
        $this->find[] = '';
        $this->replace[] = date_i18n( woocommerce_date_format(), strtotime( $this->object->order_date ) );

        $this->find[] = '';
        $this->replace[] = $this->object->get_order_number();

        if ( ! $this->is_enabled() || ! $this->get_recipient() )
            return;

        // woohoo, send the email!
        $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
    }

This is the pivotal moment! Within this method, we supply the Order ID, which we utilize to create a new instance of the WC_Order. This object allows us to verify whether the shipping method is set to “expedited.” In this illustration, we’re employing a straightforward flat rate shipping method, but you could just as easily verify the shipping ID if FedEx or UPS were the chosen options. If the shipping method isn’t marked as “expedited,” we issue a return statement, preventing the email from being dispatched. We’re not quite done with the class at this point; there’s still the task of defining the content to be used in the email:

/**
     * get_content_html function.
     *
     * @since 0.1
     * @return string
     */
    public function get_content_html() {
        ob_start();
        woocommerce_get_template( $this->template_html, array(
            'order'         => $this->object,
            'email_heading' => $this->get_heading()
        ) );
        return ob_get_clean();
    }


    /**
     * get_content_plain function.
     *
     * @since 0.1
     * @return string
     */
    public function get_content_plain() {
        ob_start();
        woocommerce_get_template( $this->template_plain, array(
            'order'         => $this->object,
            'email_heading' => $this->get_heading()
        ) );
        return ob_get_clean();
    }

These elements are duplicated from the default Admin New Order email since we’re employing the exact same template. In case you were using a custom template, these methods serve as assistants, allowing you to transfer any necessary data to the custom template. It’s important to observe that, in this instance, they are passing both the order object and the email heading string.

Lastly, we must establish the configurations for the email, allowing administrators to conveniently modify recipients, subject lines, headings, or even deactivate the email if desired. Once more, this code is borrowed from the default Admin New Order email class.

/**
     * Initialize Settings Form Fields
     *
     * @since 0.1
     */
    public function init_form_fields() {

        $this->form_fields = array(
            'enabled'    => array(
                'title'   => 'Enable/Disable',
                'type'    => 'checkbox',
                'label'   => 'Enable this email notification',
                'default' => 'yes'
            ),
            'recipient'  => array(
                'title'       => 'Recipient(s)',
                'type'        => 'text',
                'description' => sprintf( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', esc_attr( get_option( 'admin_email' ) ) ),
                'placeholder' => '',
                'default'     => ''
            ),
            'subject'    => array(
                'title'       => 'Subject',
                'type'        => 'text',
                'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->subject ),
                'placeholder' => '',
                'default'     => ''
            ),
            'heading'    => array(
                'title'       => 'Email Heading',
                'type'        => 'text',
                'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->heading ),
                'placeholder' => '',
                'default'     => ''
            ),
            'email_type' => array(
                'title'       => 'Email type',
                'type'        => 'select',
                'description' => 'Choose which format of email to send.',
                'default'     => 'html',
                'class'       => 'email_type',
                'options'     => array(
                    'plain'     => 'Plain text',
                    'html'      => 'HTML', 'woocommerce',
                    'multipart' => 'Multipart', 'woocommerce',
                )
            )
        );
    }

You can add your own settings here by following the same array format as above. And with that, we’re finished! Head over to the Plugins page and click “Activate”. Assuming you haven’t made any errors, you should see “plugin activated”. Go to WooCommerce > Settings > Emails and you should see our new email added:
woocomerce expideted order email

Woohoo! There’s a lot more to the WooCommerce email system and I encourage you to read through the different email types on the WooCommerce repository to more fully understand them.

The completed plugin from the walkthrough above is available on Github, or you can just download a zip.

Similar Posts

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments