PHPwoocommerceadvanced

WooCommerce Custom Email Notifications

Create custom email notifications for WooCommerce events and triggers

Faisal Yaqoob
#woocommerce#email#notifications#automation#customer-service
Share this snippet:

Code

php
1// Create custom email class
2if (!class_exists('WC_Custom_Order_Email')) {
3 class WC_Custom_Order_Email extends WC_Email {
4
5 public function __construct() {
6 $this->id = 'custom_order_email';
7 $this->title = __('Custom Order Email', 'woocommerce');
8 $this->description = __('Custom email sent for special order conditions', 'woocommerce');
9 $this->template_html = 'emails/custom-order-email.php';
10 $this->template_plain = 'emails/plain/custom-order-email.php';
11 $this->template_base = get_stylesheet_directory() . '/woocommerce/';
12 $this->placeholders = array(
13 '{order_date}' => '',
14 '{order_number}' => '',
15 );
16
17 // Triggers for this email
18 add_action('woocommerce_order_status_pending_to_processing_notification', array($this, 'trigger'), 10, 2);
19 add_action('woocommerce_order_status_pending_to_completed_notification', array($this, 'trigger'), 10, 2);
20
21 // Call parent constructor
22 parent::__construct();
23
24 // Other settings
25 $this->recipient = $this->get_option('recipient', get_option('admin_email'));
26 }
27
28 /**
29 * Get email subject.
30 */
31 public function get_default_subject() {
32 return __('New order received - Order {order_number}', 'woocommerce');
33 }
34
35 /**
36 * Get email heading.
37 */
38 public function get_default_heading() {
39 return __('New Order: {order_number}', 'woocommerce');
40 }
41
42 /**
43 * Trigger the sending of this email.
44 */
45 public function trigger($order_id, $order = false) {
46 $this->setup_locale();
47
48 if ($order_id && !is_a($order, 'WC_Order')) {
49 $order = wc_get_order($order_id);
50 }
51
52 if (is_a($order, 'WC_Order')) {
53 $this->object = $order;
54 $this->placeholders['{order_date}'] = wc_format_datetime($this->object->get_date_created());
55 $this->placeholders['{order_number}'] = $this->object->get_order_number();
56 }
57
58 if ($this->is_enabled() && $this->get_recipient()) {
59 $this->send($this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments());
60 }
61
62 $this->restore_locale();
63 }
64
65 /**
66 * Get content html.
67 */
68 public function get_content_html() {
69 return wc_get_template_html(
70 $this->template_html,
71 array(
72 'order' => $this->object,
73 'email_heading' => $this->get_heading(),
74 'additional_content' => $this->get_additional_content(),
75 'sent_to_admin' => false,
76 'plain_text' => false,
77 'email' => $this,
78 ),
79 '',
80 $this->template_base
81 );
82 }
83
84 /**
85 * Get content plain.
86 */
87 public function get_content_plain() {
88 return wc_get_template_html(
89 $this->template_plain,
90 array(
91 'order' => $this->object,
92 'email_heading' => $this->get_heading(),
93 'additional_content' => $this->get_additional_content(),
94 'sent_to_admin' => false,
95 'plain_text' => true,
96 'email' => $this,
97 ),
98 '',
99 $this->template_base
100 );
101 }
102
103 /**
104 * Initialize settings form fields.
105 */
106 public function init_form_fields() {
107 $this->form_fields = array(
108 'enabled' => array(
109 'title' => __('Enable/Disable', 'woocommerce'),
110 'type' => 'checkbox',
111 'label' => __('Enable this email notification', 'woocommerce'),
112 'default' => 'yes',
113 ),
114 'recipient' => array(
115 'title' => __('Recipient(s)', 'woocommerce'),
116 'type' => 'text',
117 'description' => sprintf(__('Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce'), '<code>' . esc_attr(get_option('admin_email')) . '</code>'),
118 'placeholder' => '',
119 'default' => '',
120 'desc_tip' => true,
121 ),
122 'subject' => array(
123 'title' => __('Subject', 'woocommerce'),
124 'type' => 'text',
125 'desc_tip' => true,
126 'description' => sprintf(__('Available placeholders: %s', 'woocommerce'), '<code>{order_date}, {order_number}</code>'),
127 'placeholder' => $this->get_default_subject(),
128 'default' => '',
129 ),
130 'heading' => array(
131 'title' => __('Email heading', 'woocommerce'),
132 'type' => 'text',
133 'desc_tip' => true,
134 'description' => sprintf(__('Available placeholders: %s', 'woocommerce'), '<code>{order_date}, {order_number}</code>'),
135 'placeholder' => $this->get_default_heading(),
136 'default' => '',
137 ),
138 'additional_content' => array(
139 'title' => __('Additional content', 'woocommerce'),
140 'description' => __('Text to appear below the main email content.', 'woocommerce'),
141 'css' => 'width:400px; height: 75px;',
142 'placeholder' => __('N/A', 'woocommerce'),
143 'type' => 'textarea',
144 'default' => '',
145 'desc_tip' => true,
146 ),
147 'email_type' => array(
148 'title' => __('Email type', 'woocommerce'),
149 'type' => 'select',
150 'description' => __('Choose which format of email to send.', 'woocommerce'),
151 'default' => 'html',
152 'class' => 'email_type wc-enhanced-select',
153 'options' => $this->get_email_type_options(),
154 'desc_tip' => true,
155 ),
156 );
157 }
158 }
159}

