(IN) +91-9552801437 | (USA) +1-512539-0609 hello@cloudredux.com

WooCommerce 3.0 was rolled out with lots of exciting features for end-users as well as developers. Several advancements including use of CRUD classes and others were introduced with this release to make WooCommerce more performance-friendly.

This also lead to changes in the way interaction between post types, taxonomies and related data happens. In one of our previous articles we showed you how could you (without using any plugin) add and send custom WooCommerce emails. And as we continually receive comments and requests about modifying the code to also make it compatible with WooCommerce 3.0+, I decided to quickly (yeah, I know this is very late 🙁 ) get onto this.

This tutorial has been tested to work with WooCommerce 3.0+. So, if you are looking to add and send custom emails in WooCommerce 3.0+, follow the instructions below.

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

if ( class_exists( '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' );

		// 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  = WPD_BASE_DIR . '/wc-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';

		$this->placeholders   = array(
			'{site_title}'   => $this->get_blogname(),
			'{order_date}'   => '',
			'{order_number}' => '',
		);

		// Trigger email when payment is complete
		add_action( 'woocommerce_payment_complete', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_on-hold_to_completed_notification', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_failed_to_completed_notification', array( $this, 'trigger' ) );
		add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
		
		// Call parent constructor to load any other defaults not explicity defined here
		parent::__construct();

	}

	/**
	 * Get email subject.
	 *
	 * @since  3.1.0
	 * @return string
	 */
	public function get_default_subject() {
		return __( 'XYZ Online Training Program', 'woocommerce' );
	}

	/**
	 * Get email heading.
	 *
	 * @since  3.1.0
	 * @return string
	 */
	public function get_default_heading() {
		return __( 'Welcome to Online Training Program', 'woocommerce' );
	}


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

		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();
		
			//* 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( $order_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->get_billing_email();

		}

		// Send welcome email only once and not on every order status change		
		if ( get_post_meta( $order_id, '_crwc_welcome_email_sent', true ) ) {

			return;
		}

		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->get_title() ) );

		// Set order meta to indicate that the welcome email was sent
		update_post_meta( $order_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->get_heading(),
			'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->get_heading(),
			'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',
				'desc_tip'    => true,
				'description' => sprintf( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', $this->get_subject() ),
				'placeholder' => $this->get_default_subject(),
				'default'     => ''
			),
			'heading'    => array(
				'title'       => __( 'Email Heading', 'woocommerce' ),
				'type'        => 'text',
				'desc_tip'    => true,
				'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.' ), $this->get_heading() ),
				'placeholder' => $this->get_default_heading(),
				'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'		=> $this->get_email_type_options(),
				'desc_tip'		=> true,
			)
		);
	}
		
}

endif;

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).

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();
	
	include_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->get_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. Cheers!