Customizing WooCommerce email templates can be tricky if you’re unsure where to hook your code. WooCommerce uses well-placed action hooks throughout its email templates—letting developers add content like upsell messages, order instructions, and dynamic blocks without touching core files.
This guide gives you a visual breakdown of WooCommerce email hook positions and provides developer-ready code snippets to help you extend and personalize your store’s emails efficiently.
Why Use Hooks Instead of Overriding Templates?
- No need to duplicate and manage template files
- Better compatibility with WooCommerce updates
- Easier to maintain and version in code repositories
- Great for plugin developers or child theme authors
Email Template Structure with Hooks
Here’s a hook layout inside a typical WooCommerce order email (customer_completed_order
, new_order
, etc.):
woocommerce_email_header → Email header area
woocommerce_email_before_order_table
→ Custom message or notification
[ Order table: Items, totals, etc. ]
woocommerce_email_after_order_table
→ Additional notes, recommendations
woocommerce_email_order_meta
→ Shipping method, custom order meta
woocommerce_email_customer_details
→ Billing and shipping details
woocommerce_email_footer
→ Branding, contact info, social links
Example 1: Add Message After Order Table
Let’s inject a dynamic thank-you note after the order table:
add_action( 'woocommerce_email_after_order_table', 'devguide_custom_email_note', 20, 4 );
function devguide_custom_email_note( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id === 'customer_completed_order' ) {
echo '<p style="font-size:16px; color:#3c763d;">
Thanks for your order! Use <strong>WELCOME10</strong> for 10% off next time.
</p>';
}
}
Example 2: Add Content Only for Admin’s New Order Email
Use $email->id
to conditionally hook into a specific template:
add_action( 'woocommerce_email_after_order_table', 'devguide_admin_note', 10, 4 );
function devguide_admin_note( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id === 'new_order' && $sent_to_admin ) {
echo '<p><strong>🛠 Note:</strong> This order contains custom attributes. Check before dispatch.</p>';
}
}
Example 3: Recommend a Product in Emails
Add upsell product suggestions dynamically:
add_action( 'woocommerce_email_after_order_table', 'devguide_recommended_product', 25, 4 );
function devguide_recommended_product( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id !== 'customer_completed_order' ) return;
$product_id = 123; // Change to your product ID
$product = wc_get_product( $product_id );
if ( $product ) {
echo '<hr><h3>You might also like:</h3>';
echo '<p><a href="' . get_permalink( $product_id ) . '">' . esc_html( $product->get_name() ) . '</a></p>';
}
}
Hookable Email IDs for Reference
Email Trigger | $email->id Value |
---|---|
New Order (admin) | new_order |
Cancelled Order | cancelled_order |
Failed Order | failed_order |
Customer Invoice | customer_invoice |
Order Note to Customer | customer_note |
Processing Order | customer_processing_order |
Completed Order | customer_completed_order |
Refunded Order | customer_refunded_order |
Reset Password | customer_reset_password |
New Account Registration | customer_new_account |
Use these IDs with $email->id
checks to conditionally execute logic inside your hooks.
Optional: Customize the Email Footer
Enhance branding or add social links in the footer:
add_action( 'woocommerce_email_footer', 'devguide_custom_footer', 10 );
function devguide_custom_footer() {
echo '<p style="text-align:center; font-size:14px;">
Follow us on <a href="https://twitter.com/yourhandle">Twitter</a> for updates.
</p>';
}
Want to Customize Templates Instead?
You can override templates directly via your theme:
/yourtheme/woocommerce/emails/email-order-details.php
But using hooks is safer, more maintainable, and works better for plugin-based solutions.
Summary
- Use WooCommerce email hooks to inject content into transactional emails without touching templates.
- Use
$email->id
to target specific email types. - Use
add_action()
with proper priority to control positioning. - Prefer this method over template overrides for long-term maintainability.