WooCommerce Custom Email Notifications

Create custom email notifications for specific WooCommerce events like low stock alerts, abandoned carts, or custom order statuses.

// Create custom email class
if (!class_exists('WC_Custom_Order_Email')) {
    class WC_Custom_Order_Email extends WC_Email {

        public function __construct() {
            $this->id             = 'custom_order_email';
            $this->title          = __('Custom Order Email', 'woocommerce');
            $this->description    = __('Custom email sent for special order conditions', 'woocommerce');
            $this->template_html  = 'emails/custom-order-email.php';
            $this->template_plain = 'emails/plain/custom-order-email.php';
            $this->template_base  = get_stylesheet_directory() . '/woocommerce/';
            $this->placeholders   = array(
                '{order_date}'   => '',
                '{order_number}' => '',
            );

            // Triggers for this email
            add_action('woocommerce_order_status_pending_to_processing_notification', array($this, 'trigger'), 10, 2);
            add_action('woocommerce_order_status_pending_to_completed_notification', array($this, 'trigger'), 10, 2);

            // Call parent constructor
            parent::__construct();

            // Other settings
            $this->recipient = $this->get_option('recipient', get_option('admin_email'));
        }

        /**
         * Get email subject.
         */
        public function get_default_subject() {
            return __('New order received - Order {order_number}', 'woocommerce');
        }

        /**
         * Get email heading.
         */
        public function get_default_heading() {
            return __('New Order: {order_number}', 'woocommerce');
        }

        /**
         * Trigger the sending of this email.
         */
        public function trigger($order_id, $order = false) {
            $this->setup_locale();

            if ($order_id && !is_a($order, 'WC_Order')) {
                $order = wc_get_order($order_id);
            }

            if (is_a($order, 'WC_Order')) {
                $this->object                         = $order;
                $this->placeholders['{order_date}']   = wc_format_datetime($this->object->get_date_created());
                $this->placeholders['{order_number}'] = $this->object->get_order_number();
            }

            if ($this->is_enabled() && $this->get_recipient()) {
                $this->send($this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments());
            }

            $this->restore_locale();
        }

        /**
         * Get content html.
         */
        public function get_content_html() {
            return wc_get_template_html(
                $this->template_html,
                array(
                    'order'              => $this->object,
                    'email_heading'      => $this->get_heading(),
                    'additional_content' => $this->get_additional_content(),
                    'sent_to_admin'      => false,
                    'plain_text'         => false,
                    'email'              => $this,
                ),
                '',
                $this->template_base
            );
        }

        /**
         * Get content plain.
         */
        public function get_content_plain() {
            return wc_get_template_html(
                $this->template_plain,
                array(
                    'order'              => $this->object,
                    'email_heading'      => $this->get_heading(),
                    'additional_content' => $this->get_additional_content(),
                    'sent_to_admin'      => false,
                    'plain_text'         => true,
                    'email'              => $this,
                ),
                '',
                $this->template_base
            );
        }

        /**
         * Initialize settings form fields.
         */
        public function init_form_fields() {
            $this->form_fields = array(
                'enabled'    => array(
                    'title'   => __('Enable/Disable', 'woocommerce'),
                    'type'    => 'checkbox',
                    'label'   => __('Enable this email notification', 'woocommerce'),
                    'default' => 'yes',
                ),
                'recipient'  => array(
                    'title'       => __('Recipient(s)', 'woocommerce'),
                    'type'        => 'text',
                    'description' => sprintf(__('Enter recipients (comma separated) for this email. Defaults to %s.', 'woocommerce'), '<code>' . esc_attr(get_option('admin_email')) . '</code>'),
                    'placeholder' => '',
                    'default'     => '',
                    'desc_tip'    => true,
                ),
                'subject'    => array(
                    'title'       => __('Subject', 'woocommerce'),
                    'type'        => 'text',
                    'desc_tip'    => true,
                    'description' => sprintf(__('Available placeholders: %s', 'woocommerce'), '<code>{order_date}, {order_number}</code>'),
                    'placeholder' => $this->get_default_subject(),
                    'default'     => '',
                ),
                'heading'    => array(
                    'title'       => __('Email heading', 'woocommerce'),
                    'type'        => 'text',
                    'desc_tip'    => true,
                    'description' => sprintf(__('Available placeholders: %s', 'woocommerce'), '<code>{order_date}, {order_number}</code>'),
                    'placeholder' => $this->get_default_heading(),
                    'default'     => '',
                ),
                'additional_content' => array(
                    'title'       => __('Additional content', 'woocommerce'),
                    'description' => __('Text to appear below the main email content.', 'woocommerce'),
                    'css'         => 'width:400px; height: 75px;',
                    'placeholder' => __('N/A', 'woocommerce'),
                    'type'        => 'textarea',
                    'default'     => '',
                    'desc_tip'    => true,
                ),
                'email_type' => array(
                    'title'       => __('Email type', 'woocommerce'),
                    'type'        => 'select',
                    'description' => __('Choose which format of email to send.', 'woocommerce'),
                    'default'     => 'html',
                    'class'       => 'email_type wc-enhanced-select',
                    'options'     => $this->get_email_type_options(),
                    'desc_tip'    => true,
                ),
            );
        }
    }
}

