WooCommerce Email Subject Line Generator
Rewrite WooCommerce email subject lines and headings in code, with the placeholders each email supports and the filter names that match.
<?php
/**
* WooCommerce email subjects and headings.
*
* The filter name carries the email ID, so a typo there is a filter that
* never runs rather than an error.
*/
/**
* Subject for the customer_processing_order email.
*
* @param string $subject Current subject.
* @param WC_Order $object The order, or the user for account emails.
* @param WC_Email $email The email object.
* @return string
*/
function my_store_customer_processing_order_subject( $subject, $object, $email ) {
$text = __( 'Thanks {customer_first_name}, order #{order_number} is on its way', 'my-store' );
// format_string() is what turns {order_number} into the number.
return $email->format_string( $text );
}
add_filter( 'woocommerce_email_subject_customer_processing_order', 'my_store_customer_processing_order_subject', 10, 3 );
/**
* Heading for the customer_processing_order email.
*
* @param string $heading Current heading.
* @param WC_Order $object The order, or the user for account emails.
* @param WC_Email $email The email object.
* @return string
*/
function my_store_customer_processing_order_heading( $heading, $object, $email ) {
$text = __( 'Order received', 'my-store' );
return $email->format_string( $text );
}
add_filter( 'woocommerce_email_heading_customer_processing_order', 'my_store_customer_processing_order_heading', 10, 3 );
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Rewrite the subject line and heading of any WooCommerce email in code, with the placeholders still working and the filter names built correctly from the email ID.
How to use
- Pick the email by its ID. The filter name is
woocommerce_email_subject_<id>, socustomer_processing_orderandprocessing_orderare not the same thing. - Write the subject with placeholders:
{site_title},{order_number},{order_date},{customer_first_name}and{customer_full_name}on order emails. - Keep placeholder replacement on. It runs the string through the email’s own
format_string(), which is what turns{order_number}into the number. - Change the heading too where it makes sense. The subject is what people see in the inbox; the heading is the first line inside the email.
- Put the snippet in a site specific plugin. Email wording should survive a theme change.
Example
function acme_customer_processing_order_subject( $subject, $object, $email ) {
$text = __( 'Thanks {customer_first_name}, order #{order_number} is on its way', 'acme' );
// format_string() is what turns {order_number} into the number.
return $email->format_string( $text );
}
add_filter( 'woocommerce_email_subject_customer_processing_order', 'acme_customer_processing_order_subject', 10, 3 );
Without format_string() the customer receives an email whose subject literally reads {order_number}, which is the most common report about this filter.
Pitfalls
- The placeholders are per email.
{customer_first_name}exists on order emails and not on the password reset, where the object is a user rather than an order. - The old
{blogname}placeholder still works but is deprecated in favour of{site_title}. - Subject filters run for the admin emails too.
new_ordergoes to the shop manager, not the customer, and wording written for a customer reads oddly there. - These filters do not change emails that a plugin sends itself. Subscriptions, bookings and memberships each add their own email classes with their own IDs.
- Settings in WooCommerce, Emails already allow a subject per email. A filter overrides that, and the person editing the setting will not know why it has no effect.
- A very long subject is truncated by mail clients at around 60 characters on desktop and fewer on mobile. Put the useful part first.
format_string()needs the$emailargument, which means registering the filter with three arguments. With the default one,$emailis null and the call is a fatal.- Emails are sent during checkout. An error in this filter takes the order confirmation down with it.
Compatibility
woocommerce_email_subject_<id> and woocommerce_email_heading_<id> have been stable since WooCommerce 2.x and still apply in WooCommerce 8 and 9. WC_Email::format_string() and the woocommerce_email_format_string filter have been available since 3.0. Email IDs are the ones in WC_Emails::init_transactional_emails(). The generated code targets PHP 7.0 and up, and the tool runs entirely in your browser.
Frequently asked questions
Which placeholders can I use?
{site_title}, {site_address}, {order_date}, {order_number}, {customer_first_name}, {customer_last_name} and {customer_full_name} on order emails. Account emails have fewer.Why is my placeholder printing literally?
format_string(), or the filter was registered without the $email argument.Can I just use the settings screen?
How do I add my own placeholder?
woocommerce_email_format_string and replace your token. The generated snippet includes that option.