Marketing

WooCommerce Email Hooks: 2025 Guide

Transactional emails are a critical touchpoint in the customer journey. They aren't just receipts; they are opportunities to build brand trust, provide value, and encourage future purchases. The default WooCommerce emails are functional, but they lack the personality and branding that set a store apart. That's where WooCommerce email hooks come in.

For web development professionals, understanding and utilizing these hooks is an essential skill. They provide the power to transform generic notifications into highly-customized, branded, and effective communication tools without altering the core plugin files. This guide will provide a comprehensive overview of WooCommerce email hooks, from simple content additions to complex conditional logic. We’ll explore both action and filter hooks, complete with practical, real-world examples you can implement in your projects today.

What Are WooCommerce Hooks?

Before diving into the specifics of email hooks, it’s important to understand the concept of hooks in the WordPress and WooCommerce ecosystem. Hooks are specific points in the code where developers can “hook” in their own custom functions to add or modify functionality. This is the foundation of WordPress’s flexibility, allowing for extensive customization without editing core files, which is a critical best practice.

There are two main types of hooks:

  1. Action Hooks: These allow you to do something at a specific point. When it comes to emails, you use action hooks to add new content, such as a promotional banner, care instructions, or a personalized thank-you message. The function you write for an action hook doesn’t return a value; it simply executes.
  2. Filter Hooks: These allow you to change something. Filter hooks are used to modify existing data before it’s displayed or used. For emails, this could mean changing the subject line, adding a recipient, or altering the CSS styles. A function hooked to a filter always accepts a variable, modifies it, and then must return it.

A Better Way: Why Professionals Choose Send by Elementor

Before diving into the technical details of hooks, consider the modern alternative. While hooks are a developer’s tool for making specific modifications, Send by Elementor is a complete communication toolkit designed for web creators to deliver business results.

Instead of writing PHP snippets for each customization, Send provides a visual, no-code builder that allows you to redesign all your WooCommerce emails with a simple drag-and-drop interface. This dramatically speeds up development and makes the process more intuitive.

More importantly, Send goes beyond basic email styling. It’s a fully integrated platform for:

  • Email & SMS Automation: Create powerful workflows like abandoned cart reminders, welcome series, and post-purchase follow-ups directly within WordPress.
  • Boosting Client Value: Help your clients increase sales and customer retention with professional marketing tools.
  • Unlocking Recurring Revenue: Offer email marketing and automation as a managed service, creating long-term partnerships and sustainable income for your business.

For web professionals looking to provide maximum value with minimum complexity, Send by Elementor is the superior choice. It empowers you to achieve more than what’s possible with hooks, in a fraction of the time.

Getting Started: How to Safely Add Custom Code

To use WooCommerce email hooks, you need a safe and reliable place to add your PHP code snippets. Directly editing your theme’s functions.php file is risky, as any updates to the theme will overwrite your changes. Here are the two recommended methods for adding custom code.

Method 1: Use a Child Theme (Recommended)

A child theme inherits the look, feel, and functionality of another theme, the “parent theme.” It’s the industry-standard way to modify a WordPress theme. You can add your custom code to the functions.php file of your child theme, and it will remain untouched when the parent theme is updated.

If you don’t already have a child theme set up, you can easily create one. Many theme developers provide one, or you can use a plugin to generate it. Once activated, you can access its functions.php file by navigating to Appearance > Theme File Editor in your WordPress dashboard and selecting your child theme.

Method 2: Use a Code Snippets Plugin

For those who prefer to keep customizations separate from the theme, a code snippets plugin is an excellent alternative. These plugins provide a user-friendly interface for adding, managing, and organizing your PHP snippets directly from the WordPress dashboard. This method avoids the need to interact with theme files directly and makes it easy to activate or deactivate specific snippets as needed. A popular and reliable choice is the “Code Snippets” plugin.

For the remainder of this guide, the provided code examples can be placed in either your child theme’s functions.php file or a code snippets plugin.

Action Hooks: Adding Custom Content to Emails

Action hooks are your tool for injecting new elements and information into your WooCommerce emails. Let’s explore the most useful action hooks, categorized by their location in the email template.

