How to Get Order Id in Woocommerce_Email_Headers Hook

How to get order ID in woocommerce_email_headers hook

Updated: Added compatibility with Woocommerce version 3+

I have made some tests trying to output raw data from $order object without success. After some other tests I got now the correct order ID. I have use the code below for my test to be sure. Replace the value of $your_email by your own email. Then you will receive an email with the order ID in the header name:

function testing_hook_headers( $headers, $id, $order ) {
// The order ID | Compatibility with WC version +3
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;

$your_email = '<name@email.com>';
$headers = "To: Order Num $order_id $your_email";
return $headers;
}
add_filter( 'woocommerce_email_headers', 'testing_hook_headers', 10, 3);

So Here is your code:

function techie_custom_wooemail_headers( $headers, $email_id, $order ) {

// The order ID | Compatibility with WC version +3
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;

$email = get_post_meta( $order_id, '_approver_email', true );

// Replace the emails below to your desire email
$emails = array('eee@hotmail.com', $email);

switch( $email_id ) {
case 'new_order':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;
case 'customer_processing_order':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;
case 'customer_completed_order':
case 'customer_invoice':
$headers .= 'Bcc: ' . implode(',', $emails) . "\r\n";
break;

default:
}

return $headers;
}

add_filter( 'woocommerce_email_headers', 'techie_custom_wooemail_headers', 10, 3);

I havent test your code as it's particular, but you have the right manner to get order ID.

Woocommerce different headers for each email types

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.

WooCommerce New order email manually trigger for some products

You can put the following in your functions.php:

add_filter( 'woocommerce_email_recipient_customer_completed_order', 'your_email_recipient_filter_function', 10, 2);

function your_email_recipient_filter_function($recipient, $object) {
$recipient = $recipient . ', me@myemail.com';
return $recipient;
}

the only drawback is that the recipient will see both your address & his own in the To: field.


Alternatively, you can use the woocommerce_email_headers filter. the $object passed allows you to only apply this to the completed order email:

add_filter( 'woocommerce_email_headers', 'mycustom_headers_filter_function', 10, 2);

function mycustom_headers_filter_function( $headers, $object ) {
if ($object == 'customer_completed_order') {
$headers .= 'BCC: My name <my@email.com>' . "\r\n";
}

return $headers;
}

Taken from this answer from Ewout.

Get the customer user_id in Woocommerce email footer template

You can't get the current user in woocommerce email templates, but you can get the customer user ID from the Order.

To get the customer User ID, you can set and get some data in the $GLOBAL variable:

  • Set the data - On your active theme function.php file:
add_action( 'woocommerce_email_header', 'wc_email_user_id', 10, 2 );
function wc_email_user_id( $email_heading, $email ) {
// Set global variable data: user ID and Order ID
$GLOBALS['emails_custom_data'] = array(
'user_id' => get_post_meta( $email->object->ID, '_customer_user', true ), // Set the user ID
'order_id' => $email->object->ID, // Set the Order ID
);
}
  • Get the data - On your template file just after:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}

## --- Your custom Code start here --- ##

$refNameGlobalsVar = $GLOBALS; // Get the data
$custom_data = $refNameGlobalsVar['emails_custom_data']; // Set the data in a variable

$user_id = $custom_data['user_id']; // Get the user ID
$order_id = $custom_data['order_id']; // Get the order ID (in case of…)

// Testing output
echo '<p>The user ID is '.$user_id.' | From the Order ID: '.$order_id.'</p>';

## --- End of custom code --- ##

?>

This code is tested and works

Different WooCommerce Email Header based on custom field value

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.

Targeting specific email with the email id in Woocommerce

The wc_order_email class or function doesn't exist in WooCommerce, so I have updated your question.

What you are looking at is $email variable argument (the WC_Email current type object). It's mostly defined everywhere in templates and hooks.

To get the usable current Email ID as a variable you will simply use $email_id = $email->id

To get the current Email ID of your custom emails, you should use this code (just for testing):

add_action( 'woocommerce_email_order_details', 'get_the_wc_email_id', 9, 4 );
function get_the_wc_email_id( $order, $sent_to_admin, $plain_text, $email ) {
// Will output the email id for the current notification
echo '<pre>'; print_r($email->id); echo '</pre>';
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

You will get the following:

  • new_order
  • customer_on_hold_order
  • customer_processing_order
  • customer_completed_order
  • customer_refunded_order
  • customer_partially_refunded_order
  • cancelled_order
  • failed_order
  • customer_reset_password
  • customer_invoice
  • customer_new_account
  • customer_note

Once you get the correct email ID slug for your custom email notification you can use it on any following hook (instead of overriding email templates):

woocommerce_email_header (2 arguments: $email_heading, $email)
woocommerce_email_order_details (4 arguments: $order, $sent_to_admin, $plain_text, $email)
woocommerce_email_order_meta (4 arguments: $order, $sent_to_admin, $plain_text, $email)
woocommerce_email_customer_details (4 arguments: $order, $sent_to_admin, $plain_text, $email)
woocommerce_email_footer (1 argument: $email)

HERE an example of code where I target "New order" email notifications only:

add_action( 'woocommerce_email_order_details', 'add_custom_text_to_new_order_email', 10, 4 );
function add_custom_text_to_new_order_email( $order, $sent_to_admin, $plain_text, $email ) {
// Only for "New Order" email notifications (to be replaced by yours)
if( ! ( 'new_order' == $email->id ) ) return;

// Display a custom text (for example)
echo '<p>'.__('My custom text').'</p>';
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Tested and works.

Output product custom field in woocommerce email header

Just replace your code with follows code snippet -

add_action('woocommerce_email_header', 'wcv_ingredients_email_logo', 10, 2);
function wcv_ingredients_email_logo( $email_heading, $email ){
if($email->object){
foreach($email->object->get_items() as $item_values){
// Get the product ID for simple products (not variable ones)
$product = $item_values->get_product();
$image_id = get_post_meta( $product->get_id(), 'store_email_logo', true ); //get the image ID associated to the product
$image_src = wp_get_attachment_image_src( $image_id, 'full' )[0]; //get the src of the image - you can use 'full', 'large', 'medium', or 'thumbnail' here,
$image = '<img src="'.$image_src.'">'; //create the img element
echo $image . '<br>'; //echo the image
}
}
}


Related Topics



Leave a reply



Submit