The Problem

One of my clients uses the emails from WooCommerce to run his business.  He uses the admin interface some, but not much.  Because he relies so heavily on the emails,  he wants specific information in the subject of the email.  That way he can decide how to deal with it just by looking at the subject in his list of incoming mail.

Originally, and by default, the subject for a new order looks like this:

[Client Company] New customer order (5327) – January 17, 2019

He wants something like this:

12/10/2018      clientcompany      Customer order  (5306)     Joe Blow   Company

In order to get as much real information as possible on the subject line,  I proposed this:

12-10-2018 clientcompany – Order 5306 – Joe Blow – Company

If you only have one online storefront, you don’t really need the name of the store in the subject.  My client has a few storefronts, so he needs to know which one is the source of the order. Note that the date uses dashes rather than slashes.  The dashes are a standard format in PHP.  You will see where that came from below.

Built in Options

WooCommerce has some options for modifying the subject from within the admin interface.  Find it at: WooCommerce > Settings > Emails. Then click on the name of the email you want to modify – in this case “New order.” The default for ‘Subject’ looks like:  [{site_title}] New Customer order ({order_number}) – {order_date}.  You can’t directly edit the default, but you can type over it.  Unfortunately the only options for data are site title, order number, and order date.

Near the bottom of the ‘New order’ admin page is a section title ‘HTML’ that provides an option for editing the email template.  This template is the layout for the body of the email and doesn’t provide a way to modify the email subject.

How to Make the Changes

So far, I haven’t mentioned a method that will do what we want.  WooCommerce does have a way that is noted at: docs.woocommerce.com/document/change-email-subject-lines/ Unfortunately you will need to be able to read the code to figure out what to do to make  work.  Here’s how it works and what to do:

Create a Child Theme

First, be sure you have a child theme set up.  If you don’t know how to do that, there are WordPress plugins that make it easy.  For example Child Theme Configurator. Your child theme folder is located among your WordPress files at /wp-content/themes/yourtheme-child.  The child theme folder holds files that you don’t want to change when you update your main theme.  Wordpress checks these files and uses them instead of, or in addition to, the standard files for your theme.  If you modify the basic theme in some way, this is where you put the modified files.

Create a Child functions.php

We are going to modify the functions.php file from the base theme we are using.  We do that by adding a new function to an empty file that we save in the yourtheme-child directory.  When WordPress runs,  it uses all the functions in the functions.php file in the base theme plus all the functions in the child functions.php file.

Content for Child functions.php

The WooCommerce documentation mentioned above gives you the code for your new function.  First,  however add this to the top of your new child functions.php file in a separate line so that WordPress knows it is looking at php code: <?php  Then copy the code from the documentation and paste it into your new functions.php file.

At this point the content of your functions.php file looks like this:

<?php

/*
* goes in theme functions.php or a custom plugin
*
* Subject filters:
* woocommerce_email_subject_new_order
* woocommerce_email_subject_customer_processing_order
* woocommerce_email_subject_customer_completed_order
* woocommerce_email_subject_customer_invoice
* woocommerce_email_subject_customer_note
* woocommerce_email_subject_low_stock
* woocommerce_email_subject_no_stock
* woocommerce_email_subject_backorder
* woocommerce_email_subject_customer_new_account
* woocommerce_email_subject_customer_invoice_paid
**/
add_filter(‘woocommerce_email_subject_new_order’, ‘change_admin_email_subject’, 1, 2);
function change_admin_email_subject( $subject, $order ) {
global $woocommerce;
$blogname = wp_specialchars_decode(get_option(‘blogname’), ENT_QUOTES);

$subject = sprintf( ‘[%s] New Customer Order (# %s) from Name %s %s’, $blogname, $order->id, $order->billing_first_name, $order->billing_last_name );

return $subject;
}

Note that the lines with asterisks (*) are comments and don’t affect the code.

Modifying the Code

We want to modify the email subject.  What appears in the subject is what is stored in the variable $subject in this statement:

$subject = sprintf( ‘[%s] New Customer Order (# %s) from Name %s %s’, $blogname, $order->id, $order->billing_first_name, $order->billing_last_name );

This code produces a subject that looks like this: [Client Company] New customer order (5306)  from Name Joe Blow

The sprintf statement includes five elements separated by commas.  The first is a string that incorporates the other elements into it using %s to load the other four elements in order.  Those other four elements are variables pulled from the information about the order that is stored in your database.  In my example:

$blogname = Client Company

$order->id = 5306

$order->billing_first_name = Joe

$order->billing_last_name = Blow

We still want to use all these variables, but we also need to use the name of the company ordering the items and the date of the order.  We can get the company name, if any, from: $order->billing_company.

We get the order date with this code: $order->get_date_created()->format (‘m-d-Y’).  By default this returns both the date and time, something like this: 2018-12-10T05:36:25+00:00. Fortunately WooCommerce has a function set up that allows us to format the date that is returned.  The format (‘m-d-Y’) code tells WooCommerce to return the date formatted like 12-10-2018, without the time.  For the tech details see: docs.woocommerce.com/wc-apidocs/class-WC_DateTime.html and php.net/manual/en/function.date.php.

Revised sprintf Statement

To get the result we want, the statement needs to look like this:

$subject = sprintf(‘%s %s – Order %s – %s %s – %s’, $order->get_date_created()->format (‘m-d-Y’), $blogname, $order->id, $order->billing_first_name, $order->billing_last_name, $order->billing_company);

Producing, for example:

12-10-2018 clientcompany –  Order  5306 – Joe Blow –  Company

Conclusion

I don’t get into code very much anymore, so I had to experiment a bit to get the desired result.  My client’s website is very actively making sales and I didn’t want to break it while messing around.  I have a duplicate of my client’s site on my server that I can use to test things without affecting his store.  Turns out that was a good idea because I was able to crash my playground site just by messing up the code in the sprint line. If you need to make a backup site on a separate server see: codex.wordpress.org/Moving_WordPress (Changing Your Domain Name and URLs).

In  a nutshell, we aren’t moving the site, just copying it.  So,  don’t change anything on the original site.  Move all the WordPress files to a directory on your server, export the database from the client installation, create a new database on your server and import the data.  Edit wp-config.php on the new server with the new database name and login credentials.  Nothing will work yet because the database points to the old server in numerous places.  I used the Search and Replace Script to clean up the database so that everything works like the original site.