Most of the functions you’ll hook into these actions will accept up to four arguments:

  • $order: The WC_Order object, which contains all the information about the order.
  • $sent_to_admin: A boolean (true or false) that indicates if the email is being sent to the store admin.
  • $plain_text: A boolean that indicates if the email is the plain text version.
  • $email: The WC_Email object itself, which can be useful for accessing email-specific properties.

Global Email Hooks (Affect All Emails)

These hooks allow you to add content to the header and footer of every single WooCommerce email, making them perfect for consistent branding.

woocommerce_email_header

This hook fires right after the opening <head> and <body> tags of the email template. It’s ideal for adding a custom logo or a branded banner image.

Example: Add a Custom Header Banner

add_action( 'woocommerce_email_header', 'add_custom_email_header_banner', 10, 2 );

function add_custom_email_header_banner( $email_heading, $email ) {
    // Don't add the banner to plain text emails
    if ( $email->is_plain_text() ) {
        return;
    }
    
    // URL to your banner image
    $banner_url = 'https://yourstore.com/path/to/your/email-banner.jpg';
    
    echo '<div style="text-align:center; margin-bottom: 20px;">';
    echo '<img src="' . esc_url( $banner_url ) . '" alt="' . get_bloginfo( 'name' ) . '" style="width:100%; max-width:600px; height:auto;" />';
    echo '</div>';
}

woocommerce_email_footer

This hook fires just before the closing </body> tag, making it the perfect place for social media links, a link to your return policy, or other important footer information.

Example: Add Social Media Links to the Footer

add_action( 'woocommerce_email_footer', 'add_social_links_to_email_footer', 10, 1 );

function add_social_links_to_email_footer( $email ) {
    // Don't add to plain text emails
    if ( $email->is_plain_text() ) {
        echo "\n\nFollow us on Facebook: https://facebook.com/your-page\nFollow us on Instagram: https://instagram.com/your-page";
        return;
    }
    ?>
    <div style="text-align: center; padding-top: 20px; border-top: 1px solid #E0E0E0; margin-top: 20px;">
        <p style="margin:0 0 10px 0;">Follow Us!</p>
        <a href="https://facebook.com/your-page" style="margin: 0 5px;"><img src="https://path.to/facebook-icon.png" width="32" height="32" alt="Facebook"></a>
        <a href="https://instagram.com/your-page" style="margin: 0 5px;"><img src="https://path.to/instagram-icon.png" width="32" height="32" alt="Instagram"></a>
        <a href="https://twitter.com/your-page" style="margin: 0 5px;"><img src="https://path.to/twitter-icon.png" width="32" height="32" alt="Twitter"></a>
    </div>
    <?php
}

Order-Specific Email Hooks

These hooks allow you to add content to the body of the order emails, which is where you can provide the most value to the customer.

woocommerce_email_before_order_table

This hook executes right before the main order details table. It’s a prime location for a personalized thank-you message or important pre-order information.

Example: Add a Personalized Thank You Message

add_action( 'woocommerce_email_before_order_table', 'add_personalized_thank_you_message', 10, 4 );

function add_personalized_thank_you_message( $order, $sent_to_admin, $plain_text, $email ) {
    // Only for customer emails
    if ( $sent_to_admin ) {
        return;
    }
    
    $first_name = $order->get_billing_first_name();
    
    if ( $plain_text ) {
        echo "Hi " . $first_name . ",\n\nThank you for your order! We're getting it ready for you. Here are the details:\n\n";
    } else {
        echo '<h2>Hi ' . $first_name . ',</h2>';
        echo '<p>Thank you for your order! We appreciate your business and are excited to get your items to you. You can find the details of your purchase below.</p>';
    }
}

woocommerce_email_after_order_table

As the name suggests, this hook fires immediately after the order details table. It’s perfect for upselling, cross-selling, providing care instructions, or sharing a discount code for a future purchase.

Example: Add a Coupon Code for a Future Purchase

add_action( 'woocommerce_email_after_order_table', 'add_next_purchase_coupon', 10, 4 );

