I am trying to modify the product images in the auto generated WooCommerce order e-mails. Note, I am trying to do this with hooks, rather than creating a modified e-mail template.
To start, I have a hidden input on the single product page. I have some JS that sets the ID of the image, which is based on the product’s colour (a custom attribute I made with ACF).
<input class="js-col-img-id" type="hidden" name="product-col-img-id" value="">
For reference, here’s what I’ve done to get this to work on the cart page:
// Add custom attributes to cart item data add_action('woocommerce_add_cart_item_data', 'jwd_add_custom_attr_to_cart', 10, 3); function jwd_add_custom_attr_to_cart($cart_item_data, $product_id, $variation_id) { $attrs = array(...,'product-col-img-id'); foreach ($attrs as $attr) { $san_attr = filter_input( INPUT_POST, $attr ); if ( !empty( $san_attr ) ) { $cart_item_data[$attr] = $san_attr; } } return $cart_item_data; } // This function sets the image ID in the cart, and it displays the image properly add_action( 'woocommerce_before_calculate_totals', 'bwa_new_price' ); function bwa_new_price($cart) { // ... $cart_items = $cart->get_cart(); foreach($cart_items as $item) { $data = $item['data']; // product-col-img-id is sent through the hidden input when the add to cart form is submitted $colour_img_ID = $item['product-col-img-id'] ?? false; if ($colour_img_ID) { $data->set_image_id($colour_img_ID); } } } // Add custom attributes to order add_action( 'woocommerce_checkout_create_order_line_item', 'jwd_add_attr_to_order_items', 10, 4 ); function jwd_add_attr_to_order_items( $item, $cart_item_key, $values, $order ) { if ( !empty( $values['product-colour'] ) ) { $item->add_meta_data( 'Colour', $values['product-colour'] ); } // I tried replicating this for the img ID. It does display it in the var dump mentioned below, and it does display it as an actual label in the e-mail (which I'd want to get rid of). The difficulty then becomes reading the ID through code and setting the product to display that image if ( !empty( $values['product-col-img-id'] ) ) { $item->add_meta_data( 'col_img_id', $values['product-col-img-id'] ); } }
That works fine, but I’m having difficulty replicating this in the order e-mail. So far I’ve come across the following. This shows images in the e-mail, but it’s the product’s featured image. Of note is the “show_image” key being set to true.
// Add prod IMG to e-mails function jwd_add_images_woocommerce_emails( $output, $order ) { // set a flag so we don't recursively call this filter static $run = 0; // if we've already run this filter, bail out if ( $run ) { return $output; } $args = array( 'show_image' => true, //'image_size' => array( 300, 300 ), 'image_size' => 'full', ); // increment our flag so we don't run again $run++; // if first run, give WooComm our updated table return wc_get_email_order_items($order, $args); } add_filter( 'woocommerce_email_order_items_table', 'jwd_add_images_woocommerce_emails', 10, 2 );
To modify the image, I found this filter, but I’m just having a difficult time figuring out what I need to do to replicate what I’ve done on the cart page. The closest I’ve got is having $item_data
work, and I do see the product-col-img-id
key in the var dump, though it’s in a protected object, which I’m not sure how to access. Even if I could access, I’m not sure how I could even set the image from here.
add_filter('woocommerce_order_item_thumbnail', 'jwd_add_colour_img', 10, 2); function jwd_add_colour_img($image, $item) { $item_id = $item->get_id(); //var_dump($item->get_current_data()); $product = $item->get_product(); $product_id = $item->get_product_id(); $item_data = $item->get_data(); $col_img_id = false; $item->set_image_id(1); foreach ($item_data as $key => $item) { //current_data var_dump($item); //echo "<br><br>"; $col_img_id = $item['product-col-img-id'] ?? false; if ($col_img_id) { break; } } //var_dump($col_img_id); //$item_id = $item->get_product_id(); //var_dump(wc_get_order_item_meta( $item_id, 'col_img_id', true ) ); return $image; }
Advertisement
Answer
To get WooCommerce custom meta data, you can use WC_Data
method get_meta()
.
Try the following instead to display your custom image on email notifications:
// Save custom image ID as order item meta add_action( 'woocommerce_checkout_create_order_line_item', 'save_custom_image_id_to_order_item', 10, 4 ); function save_custom_image_id_to_order_item( $item, $cart_item_key, $values, $order ) { if ( isset($values['product-colour']) && ! empty($values['product-colour']) ) { $item->add_meta_data('Colour', $values['product-colour'] ); } if ( isset($values['product-col-img-id']) && ! empty($values['product-col-img-id']) ) { $item->add_meta_data('_col_img_id', $values['product-col-img-id'] ); } } // (optional) Force display item image on emails add_filter( 'woocommerce_email_order_items_args', 'show_image_on_email_notifications' ); function show_image_on_email_notifications( $args ) { $args['show_image'] = true; return $args; } // Display custom image on emails add_filter( 'woocommerce_order_item_thumbnail', 'display_email_order_item_custom_image', 10, 2 ); function display_email_order_item_custom_image( $image, $item ) { // Only on email notifications if( is_wc_endpoint_url() ) return $image; $image_id = $item->get_meta('_col_img_id'); if( $image_id ) { $image = wp_get_attachment_image( $image_id, array( 32, 32 ), false, array() ); } return $image; }
Code goes in functions.php file of the active child theme (or active theme). It should work.