Woocommerce different headers for each email types

I use Woocommerce and I need to change email header according to its type, so that “customer-new-account.php”, “customer-processing-order.php”, “admin-new-order.php” (and so on)… they must have different header.

I’ve just copied woocommerce “emails” folder inside my child template and now I need to know how to make code changes.

Read More

Any help is appreciate. 😉
Thanks in advance.

Related posts

Leave a Reply

4 comments

  1. I believe the cleanest approach is unbind the default email header action and make your custom one. If you check any of the email templates, eg.
    /woocommerce/templates/emails/admin-new-order.php , you will see at the top that they already pass the email object as a second parameter to the action, just the default WC hooks don’t use it:

     <?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    

    So in your functions.php you can do this:

    // replace default WC header action with a custom one
    add_action( 'init', 'ml_replace_email_header_hook' );    
    function ml_replace_email_header_hook(){
        remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
        add_action( 'woocommerce_email_header', 'ml_woocommerce_email_header', 10, 2 );
    }
    
    // new function that will switch template based on email type
    function ml_woocommerce_email_header( $email_heading, $email ) {
        // var_dump($email); die; // see what variables you have, $email->id contains type
        switch($email->id) {
            case 'new_order':
                $template = 'emails/email-header-new-order.php';
                break;
            default:
                $template = 'emails/email-header.php';
        }
        wc_get_template( $template, array( 'email_heading' => $email_heading ) );
    }
    

    If you don’t need to switch whole file and just want a small change in existing header, you can pass the email type parameter into the template, just replace the bottom template inclusion by:

    wc_get_template( $template, array( 'email_heading' => $email_heading, 'email_id' => $email->id ) );
    

    and then in your header template use it as $email_id, eg:

    <?php if($email_id == 'new_order'): ?>
        <h2>Your custom subheader to appear on New Order notifications only</h2>
    <?php endif ?>
    
  2. As mentioned in the comments, I don’t think there is a way to use conditional logic on the woocommerce_email_header hook. You could go by the $header variable, but it is kind of a long string and it could change.

    First, we remove the existing email header:

    function so_27400044_remove_email_header(){
        remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
    }
    add_action( 'init', 'so_27400044_remove_email_header' );
    

    Then directly call the specific header template in your email template. For example, in the customer-invoice.php template, we can call wc_get_template() to directly load an appropriate/specific header. Assuming you’ve duplicated the email-header.php template and renamed the one for customer invoices to email-header-invoice.php it might look like this:

    <?php
    /**
     * Customer invoice email
     *
     * @author      WooThemes
     * @package     WooCommerce/Templates/Emails
     * @version     2.2.0
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit; // Exit if accessed directly
    }
    
    ?>
    
    <?php do_action( 'woocommerce_email_header', $email_heading ); ?>
    
    <?php wc_get_template( 'emails/email-header-invoice.php', array( 'email_heading' => $email_heading ) ) ; ?>
    
    <?php if ( $order->has_status( 'pending' ) ) : ?>
    

    My local set up doesn’t email so I’ve tested it with the following:

    function kia_testing(){ 
    
    $order= wc_get_order( 381 );
            ob_start();
            wc_get_template( 'emails/customer-processing-order.php', array(
                'order'         => $order,
                'email_heading' => 'some title',
                'sent_to_admin' => false,
                'plain_text'    => true
            ) );
            echo ob_get_clean();
    
    }
    add_action( 'woocommerce_before_single_product' , 'kia_testing' );
    

    I am seeing the new header being called by the modified customer-processing-order.php template.

  3. I could use a condition header using did_action function on email-header.php file in order to check which type of email was triggered.

    You can check what are the actions for each email on their class constructors. Each email have it’s own class file on woocommerce/includes/emails/ folder (i.e. woocommerce/includes/emails/class-wc-email-customer-note.php ). When checking for invoice email and new user emails, which are not triggered by add_action, you can check for $order and $user_login variables:

    if ( 0 < did_action('woocommerce_order_status_pending_to_processing_notification') || 0 >= did_action('woocommerce_order_status_pending_to_on-hold_notification') ) {
        // your specific code for this case here;
    }
    else if ( 0 < did_action('woocommerce_new_customer_note_notification') ) {
        // your specific code for this case here;
    }
    else if ( $order ) {
        echo '<p>aajast_woo_mail 7 =   invoice + customer-invoice; </p>';
    }
    else if ( $user_login ) {
        // your specific code for this case here;
    };
    
  4. I did something similar in my plugin https://wordpress.org/plugins/wc-multiple-email-recipients/.

    When using woocommerce_email_headers you can pass ID and Header as arguments.

    add_filter( 'woocommerce_email_headers', 'change_my_header_based_on_mail_type', 10, 2);
    
    // Pass ID and header as arguments which is in the scope of the filter. 
    // The ID allows us to identify the mail. Header allows us to overwrite the header. 
    
    function change_my_header_based_on_mail_type( $headers = '', $id = '') 
    {       
    
      // WooCommerce core. If the ID for notification is "New Order"
      if ($id == 'new_order') 
       {
    
        //append the following to the header
        $headers .= 'My custom output ' . "rn";
        //break;
    
       }
      // If the ID for notification is "Cancelled Order"
      if ($id == 'cancelled_order') 
       {
    
        //append the following to the header
        $headers .= 'My custom output ' . "rn";
        //break;
    return $headers;
    }