Filter out unwanted order item meta data from Woocommerce email notifications Filter out unwanted order item meta data from Woocommerce email notifications wordpress wordpress

Filter out unwanted order item meta data from Woocommerce email notifications


Try the following without any guarantee (as I don't really have the real necessary keys):

add_filter( 'woocommerce_order_item_get_formatted_meta_data', 'unset_specific_order_item_meta_data', 10, 2);function unset_specific_order_item_meta_data($formatted_meta, $item){    // Only on emails notifications    if( is_admin() || is_wc_endpoint_url() )        return $formatted_meta;    foreach( $formatted_meta as $key => $meta ){        if( in_array( $meta->key, array('Qty Selector', 'Qty', 'Total') ) )            unset($formatted_meta[$key]);    }    return $formatted_meta;}

Code goes in function.php file of your active child theme (active theme). Tested with other meta data than yours and works. I hope it will work for you too.

Now, the hook used with this code is the right filter hook. It's located in the WC_Order_Item method get_formatted_meta_data() and allows to filter the order item meta data.


There is a bug with the accepted answer, and all of the other snippets that I've found around the internet, so I'm posting my own answer here in the hopes that stores around the world don't accidentally leak information.

The problem is that when you use the Order actions meta box to resend the email, the filter check fails because is_admin() === true.

The order actions is a meta box down the side of the Orders page:

enter image description here

So the first time, when the order is created, it filters the email like you want, but then if an admin resends the email to a customer then it will be broken and show all of the meta fields to the user in the resent email.

The code that fixes this scenario is this:

$is_resend = isset($_POST['wc_order_action']) ?  wc_clean( wp_unslash( $_POST['wc_order_action'] ) ) === 'send_order_details' : false;if ( !$is_resend && (is_admin() || is_wc_endpoint_url() ) ) {  return $formatted_meta;}

So if you look at the linked snippet then you will see the meta box adds that field to the $_POST. It has to be cleaned up like that as well or it won't match.

The full example integrated into the accepted solution's answer is:

add_filter( 'woocommerce_order_item_get_formatted_meta_data', 'unset_specific_order_item_meta_data', 10, 2);function unset_specific_order_item_meta_data($formatted_meta, $item){    // Only on emails notifications    $is_resend = isset($_POST['wc_order_action']) ?  wc_clean( wp_unslash( $_POST['wc_order_action'] ) ) === 'send_order_details' : false;    if ( !$is_resend && (is_admin() || is_wc_endpoint_url() ) ) {      return $formatted_meta;    }    foreach( $formatted_meta as $key => $meta ){        if( in_array( $meta->key, array('Qty Selector', 'Qty', 'Total') ) )            unset($formatted_meta[$key]);    }    return $formatted_meta;}


I hear, that you want to show the Order Item Meta Data in the admin backend only. That's actually a tricky one. I have played around for some hours but no solution I have found, guarentee that the Order Itema Meta Data doesn't show up in e-mails to the customer.

The thing is that there are several ways these e-mails are fired (eg. through the resend meta box (which @rtpHarry mentions) or by changing order status either at the order overview, the single order view or an automatic/programmatically order status change). That gives many cases where it's neccessary to unset the Order Item Meta Data - you need to find all cases except the admin backend.

Therefore, my suggestion is to first completely remove the Order Item Meta Data using the above mentioned woocommerce_order_item_get_formatted_meta_data filter and then add them again using an action like woocommerce_before_order_itemmeta which ONLY fires in the admin backend. Because the Order Item Meta Data is unset you cannot use the get_formatted_meta_data method to get the data. Instead you can use the function wc_get_order_item_meta.

Complete code (tested and works):

//Hide 'Qty Selector', 'Qty' and 'Total' completelyadd_filter( 'woocommerce_order_item_get_formatted_meta_data', 'unset_specific_order_item_meta_data');function unset_specific_order_item_meta_data($formatted_meta){    foreach( $formatted_meta as $key => $meta ){        if( in_array( $meta->key, array('Qty Selector', 'Qty', 'Total') ) )            unset($formatted_meta[$key]);    }        return $formatted_meta;}//Add 'Qty Selector', 'Qty' and 'Total' in the admin backend onlyadd_action('woocommerce_before_order_itemmeta', 'add_specific_order_item_meta_data_in_backend', 10, 2);function add_specific_order_item_meta_data_in_backend( $item_id, $item ) {    //Only applies for line items    if( $item->get_type() !== 'line_item' ) return;        $qty_sel_lines = wc_get_order_item_meta($item_id, 'Qty Selector', false);    $qty_lines = wc_get_order_item_meta($item_id, 'Qty', false);    $total_lines = wc_get_order_item_meta($item_id, 'Total', false);        foreach ($qty_sel_lines as $qty_sel_line){        echo $qty_sel_line . '<br>';    }        foreach ($qty_lines as $qty_line){        echo $qty_line . '<br>';    }        foreach ($total_lines as $total_line){        echo $total_line. '<br>';    }}

Note:If you need to add the Order Item Meta Data to the admin e-mails, you need to do that seperately. I have not examined the options on that.