function add_next_purchase_coupon( $order, $sent_to_admin, $plain_text, $email ) {
    // Only for the 'Completed Order' email sent to the customer
    if ( ! $sent_to_admin && $email->id === 'customer_completed_order' ) {
        $coupon_code = 'THANKYOU15'; // Make sure this coupon exists in WooCommerce
        
        if ( $plain_text ) {
            echo "\n\nAs a thank you, use code " . $coupon_code . " for 15% off your next order!";
        } else {
            echo '<div style="margin-top: 30px; padding: 20px; background-color: #f7f7f7; border: 1px dashed #ccc; text-align: center;">';
            echo '<h3>A Gift For You!</h3>';
            echo '<p>As a special thank you for your purchase, please enjoy 15% off your next order with the code below.</p>';
            echo '<p style="font-size: 18px; font-weight: bold; color: #555;">' . $coupon_code . '</p>';
            echo '</div>';
        }
    }
}

woocommerce_email_order_details

This hook gives you more granular control within the order table itself. It runs after the main order details have been output but before the closing tags of the section. It can be used to add extra details about the order as a whole.

Example: Display the Payment Method Used

add_action( 'woocommerce_email_order_details', 'display_payment_method_in_email', 5, 4 );

function display_payment_method_in_email( $order, $sent_to_admin, $plain_text, $email ) {
    $payment_method_title = $order->get_payment_method_title();
    
    if ( $payment_method_title ) {
        if ( $plain_text ) {
            echo "\nPayment Method: " . $payment_method_title;
        } else {
            echo '<p><strong>Payment Method:</strong> ' . $payment_method_title . '</p>';
        }
    }
}

woocommerce_email_customer_details

This hook fires after the customer’s billing and shipping addresses. It’s a great place to add extra customer-related information, like a VAT number or a note about their account.

Example: Add a Link to the “My Account” Page

add_action( 'woocommerce_email_customer_details', 'add_my_account_link_to_emails', 25, 4 );

function add_my_account_link_to_emails( $order, $sent_to_admin, $plain_text, $email ) {
    if ( ! $sent_to_admin && is_user_logged_in() ) {
        if ( $plain_text ) {
            echo "\n\nYou can view your order details and manage your account here: " . wc_get_page_permalink( 'myaccount' );
        } else {
            echo '<p>You can view your past orders, manage your addresses, and more in your <a href="' . esc_url( wc_get_page_permalink( 'myaccount' ) ) . '">My Account</a> area.</p>';
        }
    }
}

woocommerce_email_order_meta

This hook allows you to add custom meta data to the order emails. It’s often used to display information collected from custom checkout fields.

Example: Display a Custom Checkout Field (e.g., “Delivery Instructions”)

First, you would need a custom field at checkout. Let’s assume you’ve created one with the meta key _delivery_instructions.

add_action( 'woocommerce_email_order_meta', 'add_delivery_instructions_to_emails', 10, 4 );

function add_delivery_instructions_to_emails( $order, $sent_to_admin, $plain_text, $email ) {
    $delivery_instructions = get_post_meta( $order->get_id(), '_delivery_instructions', true );

    if ( ! empty( $delivery_instructions ) ) {
        if ( $plain_text ) {
            echo "\n\nDelivery Instructions: " . $delivery_instructions;
        } else {
            echo '<h3>Delivery Instructions</h3>';
            echo '<p>' . wp_kses_post( $delivery_instructions ) . '</p>';
        }
    }
}

Filter Hooks: Modifying Email Data

Filter hooks are essential for changing the default content and behavior of WooCommerce emails. Remember, any function attached to a filter must return a value.

Modifying Email Recipients

One of the most common requirements is to send order notifications to additional people, such as a supplier, a warehouse manager, or an accountant.

The hooks for this follow a consistent pattern: woocommerce_email_recipient_{email_id}.

  • woocommerce_email_recipient_new_order
  • woocommerce_email_recipient_cancelled_order
  • woocommerce_email_recipient_failed_order
  • woocommerce_email_recipient_customer_completed_order (Note: Modifying the customer email recipient should be done with caution).

