4

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.

Any help is appreciate. ;-) Thanks in advance.

Stimart
  • 418
  • 4
  • 8
  • 20
  • How will the headers be different? You can already have a different title/phrase. – helgatheviking Dec 10 '14 at 15:54
  • I need different image and/or custom text information per types. – Stimart Dec 10 '14 at 16:13
  • It is pretty easy to add actions to `woocommerce_email_header` and/or to change the header template. But I'm not seeing a way to run any conditional logic there that will recognize what kind of email is being sent. – helgatheviking Dec 10 '14 at 16:53

4 Answers4

11

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 ?>
Jan Zikmund
  • 646
  • 9
  • 19
  • Just implemented this and still works. Do you by any chance have any idea how to use this for the footer template? – Mas May 12 '21 at 14:37
  • 1
    For anybody coming across this issue: I copied content from email-footer.php and pasted it in a new footer file (admin-new-order-footer.php') and adjusted content as needed. In admin-new-order.php I replaced do_action( 'woocommerce_email_footer', $email ); with wc_get_template( 'emails/admin-new-order-footer.php', array('email_id' => $email->id ) ) ; – Mas May 14 '21 at 10:07
  • Was looking very long for this, great solution! – Loosie94 Aug 24 '23 at 12:51
3

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.

helgatheviking
  • 25,596
  • 11
  • 95
  • 152
  • Wow, it looks a great solution. Ok, I'll test it. Stay tuned... ;-) – Stimart Dec 10 '14 at 17:03
  • Well one of us should probably test it. :) Good luck. – helgatheviking Dec 10 '14 at 17:08
  • Hi @helgatheviking. It doesn't works! I think 'cause the path of "wc_get_template( 'emails/email-header-invoice.php'" set focus directly in woocommerce plugin folder. I need to get custom "email-header-invoice.php" from a child template, where I've previously created a subfolder "woocommerce/emails". How can I do that? Please, can you explain me how to also override the email footer? – Stimart Dec 10 '14 at 20:41
  • I've changed your code with: $email_heading), '/wp-content/themes/twentyfourteen/woocommerce/' ) ; ?> but it doesn't works... where am I doing wrong? – Stimart Dec 10 '14 at 21:02
  • `wc_get_template()` does *not* set focus directly on the plugin folder. `wc_locate_template()` is called which in turn calls `locate_template()` which looks first in the theme's woocommerce folder and only then falls back to the WooCommerce core template. The file is in `theme/woocommerce/emails/email-header-invoice.php`? I don't know when I'l get to test this. – helgatheviking Dec 11 '14 at 03:00
  • Yes, files are in theme folder: "theme/woocommerce/emails/..." – Stimart Dec 11 '14 at 07:59
  • Ok, I had 2 parse errors (told you I didn't test it). I don't know what happens when you are trying to email parse errors and my local setup doesn't email anyway. But I've edited to fix the errors and show how I've tested. I am seeing the new header in my test, so maybe double check and add the missing closing parens. – helgatheviking Dec 11 '14 at 14:23
  • Hi helga. Now it seems to work as expected. I'll keep you updated. However I voted your answer. Thank you so much. :-) – Stimart Dec 12 '14 at 08:01
0

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;
};
Celso Bessa
  • 180
  • 4
  • 9
0

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 ' . "\r\n";
    //break;

   }
  // If the ID for notification is "Cancelled Order"
  if ($id == 'cancelled_order') 
   {

    //append the following to the header
    $headers .= 'My custom output ' . "\r\n";
    //break;
return $headers;
} 
Con
  • 81
  • 1
  • 2
  • 7