Register Custom Email

// Add custom email to WooCommerce
add_filter('woocommerce_email_classes', 'register_custom_order_email');
function register_custom_order_email($email_classes) {
    // Include custom email class
    require_once 'class-wc-custom-order-email.php';

    // Add to WooCommerce email classes
    $email_classes['WC_Custom_Order_Email'] = new WC_Custom_Order_Email();

    return $email_classes;
}

Email Template (HTML)

Create file: woocommerce/emails/custom-order-email.php

<?php
/**
 * Custom Order Email (HTML)
 */

if (!defined('ABSPATH')) {
    exit;
}

do_action('woocommerce_email_header', $email_heading, $email); ?>

<p><?php printf(__('You have received a new order from %s.', 'woocommerce'), $order->get_formatted_billing_full_name()); ?></p>

<h2>
    <?php
    printf(
        __('Order #%1$s - %2$s', 'woocommerce'),
        $order->get_order_number(),
        wc_format_datetime($order->get_date_created())
    );
    ?>
</h2>

<?php do_action('woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email); ?>

<?php do_action('woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email); ?>

<?php do_action('woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email); ?>

<?php
if ($additional_content) {
    echo wp_kses_post(wpautop(wptexturize($additional_content)));
}

do_action('woocommerce_email_footer', $email);

Low Stock Alert Email

// Send email when product stock is low
add_action('woocommerce_low_stock', 'custom_low_stock_email');
function custom_low_stock_email($product) {
    $to = get_option('admin_email');
    $subject = sprintf(__('Low Stock Alert: %s', 'woocommerce'), $product->get_name());

    $message = sprintf(
        __('Product "%1$s" (ID: %2$s) is running low on stock. Current stock: %3$s', 'woocommerce'),
        $product->get_name(),
        $product->get_id(),
        $product->get_stock_quantity()
    );

    $headers = array(
        'Content-Type: text/html; charset=UTF-8',
        'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>'
    );

    wp_mail($to, $subject, $message, $headers);
}

Customer Review Request Email

// Send review request email 7 days after order completion
add_action('woocommerce_order_status_completed', 'schedule_review_request_email');
function schedule_review_request_email($order_id) {
    // Schedule email for 7 days later
    wp_schedule_single_event(
        time() + (7 * DAY_IN_SECONDS),
        'send_review_request_email',
        array($order_id)
    );
}

add_action('send_review_request_email', 'send_review_request_email_callback');
function send_review_request_email_callback($order_id) {
    $order = wc_get_order($order_id);

    if (!$order) {
        return;
    }

    $to = $order->get_billing_email();
    $subject = __('How was your recent purchase?', 'woocommerce');

    $message = '
    <html>
    <head>
        <title>' . $subject . '</title>
    </head>
    <body>
        <h2>Hi ' . $order->get_billing_first_name() . ',</h2>
        <p>Thank you for your recent purchase from ' . get_bloginfo('name') . '!</p>
        <p>We hope you\'re enjoying your products. We\'d love to hear your feedback!</p>
        <p><a href="' . get_permalink(wc_get_page_id('shop')) . '" style="background: #0073aa; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Leave a Review</a></p>
        <p>Your feedback helps us improve and helps other customers make informed decisions.</p>
        <p>Thank you,<br>' . get_bloginfo('name') . '</p>
    </body>
    </html>
    ';

    $headers = array('Content-Type: text/html; charset=UTF-8');

    wp_mail($to, $subject, $message, $headers);
}

Abandoned Cart Email

// Track abandoned carts
add_action('woocommerce_cart_updated', 'track_abandoned_cart');
function track_abandoned_cart() {
    if (!is_user_logged_in() || WC()->cart->is_empty()) {
        return;
    }

    $user_id = get_current_user_id();
    $cart_data = array(
        'cart_contents' => WC()->cart->get_cart(),
        'cart_total'    => WC()->cart->get_cart_contents_total(),
        'timestamp'     => time(),
    );

    update_user_meta($user_id, '_abandoned_cart', $cart_data);
}

// Send abandoned cart email after 1 hour
add_action('init', 'schedule_abandoned_cart_emails');
function schedule_abandoned_cart_emails() {
    if (!wp_next_scheduled('send_abandoned_cart_emails')) {
        wp_schedule_event(time(), 'hourly', 'send_abandoned_cart_emails');
    }
}

add_action('send_abandoned_cart_emails', 'send_abandoned_cart_emails_callback');
function send_abandoned_cart_emails_callback() {
    $users = get_users(array('meta_key' => '_abandoned_cart'));

    foreach ($users as $user) {
        $cart_data = get_user_meta($user->ID, '_abandoned_cart', true);

        // Check if cart was abandoned more than 1 hour ago
        if (empty($cart_data) || (time() - $cart_data['timestamp']) < 3600) {
            continue;
        }

        // Check if email was already sent
        if (get_user_meta($user->ID, '_abandoned_cart_email_sent', true)) {
            continue;
        }

        $to = $user->user_email;
        $subject = __('You left items in your cart!', 'woocommerce');

        $message = '
        <h2>Hi ' . $user->display_name . ',</h2>
        <p>We noticed you left some items in your cart.</p>
        <p>Total: ' . wc_price($cart_data['cart_total']) . '</p>
        <p><a href="' . wc_get_cart_url() . '">Complete your purchase</a></p>
        ';

        $headers = array('Content-Type: text/html; charset=UTF-8');

        if (wp_mail($to, $subject, $message, $headers)) {
            update_user_meta($user->ID, '_abandoned_cart_email_sent', true);
        }
    }
}

Send Email on Custom Event

// Send email when custom action occurs
add_action('custom_woocommerce_action', 'send_custom_notification_email', 10, 2);
function send_custom_notification_email($order_id, $custom_data) {
    $order = wc_get_order($order_id);

    $to = $order->get_billing_email();
    $subject = __('Custom Notification', 'woocommerce');

    $message = sprintf(
        __('Hello %s, this is a custom notification about your order #%s.', 'woocommerce'),
        $order->get_billing_first_name(),
        $order->get_order_number()
    );

    $headers = array('Content-Type: text/html; charset=UTF-8');

    wp_mail($to, $subject, $message, $headers);
}

Features

  • Custom Email Classes: Fully integrated with WooCommerce email system
  • Admin Settings: Configurable via WooCommerce > Settings > Emails
  • Template Support: Uses WooCommerce email templates
  • Multiple Triggers: Low stock, abandoned cart, review requests, custom events
  • Scheduled Emails: Time-delayed emails using WP Cron
  • HTML & Plain Text: Supports both email formats
  • Placeholders: Dynamic content with placeholders
  • Customizable: Full control over subject, heading, and content
  • Professional: Uses WooCommerce email styling

Dependencies

  • WooCommerce

Related Snippets