Search code examples
phpwordpresswoocommercemetadataemail-notifications

Display WooCommerce order item custom meta data only in Admin New order notification


I have a huge problem to solve a below case. Can you help me, please?

What I need to do:

  1. I needed to create an additional product custom field like technical specification (tech_spec), which would be filled by administrator during creating/editing a product, so I use ACF plugin.

  2. These technical informations are reserved only for administrator, so I don't want to show it to customer, however I need to add them automatically to orders panel (backend) during creating a new order by clients, as well as send them only to administrator in a new order notification (email).

What I've tried to do:

  1. I created a tech_spec field using a ACF plugin and displayed it on the single product edit page.

  2. I implemented this field's data on the single product page using the hook: woocommerce_before_add_to_cart_button and used css to hide them.

    PHP (functions.php):

add_action('woocommerce_before_add_to_cart_button','techspec_field');

function techspec_field(){
    global $product;
    ob_start(); ?>
        <div class="techspec-info">
            <textarea name="tech_spec"><?php the_field('tech_spec'); ?></textarea>
        </div>
    <?php
    $content = ob_get_contents();
    ob_end_flush();
    return $content;
}

CSS (style.css):

.techspec-info textarea {
display: none !important;
visibility: hidden;}
  1. I created a function to adding a field's data to the cart.
add_filter('woocommerce_add_cart_item_data','techspec_add_item_data', 10,3);

function techspec_add_item_data($cart_item_data, $product_id, $variation_id)
{
    if(isset($_REQUEST['tech_spec']))
    {
        $cart_item_data['tech_spec'] = sanitize_text_field($_REQUEST['tech_spec']);
    }

    return $cart_item_data;
}
  1. Next I implemented another function to display a data in a cart and checkout page.
add_filter('woocommerce_get_item_data','techspec_add_item_meta',10,2);

function techspec_add_item_meta($item_data, $cart_item)
{

    if(array_key_exists('tech_spec', $cart_item))
    {
        $custom_details = $cart_item['tech_spec'];

        $item_data[] = array(
            'key'   => 'Technical Specification',
            'value' => $custom_details
        );
    }

    return $item_data;
}
  1. After that I created a function to adding data to new order.
add_action( 'woocommerce_checkout_create_order_line_item', 'techspec_add_custom_order_line_item_meta', 10,4 );

function techspec_add_custom_order_line_item_meta($item, $cart_item_key, $values, $order)
{

    if(array_key_exists('tech_spec', $values))
    {
        $item->add_meta_data('Technical Specification', $values['tech_spec']);
    }
}

Up to this moment everything works fine, but tech_spec field's data are sending to all recipients, including customers. How to restrict sending these data only to administrator? I mean a new order notification. I will be gratefull if you want to help me.

I've tried use different solutions like if($sent_to_admin), as well as hide these data using woocommerce_order_item_get_formatted_meta_data, but it doesn't work, or I did something wrong. Thank you in advance for your help.


Solution

  • You will not be able to target only admin new order email notification, for order items custom meta data.

    Now to make this custom order item meta data only visible on Admin single order pages, you will need to alter the "meta key" in your last function, replacing it with a slug starting with an underscore, something like _tech_spec, it will be hidden from customer and email notifications:

    add_action( 'woocommerce_checkout_create_order_line_item', 'techspec_add_custom_order_line_item_meta', 10,4 );
    
    function techspec_add_custom_order_line_item_meta($item, $cart_item_key, $values, $order)
    {
    
        if(array_key_exists('tech_spec', $values))
        {
            $item->add_meta_data('_tech_spec', $values['tech_spec']);
        }
    }
    

    If you want to have a readable "meta key" name replacement on Admin orders, you will use:

    add_filter( 'woocommerce_order_item_display_meta_key', 'filter_order_item_display_meta_key', 10, 3 );
    function filter_order_item_display_meta_key( $display_key, $meta, $item ) {
        // only on Admin
        if ( is_admin() && $display_key === '_tech_spec' ) {
            $display_key = __('Technical Specification', 'woocommerce');
        }
        return $display_key;
    }
    

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