One of the great plusses of WooCommerce is the amount of thought the developers have put into customising almost every aspect of its functions. When customising the notification emails that are sent out with a new order or completed order etc., there are several approaches to take:
- WooCommerce Settings – simple control of appearance such as font colour and footer text can be accessed in WooCommerce > Settings > Emails > Email Options. However, these will apply to all notification emails, and do not offer fine-grained control.
- Template Overrides – much more sophisticated customisation of each email’s appearance is possible by copying the relevant email template from woocommerce/templates/emails/ to yourtheme/woocommerce/emails/ – you can do this from the back-end in WooCommerce > Settings > Emails > <email name>. The theme email template will now be used in place of the standard template, and can be customised to your heart’s content.
- Hooks and Filters – WooCommerce provides a wide range of hooks and filters to customise almost every aspect of the notification emails, which is useful if you want to have some programmatic control of the emails – for example, sending different new order emails to registered customers and guest checkouts. The WooCommerce documentation of these is pretty minimal so I’ve fleshed it out below:
Notification email header hooks
apply_filters( 'woocommerce_email_subject_' . $this->id, $this->format_string( $this->subject ), $this->object );
apply_filters( 'woocommerce_email_heading_' . $this->id, $this->format_string( $this->heading ), $this->object );
apply_filters( 'woocommerce_email_recipient_' . $this->id, $this->recipient, $this->object );
apply_filters( 'woocommerce_email_headers', "Content-Type: " . $this->get_content_type() . "\r\n", $this->id, $this->object );
apply_filters( 'woocommerce_email_attachments', array(), $this->id, $this->object );
$this->id can have the following values:
- new_order
- customer_processing_order
- customer_completed_order
- customer_invoice
- customer_note
- low_stock
- no_stock
- backorder
- customer_new_account
- customer_invoice_paid
For example, to change the email heading of new order emails, use:
add_filter('woocommerce_email_heading_new_order', 'my_email_heading_customisation_function', 1, 2);
Notification email appearance hooks
add_filter( 'woocommerce_email_style_inline_tags', array( $this, 'style_inline_tags' ) );
add_filter( 'woocommerce_email_style_inline_h1_tag', array( $this, 'style_inline_h1_tag' ) );
add_filter( 'woocommerce_email_style_inline_h2_tag', array( $this, 'style_inline_h2_tag' ) );
add_filter( 'woocommerce_email_style_inline_h3_tag', array( $this, 'style_inline_h3_tag' ) );
add_filter( 'woocommerce_email_style_inline_a_tag', array( $this, 'style_inline_a_tag' ) );
add_filter( 'woocommerce_email_style_inline_img_tag', array( $this, 'style_inline_img_tag' ) );
Other notification email hooks
apply_filters( 'woocommerce_email_enabled_' . $this->id, $enabled, $this->object );
Examples
Customise the admin new order email subject for registered customers only:
// Change new order email subject for registered customers function wc_change_admin_new_order_email_subject( $subject, $order ) { global $woocommerce; if ( check_user_role( 'customer' ) ) { $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES); $subject = sprintf( '[%s] New Customer Order (%s) from %s %s', $blogname, $order->get_order_number(), $order->billing_first_name, $order->billing_last_name ); } return $subject; } add_filter('woocommerce_email_subject_new_order', 'wc_change_admin_new_order_email_subject', 1, 2);
Customise the admin new order email recipient to redirect to different departments for registered customers and guest checkouts:
// Change new order email recipient for registered customers function wc_change_admin_new_order_email_recipient( $recipient, $order ) { global $woocommerce; if ( check_user_role( 'customer' ) ) { $recipient = "accounts@yourdomain.com"; } else { $recipient = "newbusiness@yourdomain.com"; } return $recipient; } add_filter('woocommerce_email_recipient_new_order', 'wc_change_admin_new_order_email_recipient', 1, 2);
How to remove product name permalink in the completed order email notification to the customer.
Need help to write some custom code to remove the elements via hooks or filters. Screenshot https://imgur.com/a/snveX
The source code https://woocommerce.github.io/code-reference/files/woocommerce-templates-emails-email-downloads.html#source-view.39
Any help?
I don’t think you can remove the link using only hooks or filters. You can do this quite easily by copying the email-downloads.php template to yourtheme/woocommerce/emails/email-downloads.php, and changing this line:
to this:
Thank you. It works. Does it get affected if Woocommerce updates plugin? I am sure when theme is changed it will not work unless updated in the child theme.
Hi Robin
I try to remove the line “In backorder: 2” / “Im Lieferrückstand: x” on the Customer Order E-Mail.
Since few Days ago i can’t find any solutions.
Can you maybe help?
Thank you
hello help please. In my purchase order before finishing I have used a plugin to place a field of biiling_
billing_local select
How can I do that when an option is selected, for example 2, send me an email to a recipient x that I will put in the code?
Great
How to hide ” purchase note ” in processing order email.?
Hi Robin,
Is there code snippet / plugin which will help identify $this->id for emails added by different plugins?
Please guide.
Thanks
I’m trying to send a customer_processing_order mail to a sub order created by WP Multi order plug in. WC automatically sends mail to the main order but not to the sub orders.
I use the following code
$mailer = WC()->mailer()->get_emails();
$mailer[‘WC_Email_Customer_Processing_Order’]->trigger($suborder_id);
This was not sending mail.
While I tracked through the code in class-wc-email-customer-processing-order.php
and class-wc-email.php
I figured out that in the public function trigger( $order_id, $order = false ) {
…
…
The following lines of code — as installed and downloaded WC (Version 4.1.0)
if ( is_a( $order, ‘WC_Order’ ) ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$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() );
}
While $this-recipient — is correctly the recipient mail of the Sub Order
and $this->is_enabled() is also true
However $this->get_recipient() returning null
$this->get_recipient() in turn as found in class-wc-email.php
public function get_recipient() {
$recipient = apply_filters( ‘woocommerce_email_recipient_’ . $this->id, $this->recipient, $this->object, $this );
$recipients = array_map( ‘trim’, explode( ‘,’, $recipient ) );
$recipients = array_filter( $recipients, ‘is_email’ );
return implode( ‘, ‘, $recipients );
}
I see that $recipient is becoming null after the call to filter hook i.e.
$this->recipient has the email ID proper
$this->id is customer_processing_order
$recipient – the return value of the apply_filter(..) function is null.
I’ve not defined any filter function.
Also out of further debugging – I defined a filter function as follows Just to track what is happening to the mail Recipient as follows: (in my theme function.php)
add_filter( ‘woocommerce_email_recipient_customer_processing_order’, ‘return_mail_id_unchanged’, 20, 2);
function return_mail_id_unchanged ($recipient, $order) {
echo ‘ Recipient in function return_mail_id_unchanged ‘ . $recipient ;
return $recipient;
}
To my surprise I see that $recipient passed to this filter function is null.
The recipient mail ID is all proper until the apply_filter() hook is called by WC
Am I doing something wrong ?
Why is WC losing the recipient mail ID after the apply_filter() hook is called
although I’ve not registered any filter function to alter the recipient mail ID ?
Please help me correct any mistake I may have in my code.
Or is this a bug with WC 4.1.0 ?
Appreciate your help.
As a workaround I’m doing the following..
I changed my filter function (although I did not want any filter function, but to workaround this issue I’m forcing a filter function)
add_filter( ‘woocommerce_email_recipient_customer_processing_order’, ‘return_mail_id_from_order’, 20, 2);
function return_mail_id_from_order ($recipient, $order) {
// This echo printing null — sice $recipient passed to this filter function itself is null
echo ‘ Recipient in function return_mail_id_unchanged ‘ . $recipient ;
// Once again Read Order billing email address and return
return $order->get_billing_email();
}
I have admin and users(subscribers) that register to the site. User’s that are registered make “Campaigns” which show up as products in the woo commerce shop. I as the admin am getting the user’s(subscriber) purchase notification emails when a purchase occurs.
Needing a solution that sends all types of order emails(cancellation, processing, refund etc) of the item being purchased to user(subscriber) that posted the campaign, the site admin and the payer.
All items “Purchased” are cash on delivery. So, what is important here, is that the user(subscriber) gets their purchase notification, and they can manually change the order status to completed. After they verify they get their cash payment.
I’m hoping you can help! Thank you so much – David
function my_function_add_recipient( $recipient, $order ) {
global $woocommerce;
$WestCoast = array('AZ','CA','CO','ID','KS','MT','NE','NV','NM','ND','OK','OR','SD','TX','UT','WA','WY');
$EastCoast = array('AL','AR','CT','DE','FL','GA','IL','IN','IA','KY','LA','ME','MD','MA','MI','MN','MS','MO','NH','NJ',
'NY','NC','OH','PA','RI','SC','TN','VT','VA','WV','WI');
if ( in_array( $order->shipping_state, $WestCoast )) {
$recipient .= ', order2@email.com';
}
else if ( in_array( $order->shipping_state, $EastCoast )) {
$recipient .= ', orders@email.com';
}
return $recipient;
}
add_filter( 'woocommerce_email_recipient_new_order', 'my_function_add_recipient', 10, 2 );
Hi Robin, can you add multiple tags in the add filter if you need to also add this for new_subcription_order recipients?
Your code looks like it should work. I think you should use elseif (one word).
thank you! I’ve fixed that. Is there some reason that the email may not be received? Its clearly showing that the other email was properly attached and that it should of been sent to the right email, but they say they did not receive it?
Emails sent from a website often don’t get through to the recipient, especially if you’re using the built-in PHP mail. It’s often wise to use a plugin to send via SMTP or a 3rd-party email service like SendGrid or MailGun.
Very helpful thank you!
Hi Robin, your post is the closest to what i’m trying to do, not been able to get it working though.
Trying to; add ‘edit product’ link to admins ‘no stock’ notifications 🙂
add_filter( ‘woocommerce_email_content_no_stock’, ‘change_stock_content’, 10, 12 );
// For No stock notification
function change_stock_content( $message, $product ) {
// HERE set your replacement email
$message = ‘product_id)) . ‘”> ‘ .get_the_title($product->product_id) . ‘‘;
return $message;
}
Hi Dev. You’ve got some errors in your code – the fourth parameter in the add_filter call should be 2, not 12; and there are some problems with your $message string. Try this:
This will create a link to the product, with the product’s title as the link text.
Hi, thank you for you text. I tried to use this code without success:
add_filter( ‘woocommerce_email_recipient_new_order’, ‘conditional_recipient_new_email_notification’, 15, 2 );
function conditional_recipient_new_email_notification( $recipient, $order ) {
if( is_admin() ) return $recipient; // (Mandatory to avoid backend errors)
## — YOUR SETTINGS (below) — ##
$targeted_id = 37; // HERE define your targeted product ID
$addr_email = ‘name@domain.com’; // Here the additional recipient
// Loop through orders items
foreach ($order->get_items() as $item_id => $item ) {
if( $item->get_variation_id() == $targeted_id || $item->get_product_id() == $targeted_id ){
$recipient .= ‘, ‘ . $addr_email;
break; // Found and added – We stop the loop
}
}
return $recipient;
Do you know tell me if I am missing something here? Thank you very much! 😉
Hi Diego
I can’t see any big problems with you code. A few possible problems:
Try this:
It did not work either. The “No closing } on the conditional_recipient_new_email_notification function.” was just a paste error of mine.
I run a ssh grep looking for “woocommerce_email_recipient_new_order” at woocommerce folder and do not find anything. I guess this filter does not exist anymore. I tried this other ones with no success too:
woocommerce_order_status_pending_to_processing_notification
add_filter( ‘woocommerce_order_status_gplsquote-req’, ‘conditional_recipient_new_email_notification’, 15, 2 );
add_filter( ‘woocommerce_thankyou_wc-gplsquote-req’, ‘conditional_recipient_new_email_notification’, 15, 2 );
add_filter( ‘gpls_woo_rfq_before_thankyou’, ‘conditional_recipient_new_email_notification’, 15, 2 );
add_filter( ‘gpls_woo_rfq_woocommerce_thankyou’, ‘conditional_recipient_new_email_notification’, 15, 2 );
Any other ideas? Really thank you for the help! 😉
The filter does exist – look here in the codex. Its name is dynamically generated with the email type, which is why it didn’t show up for your grep.
These are the possible values:
woocommerce_email_recipient_new_order
woocommerce_email_recipient_customer_processing_order
woocommerce_email_recipient_customer_completed_order
woocommerce_email_recipient_customer_invoice
woocommerce_email_recipient_customer_note
woocommerce_email_recipient_low_stock
woocommerce_email_recipient_no_stock
woocommerce_email_recipient_backorder
woocommerce_email_recipient_customer_new_account
woocommerce_email_recipient_customer_invoice_paid
I think you need to use some logging to find the problem – it really helps to debug hooks where you can’t print to the screen.
Add this to your functions.php:
Set WP_DEBUG and WP_DEBUG_LOG to true in the wp-options file.
Now you can use logging in your code, for example:
Now the value of $recipient will be written to a log in your uploads/wc-logs folder, and you can check if the logic is working correctly.
Hello,
Thanks much for listing these filter options such as woocommerce_email_recipient_customer_processing_order
I’m using WooCommerce Subscriptions and cannot find what the correct filters are for adding another email recipient to pending cancellations (meaning customer cancelled, but subscription term has not ended so it is in pending state).
I tried the following but it doesn’t seem to be recognized:
add_filter( ‘woocommerce_email_recipient_pending_cancellation_subscription’, function ( $recipients, $this_email ) {
$subscription = $this_email->object;
$recipients .= ‘,’ . $subscription->billing_email;
return $recipients;
}, 10, 2 );
Thanks for any help and the great resource!
In follow-up to my question…got it to work to add the customer to the pending cancellation email in this way:
add_filter( ‘woocommerce_subscription_status_pending-cancel’, function ( $subscription ) {
$customer_email = $subscription->get_billing_email();
$wc_emails = WC()->mailer()->get_emails();
$wc_emails[‘WCS_Email_Cancelled_Subscription’]->recipient .= ‘,’ . $customer_email;
$wc_emails[‘WCS_Email_Cancelled_Subscription’]->trigger( $subscription );
return $subscription;
} );
Hi, the above code is awesome!!
However, how can I add multiple (more than 1) additional email addresses instead?
Also, emails under current coding are sent as TO: , how can I have emails sent to the multiple additional addresses as BCC: instead?
Have been looking for help on these issues I encounter!
How do i get to send an email that have 3 variant of emails for example:
If is this country send it to example@mail.com
else if is this country send it to example1@mail.com
else is this other country send it to example3@mail.com
Try this:
Is there any solution to add a hyperlink on products for woocommerce_email_content_low_stock???
Thanks in advance
I am trying to direct orders to different email addresses based on the zip code that is entered, is that possible? If so, any help out there?
Hi Wes. If you need to target postal codes rather than states (as in the case above), just swap billing_state with billing_postcode. Then add the postal codes in the array, like:
$variable = array(‘postalcode’, ‘postalcode’, ‘postalcode’);
Hope this helps.
Anybody knows how to remove product attachments (downloadable files) in the confirmation email but to keep the pdf invoice?
Woocommerce has a field called Customer provided note:. How would you add the info in that field to the woocommerce order has shipped email?
Is it possible to show the customers userlogin on the new order email. I do not want the first and last name as all of our customers have a unique login which is used for all transactions, accounting and shipping.
Hi,
Thanks for giving an idea about hook & filters, but my query is i want to override any function which is already present in multiple class but i want only single class’s function to override with my function.
Can anyone let me know how should i call filter to denote that function which i am going to override is denoting to this specific class.
I need a very simple purchase alert email format, so that it can be data stripped and the info put into a spreadsheet.
It doesn’t need to have graphics etc, just the data arranged line-by-line.
Can anyone help please?
Hi,
Just wondering if you can help please? I am using the order status manager and want to create a “review request” email to send once my customers have received their item. I would like to be able to include a link to the product they ordered to make it easier for them but I am only given the following “placeholders”: {order_date}, {order_number}, {order_status}, {billing_first_name}, {billing_last_name}, {billing_company}, {blogname}, {site_title}.
Is there any way around this?
Many thanks,
Lisa
Hi there! I am kinda stumped here. I am trying to show the Shipping Line item in all woocommerce emails even though the shipping is $0.00.Woocommerce hides the line item as default. I would like to show it, even if it is Zero. Is there a code i could use in the themes functions.php file? Thanks in advance!
Hello,
I am using Checkout Add-Ons Editor to add additional option to collect urgent fees at checkout page.
Urgent option appeared in Emails for both Admin and client BUT checkout addons not appearing in WooCommerce Advanced Notifications email.
How to get this checkout addon field in WooCommerce Advanced Notifications email?
I think you’d need to contact WooThemes support for this one.
Hello Robin
Can you help with something?
how can i get the Category Name of the product on my Email Order Details?
For example
Category ProdName . Product . Quantity . Price
Thank you
mhornet, did you figure this out? I also seek the ability to identify category a product was added to cart from. Helpful when same product is in two categories.
Hi Robin,
Can you please help on this ,
function my_function_add_recipient( $recipient, $order ) {
global $woocommerce;
if ( $order->billing_country == ‘Oman’ ) {
$recipient .= ‘, testing@email.com‘;
}
return $recipient;
}
add_filter( ‘woocommerce_email_recipient_new_order’, ‘my_function_add_recipient’, 10, 2 );
The above code is not working as am using woocommerce 2.6.4
Thanks in advance.
First, try removing the space after the comma in your extra recipient code.
Next I would try removing the billing country condition to make sure sure this is not causing your problem.
It can be very useful to use the wc_logger function to write variable values to a log file so you can debug what’s happening.
Hello Robin
Can you help with something?
how can i get product_category on my email-order-details.php?
Hi Robin,
Thanks for the post. I thought I would post my request here as I cannot find a solution.
The backorder notifications don’t really make to much sense.
If my stock amount is 40 and the user order’s 50 items then the email is formatted as follow.
50 units of ProductSku-ProductName have been backordered in order #995.
Is there a way to show the amount of items that the order has gone past stock instead of the total quantity?
So if the user orders 50 and only 40 in stock, it would be great for the email to say:
Order #001
Product Name: Product xyz
Purchased: 50
Stock Amount: 40
Backordered: 10
Something like that would be great. Or even:
50 units of ProductSku-ProductName have been order but 10 units have been backordered in order #995.
I have gone through all of the documentation and tried to customize this to show the backorder amount instead of the full quantity but no luck.
Would you recommend doing this a certain way? Can it even be done?
Thanks for your help!
Hey Robin,
I want to disable email notification for specific product for others it’s fine to receive email notification let me know if this is possible?
Thanks
This is a tricky one as the order can contain several products. How do you decide whether or not to send the notification?
i need to attach a pdf to the woocommerce “thank you for your order” email to the customer. i’ve found a code snippet. something similar to what you suggested to jason. i have put it in the functions.php as described. it doesn’t work. the emails are sent. the orders are processed correctly. also, the customer receives pdf invoices when the order is completed. it just doesn’t send the pdf with the first email. i tried a few slightly different code snippets. also i’ve found flaws here and there (like wrong variable names), tried the orginal code, the corrected code, a few variations, with a slash between the directory call and the rest of the path, without the slash … nothing! so, any suggestions? the pdf has been uploaded before. so, it’s in an upload directory. something like “wp-content/uploads/2016/09/storename-policy.pdf”. any idea how to get there?
Hi Robin,
maybe you could help me with this. I want the mail notifications to the admin only come for non-downloadable goods. So I’ve found some example code online but this didn’t work as intended and since I’m completely new to php and WooCommerce I have quite some trouble in finding the solution. So far I’ve first disabled the notification that comes when the order is complete by using:
—
add_action( ‘woocommerce_email’, ‘unhook_those_pesky_emails’ );
function unhook_those_pesky_emails( $email_class) {
remove_action( ‘woocommerce_order_status_pending_to_completed_notification’, array( $email_class->emails[‘WC_Email_New_Order’], ‘trigger’ ) );
}
—
Then after that I wanted to check if a product is a downloadable one or not and then send a notification to the admin. But I don’t know how to really do that and had no success yet.
—
add_action(‘woocommerce_order_status_completed_notification’, ‘send_download_notification’);
function send_download_notification($order_id) {
global $woocommerce;
$order = new WC_Order($order_id);
if (!$order->has_downloadable_item()){
$mailer = $woocommerce->mailer();
$mailer->customer_invoice( $order );
}
}
—
In the if-statement I tried to send a mail directly to the admin by using another action but that didn’t work out either. Do you have any idea?
Thanks in advance,
Andi
Hello,
I am having an issue when new users register on my site, which the register form is from woocommerce, they receive a confirmation email, but I don’t on the admin end. The new accounts are indeed being created, and the user can even reply to me in their confirmation email. It’s just an initial confirmation email I don’t get when they register.
I have gone into the woocommerce settings and done everything I can to configure that but nothing works. All other forms from gravity forms are working properly once I configured the SMTP/hosting properly on my site, but this register form is the only one giving me issues
How do I fix this? Also, I really don’t know how to edit code, I am new to this so if you could please tell me exactly how to edit that would be awesome.
Thank you so much! I feel this is the article that will help me as it is quite recent and all else has failed
Hmmm, email issues are always tricky because there are so many places it can go wrong. Check:
If those don’t work, you probably need to set up some debug logging – contact me and I might be able to help.
Dear Robin,
unfortunately I had rename “billing_phone” in “billing_phone_noval” for reasons of telephone field validation in the checkout. (See http://blog.lemu.ch/woocommerce/woocommerce-checkout-allow-any-character-in-billing-phone-field/). Now, the phone number is no longer displayed in the order mail and notification mail. How can I change “billing_phone” in “billing_phone_noval” in mails?
Many thanks in advance for your efforts!!!
Hi Tim. Unfortunately, I think you’ve made your life quite difficult because you chose to rename the field instead of customising the validation. You can’t modify the email template. Try using the woocommerce_email_customer_details_fields hook:
I don’t know if this will work though…
Hi Robin,
where do I have to paste the code? In “new_order.php” or in theme´s function.php? Do I need my previous code?
In functions.php, in addition to your other code.
It does not work 🙁
This is my code, maybe you can see any mistake? THANK YOU!
add_filter( ‘woocommerce_billing_fields’ , ‘custom_override_billing_phone’, 20 );
function custom_override_billing_phone( $fields ) {
// unset billing_phone field
unset($fields[‘billing_phone’]);
// add new phone field without validation
$fields[‘billing_phone_noval’] = array(
‘label’ => __(‘Phone’, ‘woocommerce’),
‘placeholder’ => _x(”, ‘placeholder’, ‘woocommerce’),
‘required’ => true,
‘class’ => array(‘form-row-last’),
‘clear’ => true
);
return $fields;
}
add_filter( ‘woocommerce_email_customer_details_fields’, ‘wc_billing_phone_field’, 40, 3);
function wc_billing_phone_field($fields, $sent_to_admin, $order ) {
$fields[“billing_phone”][“value”] = get_post_meta( $order->id, ‘billing_phone_noval’, true );
return $fields;
}
Would you know of a way to DISABLE all WC emails sending to a Customer, if their Order Total == 0 (this hapens when a Coupon of Full Value is claimed e.g.)
ANy tips be great, Thank you!
Hi Ivan. There’s some documentation on unhooking WooCommerce emails. Try checking the order total in your hook function, then unhooking the relevant emails if it’s zero.
Hi there. This code is great. Thanks so much for posting it.
I would love to be able to do something similar to your example that changes the recipient, but since we have two store locations, I would like to use an order meta field (store_pickup) value to determine the recipient.
Any help greatly appreciated.
Hi Joe. Try this:
You can hook on other emails too by adding for example:
etc.
Hello,
I would like to use your code for:
In my check out I added a drop-down field and I ask the client to select the name of a coach that comes from a list generated by a coach portfolio. I would like the coach to receive an email when the customer’s order goes into the current stage.
Can you help me please.
Hi Real, you can hook on the woocommerce_order_status_{$status_transition[to]} action which fires when the order status changes to a certain state (e.g. processing, when the payment is completed). Something like:
Ah, that plugin is now available here:
https://schon.io/woocommerce-reply-to-customer/
And a direct alternative was posted here:
http://spigotdesign.com/change-woocommerce-new-order-reply-address-customer/
It adds the ‘reply to’ OK, but doesn’t change the ‘from’ at all.
Hi Robin – useful stuff here but I’m still confused how to change just the three orders that go to the shop (New, Cancelled and Failed Orders).
Woo currently sends orders ‘from’ Customer .
Best practice now seems to be emails ‘from’ Customer and a
‘reply-to Customer .
Can this be done easily?
By the way that Peter Hartree plugin page 404s and doesn’t seem to be available on his site of git at all now.
Oh, it didn’t like the angle brackets! Try…
Woo: ‘from’ customer (customeremail)
Best ‘from’ customer (shop.com) & ‘reply-to’ customer (customeremail)
I haven’t had a chance to look at this in detail, but does this snippet help you out?
Hi Robin – thanks for the reply.
Had a good think and play with this and for the Admin emails it is actually coming from:
shopowner (shop.com)
(It was our last cart where it came from customer (customeremail).
That snippet (hadn’t seen that before) actually makes it come from:
customer (customeremail) which as it does not match the site would be treated as spam by Gmail etc.
But because we will get hundreds (hopefully!) of orders in effect from ourselves what we need is:
customer (shop.com)
So we can instantly see in an email inbox who the order is from. And the reply-to plugin will sort out the reply,
So that snippet goes too far, but does actually change the shop name to the customer name. So just a matter of stripping it down and it will be perfect.
Thanks for the pointer!
Just made a test order on the site and can confirm that the ‘name’ function combined with the ‘reply-to’ function in a small bespoke plugin works perfectly!
Thanks Robin!
Hi!
I want to show the customer name in this field, plus a own field I made by WooCommerce Checkout Field Editor (Screenshot: http://postimg.org/image/fqw4qnmpn/)
And I also want to show the phone numbers in both Billing Address and Shipping Address
Can you help me with this? 🙂
Hi Hanna. To add fields to the Customer Details section, use the woocommerce_email_customer_details_fields filter:
To add the phone numbers to the addresses, override woocommerce/templates/emails/email-addresses.php to yourtheme/woocommerce/emails/email-addresses.php and add the numbers to the template, using the magic properties $billing_phone and $shipping_phone.
I’ve been looking for a solution to not send any emails if i do an order manually via WP Backend.
I really appreciate any kind of tips
Hi Martin. WooCommerce has some documentation on unhooking notification emails. In your hook function, you could try checking is_admin to see if the order was created in the back end. Like so:
Hey Robin,
thank you very much
Is there a filter specifically for the admin notification email for new orders? woocommerce_email_attachments only fires for customer emails.
Hi Jason. Do you want to specifically filter email attachments for the new order admin notification? If so, try something like:
where $array contains your attachments.
Tried the filter in functions.php and my custom plugin but the only solution that worked was adding the filter directly to emails/plain/admin-new-order.php:
add_filter(‘woocommerce_email_attachments’, ‘admin_woocommerce_email_attachments’, 1, 3);
function admin_woocommerce_email_attachments($attachments, $status, $order)
{
// Add PDF invoice to admin email
$order_id = $order->id;
$pdf_invoice = function_to_create_pdf($order_id);
$attachments[] = $pdf_invoice[‘pdf’];
return $attachments;
}
The problem was the filter wasn’t assigned to the correct WC_Email object unless it was in the file above.
Hey Robin,
I have a similar question. How could you make it so notifications are sent to the author of the product, the author being a variable instead of a static email address?
Thanks!
Hi George. By author do you mean the WordPress user who created the product?
Hi Robin,
I try to get the new order notification to the a field “event organizer”.
I add this and it works!
It is possibile to change the notification if a customer order from more “event organizer”?
So, to each “event organizer” send the notification to its relative product.
thanks
Have you added the “event organiser” as a custom field? If so, have you added it to the product or the order?
Hi Robin,
First of all thanks for sharing the awesome tips.
Based on Pim’s question, how would i add new email recipients to redirect to different dealers based on the customers postal code or province?
Eg.: Customer with postal code “X” places an order, the order is redirected to Dealer “Z” (based on the customers postal code or province).
Hi Robin,
I nearly come up with a solution myself:
function my_function_add_recipient( $recipient, $order ) {
global $woocommerce;
if ( $order->billing_state == 'XX' ) {
$recipient .= ', myemail@address.com';
}
return $recipient;
}
add_filter( 'woocommerce_email_recipient_new_order', 'my_function_add_recipient', 10, 2 );
Which does work if you only need to specify a single state/country. (hope this helps someone by the way)
But if i add a variable with an array of states, it won’t work.
function my_function_add_recipient( $recipient, $order ) {
global $woocommerce;
$variable = array('XX', 'YY', 'ZZ');
if ( $order->billing_state = $variable ) {
$recipient .= ', myemail@address.com';
}
return $recipient;
}
add_filter( 'woocommerce_email_recipient_new_order', 'my_function_add_recipient', 10, 2 );
Any idea? Appreciate your help.
Hi Jonathan. You need to use the in_array function to check if the billing state is in the array. Change this line:
to
Hi Robin,
Thanks for your feedback.
In the meantime i actually managed to change my code using the in_array function. I also added a check for the current user role (which comes in handy if only certain dealers should receive the notification emails based on the users states).
Jonathan, can you please help me with this? I am having the same issue. I need to have the order email goto different offices based on postal codes, ideas?
Hi Wes. If you need to target postal codes rather than states (as in the case above), just swap billing_state with billing_postcode. Then add the postal codes in the array, like:
$variable = array(‘postalcode’, ‘postalcode’, ‘postalcode’);
Hope this helps.
Hi Robin, i need help with one more thing in my plugin. How can I change the text in the footer of the email that woocommerce sends for every new order. Probably I have to hook this action “woocommerce_email_footer”, but I can’t find any example in the web
I assume you don’t want to just change the footer text for all emails in WooCommerce > Emails > Email Template > Footer Text? Then I think you either need to:
Hi Robin,
I have read the comments by now, but still can’t find solution to my problem. I have created new payment Gateway in woocommerce and it works ok, but there is one more thing to have it finished. I need to send the new order email to one more recipient except the client and the shop owner. I’ve tried to hook to ‘woocommerce_email_recipient_customer_processing_order’ and ‘woocommerce_email_recipient_new_order’ but with no success. Can you please give another direction?
Hi Maria. Try something like this:
Note the semi-colon joining the additional email address to the recipient list.
Thank you for the fast reply!
I’ve already tried this with no success. Even more, now it sends email only to the customer …
Hmmm, try changing the recipient list separator in line 4 to a comma:
Now sends emails again to the owner and the customer, but not to the additional email.
So it seems as if your PHP mailer is configured to not send to multiple recipients. Let’s try adding a BCC to the admin order headers:
Obviously change the recipient address to the one you’re using.
The solution with the ‘,’ worked, just the received mails went to the spam folder. Thank you! Thank you! Thank you!
I was reading here… yet I was unable to find the answer I am looking for. I need the product sku to show up in the New Order email. I have located the email-order-items.php file – Yet I do not know what it is that I need to change. Any chance you could point me in the right direction?
Hi Jessica. The email-order-items.php template already has the code to display the SKU here:
However, $show_sku is false (disabled) by default. To enable it, we can use the woocommerce_email_order_items_table filter in functions.php:
You can tweak other items in the table here too, such as showing a product image or a purchase note.
Hi Robin,
I need a script that provide a e-mailnotification to a specific franchiser, based on the areacode (dutch) that is filled in by the buyer in Woocommerce. Any ideas?
Hi Pim. First you’ll need to identify a hook action to trigger the email notification (e.g. order completed). In your hook function, you’ll need to retrieve the area code (post code?) from the order’s billing/shipping address. Then your function has to look up the franchiser from the area code, maybe using a table of area codes and user IDs in an array. Now you can look up the franchiser’s email address using their user ID and send a notification email.
Hi Hobin!
First I want to apologize for my English, hope you can understand me.
I’ve looked everywhere but could not find a solution.
When payment is made through bank deposit or cash, I do not receive notification, because the system only sends an email notification when identifying the payment, So I’d like to know if is there a way to send a copy (CCO) of the first message that goes to the user, to my e-mail?
Thank you in advance.
For this, I think you’d need to use the woocommerce_email_recipient_customer_processing_order hook, as for cash orders the order status is set to processing, not completed. We can’t add a cc: field to the email, but we can add ourselves to the recipient list. Try this:
Obviously, change you@youremail.com to your own email address. Let me know how you get on.
This solution seems like the closest to what I am trying to accomplish. I need to add a second recipient to the order. Example, representative. Since there are more than one it would be ideal if there is an input for them in the form. rep_email So they can add their e-mail address and when it is submitted they get the message as well. Thank you for this great post.
Where would these extra recipients’ addresses be entered?
I would have it below the billing address on check out. So it’s any valid e-mail address inputted into the form that it would go to besides the billing email address.
Here’s a good article on customising checkout fields which should get you set up. Then you can copy your notification email to the custom field value as follows:
Hello, I have searched everywhere for this with no luck, I’m hoping you may be able to help? I would like to add personalisation to my Woocommerce customer emails so that I address the customer by their first name. eg Customer Completed Order Email currently says ‘Hi there. Your recent order…..
I want to customise/personalise it so it says ‘Hi (insert first name). Your recent order…
Looking at the documentation for the WC_Order class, there is a magic property $billing_first_name which you might be able to use. Override the customer-completed-order.php template and edit the following line:
Change it to:
I am trying to make the html new order email overall text area as wide as possible when I receive it. At present a 10 item order covers 2 pages.
The box that contains the order info is 5.5 inches wide.
I think you need to override /wp-content/plugins/woocommerce/templates/emails/email-styles.php. Have a look at the CSS and make any changes you need. For example, the #wrapper class has 70px padding to the left and right – this could be reduced to fit more on the page.
Hi, please how to add to email VAT cost per line (and additional)?
Example field:
Product | Qty | Price per product | VAT | VAT fee | Total VAT per line | Total per line
Thank You
You need to override email-order-items.php. Here are some useful functions in WC_Order which will give you the values you need to add:
$order->get_item_subtotal()
$order->get_item_tax()
$order->get_item_total()
$order->get_line_subtotal()
$order->get_line_tax()
$order->get_line_total()
Don’t forget you’ll need to add extra columns to the head and footer of the table – see this post for more.
Thank You for replay. Its usefull information. My solution is:
$item ) :
$_product = apply_filters( ‘woocommerce_order_item_product’, $order->get_product_from_item( $item ), $item );
$item_meta = new WC_Order_Item_Meta( $item[‘item_meta’], $_product );
if ( apply_filters( ‘woocommerce_order_item_visible’, true, $item ) ) {
?>
<tr class="”>
<?php
// Show title/image etc
if ( $show_image ) {
echo apply_filters( 'woocommerce_order_item_thumbnail', 'get_image_id() ? current( wp_get_attachment_image_src( $_product->get_image_id(), ‘thumbnail’) ) : wc_placeholder_img_src() ) .'” alt=”‘ . __( ‘Product Image’, ‘woocommerce’ ) . ‘” height=”‘ . esc_attr( $image_size[1] ) . ‘” width=”‘ . esc_attr( $image_size[0] ) . ‘” style=”vertical-align:middle; margin-right: 10px;” />’, $item );
}
// Product name
echo apply_filters( ‘woocommerce_order_item_name’, $item[‘name’], $item );
// SKU
if ( $show_sku && is_object( $_product ) && $_product->get_sku() ) {
echo ‘ (PČ: ‘ . $_product->get_sku() . ‘)’;
}
// allow other plugins to add additional product information here
do_action( ‘woocommerce_order_item_meta_start’, $item_id, $item, $order );
// Variation
if ( $item_meta->meta ) {
echo ” . nl2br( $item_meta->display( true, true, ‘_’, “\n” ) ) . ”;
}
// File URLs
if ( $show_download_links && is_object( $_product ) && $_product->exists() && $_product->is_downloadable() ) {
$download_files = $order->get_item_downloads( $item );
$i = 0;
foreach ( $download_files as $download_id => $file ) {
$i++;
if ( count( $download_files ) > 1 ) {
$prefix = sprintf( __( ‘Download %d’, ‘woocommerce’ ), $i );
} elseif ( $i == 1 ) {
$prefix = __( ‘Download’, ‘woocommerce’ );
}
echo ” . $prefix . ‘: ‘ . esc_html( $file[‘name’] ) . ‘‘;
}
}
// allow other plugins to add additional product information here
do_action( ‘woocommerce_order_item_meta_end’, $item_id, $item, $order );
?>
get_item_total( $item );
$cena_bez_dph_za_jednotku = $cena_s_dph_za_jednotku / 1.21;
echo number_format ($cena_bez_dph_za_jednotku, 2, ‘,’, ‘.’) . ‘ Kč’;
?>
<?php
echo apply_filters( 'woocommerce_order_item_quantity_html', ' ‘ . sprintf( ‘× %s’, $item[‘qty’] ) . ‘‘, $item );
?>
get_line_subtotal($item);
$celkem_bez_dph = $celkem_s_dph /1.21;
$celkem_dph = $celkem_s_dph – $celkem_bez_dph;
echo number_format($celkem_dph, 2, ‘,’, ‘.’) . ‘ Kč’;
?>
id, ‘_purchase_note’, true ) ) ) : ?>
Glad you found a solution, and thanks for sharing it.
Hi Robin.
Is there anyway I can add a field to the new order email to pick up an atribute that i have got. Eg I have an atribute for a Composer name that i want to add to the new order email
Many Thanks
Hi Ali. I think you’ll need to override email-order-items.php i.e. copy it from /wp-content/plugins/woocommerce/templates/emails to /wp-content/themes/YOUR_THEME/woocommerce/emails. Then edit the copy and add the following just before the // File URLs comment:
Hi Robin, many thanks for the info. I have a few more queries, about adding my custom attributes (composer name) to Athens different woocommerce templates. so when a customer starts the process it shows the composer name until they have checked out. hope it makes sense. Cheers again. m
It’s out of the scope of this post, but I think you want to override /wp-content/plugins/woocommerce/templates/order/order-details.php to /wp-content/themes/YOUR_THEME/woocommerce/templates/order/order-details.php and add the attribute code like you did to the email template. As an alternative, you could also look at the woocommerce_order_item_meta_start hook.
Is their any trick or plugin to customize :-
When admin receive an e-mail from his WooCommerce site he get “customer transaction Id” instead of “Order Id”.
thanks in advance.
Do you want to replace the word “Order” with the words “Customer transaction” in the admin new order notification? If so, just override the template in WooCommerce > Settings > Emails > New order and change the following:
to
Thanks Robin Hislop.
One more question from my side is that possible when a order email goes to Administrator he gets both “Order Id” and “Transcation Id” .
Try this in your functions.php:
Hie Robin thanks for your quick reply, but this above code not working for me.
Is there any alternate solution or i am again describing my problem.
When a order is placed simultaneously an automatic E-mail sends to store admin in that email he only receive “Order ID” and I want he receive both “Order ID” and “Transaction ID” as well.
I had a look in the database and the PayPal Transaction ID field is stored with the key name “Transaction ID”, so try:
How to add product url in email new order confirmation. So when you click product name to go to product page?
Hi Mihaela. To add product urls to the notification email, you would need to override the email-order-items.php template. Copy /wp-content/plugins/woocommerce/templates/emails/email-order-items.php to /wp-content/themes/YOUR-THEME/woocommerce/emails/email-order-items.php. Now you can edit your theme’s template template to add the info you need. Change the following line:
to:
Thanks very much
Would you happen to know how to add “Reply-to” in the new order email?
So, I want to add “billing_email” as “reply-to” address in the new order email.
Thank you!
Hi Steve
This actually looks a bit tricky, as the From address is set globally for all emails. You could try this:
but I suspect the From address has already been set and there is no hook to remove it. Try my suggestion, if you have no luck there is a plugin for this.
Can i use hooks to get email notifications which are not currently possible because of the payment gateway i’m using. they doesnt support emails with woocommerce.
when a customer place an order via cash on delivery, i get the email. but when the order is made by the ‘payment gateway’, email doesn’t come.
I’ve talked with the payment gateway people but they say it’s not possible in our system.
Any suggestions how to get email?
The WooCommerce email notification system should be independent of the payment gateway i.e. the payment gateway should handle the transaction, and then update the status of the order to ‘Processing’, whereupon WooCommerce can do its stuff. So you could hook into the woocommerce_order_status_.$new_status->slug action, like this:
There’s also a woocommerce_payment_complete action which might help you.
Robin, ‘customer_processing_order’, is not in your list of usable values for $this->id.
My site is using the BACS gateway, and WooCommerce sets the default status for a new order using BACS to “on-hold”, which also isn’t in your list.
Any suggestions to attach a PDF file when the gateway is BACS? My code works only when the order’s status has been manually updated to “customer_completed_order”. But I’d like the attachment sent with the first email to the customer after they have submitted their order.
Thank you in advance.
Hi Paul, sorry for the slow reply. You’re right – I was missing a few values from my list. I’ve updated it now, but I’m not sure this is definitive.
WRT to your problem, I think you’d need to filter on ‘woocommerce_email_attachments_customer_processing_order’. In your function, you’d probably need to confirm the gateway is BACS by checking $order->payment_method;.
Robin,
Does that filter hook exist? And I really would need a hook for “on-hold”.
I solved my problem another way. I re-coded the “thankyou.php” script to display a dynamically created HTML invoice, and then using DOMPDF to create a PDF of the invoice and email it using wp_mail. Works like a charm, No plugin or hooks required.
I haven’t tried it, but there’s nothing in the filter code to suggest it wouldn’t work.
Another approach might be to hook on the woocommerce_order_status_.$new_status->slug action. So something like: