Adding and Sending Custom WooCommerce Email (without a plugin)

WooCommerce
Featured Image: Adding and Sending Custom WooCommerce Email (without a plugin)
Share

This tut has been updated to work with WooCommerce 3.0+. Read how can you add and send custom WooCommerce email for WooCommerce version 3.0 and higher.

Emails are pretty important when you have customers purchasing products from your online store. Customers buying your products (even us, when we make an online purchase), be it physical or virtual, expect to receive some sort of emails about the confirmation of payment, the processing of order and so on. If your store fails to do so, you’re probably doing it wrong and making your business suffer. Because, the customer has just sent you his money and they’ve not yet heard back from you, they’ve not received a payment confirmation. Get the problem?

If you’re selling with WordPress & WooCommerce, things are quite easy for you as a store owner/manager. WooCommerce, by default, sends out some emails to let your customers know that their order has been placed, processed and/or is complete. However, sometimes it may happen that based on the products you’re selling, you may need to send out custom emails to the customers once they’ve placed an order on your site.

Practical Example

For instance, let’s say, you have a WordPress & WooCommerce powered online store that allows customers to purchase a course on your website and in-turn grants them access to your online training program.

In such a case, you may want to send out a Welcome Email to the customers informing them about the purchase and sharing access details for the online training program. In order to be able to do so, we’ll need to add a custom WooCommerce email that triggers every time a new order is placed on the site. WooCommerce 2.0 introduced a whole bunch of new features, including the ability to add a new class-based implementation for emails. In this article, we’ll use the WooCommerce email class implementation to add a custom email which is triggered on every new order once the payment has been received.

Side Note

The example cited above may also require custom implementation that allows interaction between WooCommerce and (possibly the API to connect to) your online training program to allow adding new user accounts when a customer makes a purchase at your online store. This article does not cover the integration to a third-party service part, and is strictly intended to guide you on how can a custom email be added and sent through your WooCommerce store.

Implementation

Duh.. Enough Talk! Let’s Implement That

Implementation of custom email is divided into three phases:

  1. Extending WC_Email class to define the email header, subject, email template for content, etc.
  2. Adding our custom email class to the default WooCommerce email classes using woocommerce_email_classes filter
  3. Creating our own email template to be used to generate email content for our custom email.

Let’s get started.

First things first!

It is highly recommended that any customization be kept separate from the theme. A plugin like WP Designer could come in handy if you want to add such a customization. This example requires you to FTP into your website and create custom directories and files inside wp-content > uploads directory. Following is a list of directories and files that need to be created:

  1. Create directory crwc-custom-emails inside wp-content > uploads.
  2. Create file crwc-email-functions.php in the root of crwc-custom-emails directory (crwc-custom-emails > crwc-email-functions.php).
  3. Create file class-crwc-welcome-email.php in the root of crwc-custom-emails directory (crwc-custom-emails > class-crwc-welcome-email.php).
  4. Create a sub-directory emails inside crwc-custom-emails directory.
  5. Create a new file crwc-welcome-email.php inside the emails directory (crwc-custom-emails > emails > crwc-welcome-email.php).
  6. You can also choose to create a sub-directory plain inside emails directory and then create crwc-welcome-email.php file inside plain directory (crwc-custom-emails > emails > plain > crwc-welcome-email.php). This will be used in case emails use plain content-type.

Building custom email class

The custom email class that we create would actually define the email trigger plus the email content. We can extend the default WC_Email class and hence make use of all of the parent email class methods & members that are available. This makes life really easy 😉

Add the following code to class-crwc-welcome-email.php file.

<?php

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

/**
 * Welcome Email class used to send out welcome emails to customers purchasing a course
 *
 * @extends \WC_Email
 */

class CRWC_Welcome_Email extends WC_Email {
	