Example: Add a BCC Recipient to New Order Emails

This example sends a blind carbon copy of the “New Order” email to the accounting department.

add_filter( 'woocommerce_email_recipient_new_order', 'add_bcc_recipient_for_new_orders', 10, 2 );

function add_bcc_recipient_for_new_orders( $recipient, $order ) {
    // Add your BCC email address here
    $bcc_email = '[email protected]';
    $recipient .= ', bcc:' . $bcc_email;
    
    return $recipient;
}

Example: Send New Order Emails to Different Addresses Based on Product Category

This advanced example demonstrates sending the new order notification to a specific supplier if the order contains a product from their category.

add_filter( 'woocommerce_email_recipient_new_order', 'conditional_supplier_email_recipient', 10, 2 );

function conditional_supplier_email_recipient( $recipient, $order ) {
    if ( ! $order instanceof WC_Order ) {
        return $recipient;
    }

    $items = $order->get_items();
    $supplier_a_email = '[email protected]';
    $supplier_b_email = '[email protected]';
    
    $send_to_supplier_a = false;
    $send_to_supplier_b = false;

    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        if ( has_term( 'supplier-a-category', 'product_cat', $product_id ) ) {
            $send_to_supplier_a = true;
        }
        if ( has_term( 'supplier-b-category', 'product_cat', $product_id ) ) {
            $send_to_supplier_b = true;
        }
    }

    if ( $send_to_supplier_a ) {
        $recipient .= ',' . $supplier_a_email;
    }
    if ( $send_to_supplier_b ) {
        $recipient .= ',' . $supplier_b_email;
    }

    return $recipient;
}

Modifying Email Subjects and Headings

Personalizing the subject line and heading can significantly improve open rates and brand perception. The hooks for these also follow a predictable pattern:

  • woocommerce_email_subject_{email_id}
  • woocommerce_email_heading_{email_id}

Example: Personalize the “Completed Order” Subject Line

add_filter( 'woocommerce_email_subject_customer_completed_order', 'personalize_completed_order_subject', 10, 2 );

function personalize_completed_order_subject( $subject, $order ) {
    $first_name = $order->get_billing_first_name();
    // The default subject is "Your {site_title} order is now complete"
    // Let's change it to be more personal.
    $new_subject = sprintf( 'Great news, %s! Your %s order has shipped!', $first_name, get_bloginfo( 'name' ) );
    
    return $new_subject;
}

Example: Customize the “New Order” Heading for Admins

add_filter( 'woocommerce_email_heading_new_order', 'customize_admin_new_order_heading', 10, 2 );

function customize_admin_new_order_heading( $heading, $order ) {
    // The default is "New customer order"
    $new_heading = sprintf( 'New Order (#%s) - Total: %s', $order->get_order_number(), $order->get_formatted_order_total() );
    
    return $new_heading;
}

Modifying Email Content and Styles

For more advanced content manipulation, you can use filters.

woocommerce_email_get_content_{email_id}

This filter allows you to completely override the content of a specific email. This is a powerful but blunt instrument. Use it with care, as you will be responsible for generating all the HTML content.

woocommerce_email_styles

This filter gives you control over the inline CSS styles applied to WooCommerce emails. You can use it to change colors, fonts, and spacing to better match your brand identity.

Example: Change the Primary Color of Emails

add_filter( 'woocommerce_email_styles', 'change_woocommerce_email_colors', 10, 2 );

function change_woocommerce_email_colors( $css, $email ) {
    // Your brand's primary color
    $brand_color = '#7A5CFA';
    
    // Find and replace the default WooCommerce green color
    $css = str_replace( '#7f54b3', $brand_color, $css );
    
    return $css;
}

Putting It All Together: Conditional Logic

The true power of hooks is unlocked when you combine them with conditional logic. This allows you to create highly targeted and relevant email customizations. You can use any data from the $order object to create your conditions.

