Different WooCommerce Email Header based on custom field value

I’m trying to change my email header based on order custom field “delivery type” to help staff in a shop determine whether an order is for delivery or collection, they would like the email header to be colour coded.

There are couple of useful posts here explaining how to unbind the WooCommerce email header and then effectively either add the call to the email-header.php template manually in every email template (new order, processing etc.) or use switch statements to apply a new header based on the email type.

I am trying to customize the email-header.php template based on some custom order meta data, for New Order email notification.

At the moment I’m doing this in the admin-new-order.php template, but because you have to unset/unbind the header globally you’d have to add the call to the email-header.php template manually for each mail type/template.

Based on Woocommerce different headers for each email types answer code, Here is my code attempt:

add_action( 'init', 'replace_email_header_hook' );

function replace_email_header_hook(){
    remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
    add_action( 'woocommerce_email_header', 'woocommerce_email_header', 10, 2 );
}

function woocommerce_email_header( $email_heading, $email ) {

    $order = $email->object;

    $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;

    $del_type = get_post_meta( $order_id, 'delivery_type', true );

    switch($email->id) {
    case 'new_order':
        if ($del_type == 'delivery') {

            $template = 'emails/email-header-alt.php';

        }

        else if ($del_type == 'pickup') {


                $template = 'emails/email-header.php';


            }
        break;
    default:
        $template = 'emails/email-header.php';
    }
    wc_get_template( $template, array( 'email_heading' => $email_heading ) );
}

The issue seems related to $order_id variable when trying to get it from the Order object within this hook and I’m not sure if this is possible.

Answer

The main error in your code is else if which should be elseif instead and you should rename your custom function woocommerce_email_header differently.

There is no issue with $email->object, which is the WC_Order object. You can get the Order Id using $email->object->get_id() 5if needed).

Also your code can be simplified and optimized since WooCommerce 3. Try the following instead:

add_action( 'init', 'customizing_woocommerce_email_header' );
function customizing_woocommerce_email_header(){
    remove_action( 'woocommerce_email_header', array( WC()->mailer(), 'email_header' ) );
    add_action( 'woocommerce_email_header', 'custom_email_header', 10, 2 );
}

function custom_email_header( $email_heading, $email ) {
    $template = 'email-header.php'; // Default template

    if ( 'new_order' === $email->id && 'delivery' === $email->object->get_meta( 'delivery_type' ) ) {
        $template = 'email-header-alt.php'; // Custom template
    }
    wc_get_template( 'emails/'.$template, array( 'email_heading' => $email_heading ) );
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.