	/**
	 * Set email defaults
	 */
	public function __construct() {

		// Unique ID for custom email
		$this->id = 'crwc_welcome_email';

		// Is a customer email
		$this->customer_email = true;
		
		// Title field in WooCommerce Email settings
		$this->title = __( 'Welcome Email', 'woocommerce' );

		// Description field in WooCommerce email settings
		$this->description = __( 'Welcome email is sent when an online training program account is created for the customer after the purchase of the online course.', 'woocommerce' );

		// Default heading and subject lines in WooCommerce email settings
		$this->subject = apply_filters( 'crwc_welcome_email_default_subject', __( 'XYZ Online Training Program', 'woocommerce' ) );
		$this->heading = apply_filters( 'crwc_welcome_email_default_heading', __( 'Welcome to Online Training Program', 'woocommerce' ) );
		
		// 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
		$upload_dir = wp_upload_dir();
		
		$this->template_base  = $upload_dir['basedir'] . '/crwc-custom-emails/';	// Fix the template base lookup for use on admin screen template path display
		$this->template_html  = 'emails/crwc-welcome-email.php';
		$this->template_plain = 'emails/plain/crwc-welcome-email.php';

		// Trigger email when payment is complete
		add_action( 'woocommerce_payment_complete', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_on-hold_to_processing', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_on-hold_to_completed', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_failed_to_processing', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_failed_to_completed', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_pending_to_processing', array( $this, 'trigger' ) );
		
		// Call parent constructor to load any other defaults not explicity defined here
		parent::__construct();

	}


	/**
	 * Prepares email content and triggers the email
	 *
	 * @param int $order_id
	 */
	public function trigger( $order_id ) {

		// Bail if no order ID is present
		if ( ! $order_id )
			return;
		
		// Send welcome email only once and not on every order status change		
		if ( ! get_post_meta( $order_id, '_crwc_welcome_email_sent', true ) ) {
			
			// setup order object
			$this->object = new WC_Order( $order_id );
			
			// get order items as array
			$order_items = $this->object->get_items();

			//* Maybe include an additional check to make sure that the online training program account was created
			/* Uncomment and add your own conditional check
			$online_training_account_created = get_post_meta( $this->object->id, '_crwc_user_account_created', 1 );
			
			if ( ! empty( $online_training_account_created ) && false === $online_training_account_created ) {
				return;
			}
			*/

			/* Proceed with sending email */
			
			$this->recipient = $this->object->billing_email;

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

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

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

			// All well, send the email
			$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
			
			// add order note about the same
			$this->object->add_order_note( sprintf( __( '%s email sent to the customer.', 'woocommerce' ), $this->title ) );

			// Set order meta to indicate that the welcome email was sent
			update_post_meta( $this->object->id, '_crwc_welcome_email_sent', 1 );
			
		}
		
	}
	
	/**
	 * get_content_html function.
	 *
	 * @return string
	 */
	public function get_content_html() {
		return wc_get_template_html( $this->template_html, array(
			'order'			=> $this->object,
			'email_heading'		=> $this->email_heading( $this->course_info['program'] ),
			'sent_to_admin'		=> false,
			'plain_text'		=> false,
			'email'			=> $this
		) );
	}


	/**
	 * get_content_plain function.
	 *
	 * @return string
	 */
	public function get_content_plain() {
		return wc_get_template_html( $this->template_plain, array(
			'order'			=> $this->object,
			'email_heading'		=> $this->email_heading( $this->course_info['program'] ),
			'sent_to_admin'		=> false,
			'plain_text'		=> true,
			'email'			=> $this
		) );
	}


	/**
	 * 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',
				'default' => 'yes'
			),
			'subject'    => array(
				'title'       => __( 'Subject', 'woocommerce' ),
				'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', 'woocommerce' ),
				'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', 'woocommerce' ),
				'type'        => 'select',
				'description' => __( 'Choose which format of email to send.', 'woocommerce' ),
				'default'       => 'html',
				'class'         => 'email_type wc-enhanced-select',
				'options'     => array(
					'plain'	    => __( 'Plain text', 'woocommerce' ),
					'html' 	    => __( 'HTML', 'woocommerce' ),
					'multipart' => __( 'Multipart', 'woocommerce' ),
				)
			)
		);
	}
		
}

Viewing custom email settings

The code mentioned above will help us to create custom class with all settings and triggers. However, to be able to see the custom email settings that we created along with the default emails on WooCommerce Emails screen under WooCommerce > Settings > Emails, we’ll need to add this class to the default email classes in WooCommerce. In order to do that, we’ll make use of the woocommerce_email_classes filter to include custom email class to the default classes.

Add the following code to crwc-email-functions.php file (inside crwc-custom-emails directory).

<?php

add_filter( 'woocommerce_email_classes', 'crwc_custom_woocommerce_emails' );

function crwc_custom_woocommerce_emails( $email_classes ) {

	//* Custom welcome email to customer when purchasing online training program

	$upload_dir = wp_upload_dir();
	
	require_once( $upload_dir['basedir'] . '/crwc-custom-emails/class-crwc-welcome-email.php' );
	$email_classes['CRWC_Welcome_Email'] = new CRWC_Welcome_Email(); // add to the list of email classes that WooCommerce loads


	return $email_classes;
	
}

Now, when you navigate to WooCommerce > Settings > Emails, you should be able to see the custom email Welcome Email that we added to the list of emails on that page. If you click on the Configure button, you will find settings screen that allows you to enable/disable the email, edit/update the email subject and heading and choose the email content type since we added these settings in the custom class we created above.

Creating custom email template

Until this point, we have been able to create email class that helps create email trigger and set-up email content and we have also been able to add our custom email to the WooCommerce Emails screen. We still need to define the email template that will be used for the email content. The paths to the email content templates have already been defined in the custom email class we created above. Let’s add the actual content that will be used by the welcome email we send out to customers.

Add the following code to crwc-welcome-email.php file (inside emails directory).

<?php
/**
 *
 * Welcome email content template
 *
 * The file is prone to modifications after plugin upgrade or alike; customizations are advised via hooks/filters
 *
 */
 
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * @hooked WC_Emails::email_header() Output the email header
 */
do_action( 'woocommerce_email_header', $email_heading, $email ); ?>

<p><?php _e( 'Thank you for your purchase of Online training course. Your account has been successfully created over the Online Training Program portal.', 'woocommerce' ); ?></p>

<p><?php _e( 'Use the following credentials to login to the portal:', 'woocommerce' ); ?></p>

<p>
	<strong><?php __( 'Login URL: ', 'woocommerce' ) ?></strong><?php _e( 'https://example.com' ); ?><br />
	<strong><?php __( 'Username: ', 'woocommerce' ) ?></strong><?php echo make_clickable( esc_attr( $order->billing_email ) ); ?><br />
</p>

<p><?php _e( 'Below are the order details for your reference.' ) ?></p>

<?php
/**
* @hooked WC_Emails::order_details() Shows the order details table.
* @hooked WC_Emails::order_schema_markup() Adds Schema.org markup.
* @since 2.5.0
*/
do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email );

/**
* @hooked WC_Emails::order_meta() Shows order meta data.
*/
do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email );

/**
* @hooked WC_Emails::customer_details() Shows customer details
* @hooked WC_Emails::email_address() Shows email address
*/
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );

/**
 * @hooked WC_Emails::email_footer() Output the email footer
 */
do_action( 'woocommerce_email_footer', $email );

You can modify the email content template as required based on your specific requirements and accordingly, the details that you’d need to send out to your customers.

Start making Custom WooCommerce email work

We’re almost there with starting to send custom WooCommerce emails to the customers. All we need to do is to trigger our code. The filter we added to include our custom email class to list of default email classes is placed in crwc-email-functions.php, but hey!, wait a sec.. did we actually include it so that it is executed by WordPress? No, not yet. Let’s do that.

In order to do so, you can just add the following code to your theme’s functions.php:

$upload_dir = wp_upload_dir();

include_once( $upload_dir['basedir'] . '/crwc-custom-emails/crwc-email-functions.php' );

That’s it! Now on, when a customer purchases an online training product from your store, he would receive a welcome email with his credentials. Sounds good, right? Happy customers, happy you!

This tut has been updated to work with WooCommerce 3.0+. Read how can you add and send custom WooCommerce email for WooCommerce version 3.0 and higher.