Here are a few common conditional checks:

  • By Payment Gateway: $order->get_payment_method()
  • By Shipping Method: $order->get_shipping_method()
  • By Order Total: $order->get_total()
  • By Product/Category: Loop through $order->get_items() as shown in a previous example.

Example: Add BACS/Bank Transfer Details Only When Needed

This example uses an action hook to add bank transfer details to the “Order on-hold” email, but only if the customer selected that specific payment method.

add_action( 'woocommerce_email_before_order_table', 'add_bank_details_for_bacs_orders', 10, 4 );

function add_bank_details_for_bacs_orders( $order, $sent_to_admin, $plain_text, $email ) {
    // Only for 'customer_on_hold_order' email and for the customer
    if ( $sent_to_admin || $email->id !== 'customer_on_hold_order' ) {
        return;
    }

    // Only for 'bacs' payment method
    if ( $order->get_payment_method() === 'bacs' ) {
        if ( $plain_text ) {
            echo "To complete your order, please make a payment to the following bank account:\nAccount Name: Your Company\nAccount Number: 12345678\nSort Code: 12-34-56\nPlease use your Order ID as the payment reference.";
        } else {
            echo '<h2>Payment Instructions</h2>';
            echo '<p>Thank you for your order. To finalize your purchase, please transfer the total amount to our bank account using the details below. Please use your Order ID as the payment reference.</p>';
            echo '<ul>';
            echo '<li><strong>Account Name:</strong> Your Company</li>';
            echo '<li><strong>Account Number:</strong> 12345678</li>';
            echo '<li><strong>Sort Code:</strong> 12-34-56</li>';
            echo '</ul>';
        }
    }
}

Troubleshooting Common Issues

When working with PHP and hooks, you might encounter a few issues.

  • The White Screen of Death: This usually means a fatal PHP error. Check your code for syntax errors like missing semicolons or brackets. If you have access to your server’s error logs, they will pinpoint the exact problem.
  • Changes Not Appearing:
    • Caching: Clear all levels of caching—your browser, any caching plugins, and your hosting provider’s cache.
    • Hook Priority: Another function might be running after yours and overwriting your changes. Try increasing the priority of your hook (the number in the add_action or add_filter call). A lower number runs earlier. For example, add_action( 'hook_name', 'your_function', 5 ); will run before the default priority of 10.
    • Wrong Hook: Double-check that you are using the correct hook for the specific email and location you want to modify.

Conclusion: Taking Control of Your Communications

Mastering WooCommerce email hooks is a powerful skill for any web professional. It allows you to move beyond the default templates and create a truly branded and effective communication strategy for your clients’ stores. By using a combination of action and filter hooks, you can add valuable information, reinforce brand identity, and ultimately improve the customer experience.

While manually coding these customizations provides ultimate flexibility, it’s also true that managing dozens of snippets can become complex. For projects requiring extensive and dynamic email workflows, a dedicated email customization tool can provide a more streamlined interface, often with visual builders and pre-built logic, simplifying the entire process. The key is to choose the right approach for the project’s needs, and now, with a deep understanding of hooks, you have the power to do just that.

Want to learn more?
Subscribe to our Newsletter.

By submitting your details, you agree to receive Elementor emails, including marketing emails, and to our Terms of Service & Privacy Policy.

You may also like

Get Started

It's easy to get overwhelmed by the sheer number of digital marketing strategies vying for your attention these days. But don't worry! Email marketing remains a tried-and-true method. It's more than just sending messages; it's about connecting with your audience, turning interest into sales, and ultimately growing your business.

Get Started

In the bustling world of e-commerce, where competition is fierce, and customer attention spans are fleeting, building a strong email list is no longer just a good idea—it's an absolute necessity. Think of your email list as your digital goldmine, a direct line to connect with your audience, nurture relationships, and drive sales. For ecommerce store owners, this is especially crucial.

Grow Your Audience
Choosing the right marketing tools can define your business's growth trajectory. With email marketing consistently delivering strong results, selecting the best mass email service is a critical decision. 
Marketing
As a web professional, you pour your skills into building stunning, functional websites for your clients. But what happens after the site goes live? The real journey of turning visitors into loyal customers begins. 

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *