phpwordpresswoocommercecustom-taxonomyemail-notifications

Different recipients based on product category in WooCommerce email notification


I am setting up a site for a school that sells both virtual products (fees and excursion payments) and Physical (uniforms) however they would like to have order notifications for each category to be sent to separate recipients as they are dealt with by different departments.

For example all uniform category orders are to go to recipient one, while all the others go to recipient two... I have come across multiple ways to send custom emails messages based on the product, however none of these meet my requirements.

I would also like to be able to do this without the use of a plugin like Woocommerce Advanced Notifications.

Any assistance with this would be greatly appreciated.


Solution

  • The following will add additional recipients to "New Order" email notification based on your product categories, that you will define in an indexed array with an email recipient / product category pairs:

    add_filter( 'woocommerce_email_recipient_new_order', 'custom_email_recipient_new_order', 10, 2 );
    function custom_email_recipient_new_order( $recipient, $order ) {
        // Not in backend when using $order (avoiding an error)
        if( ! is_a($order, 'WC_Order') ) return $recipient;
    
        // Define the email recipients / categories pairs in the array
        $recipients_categories = array(
            'email.one@email.com'   => 'category-one',
            'email.two@email.com'   => 'category-two',
            'email.three@email.com' => 'category-three',
        );
    
        // Loop through order items
        foreach ( $order->get_items() as $item ) {
            // Loop through defined product categories
            foreach ( $recipients_categories as $email => $category ) {
                if( has_term( $category, 'product_cat', $item->get_product_id() ) && strpos($recipient, $email) === false ) {
                    $recipient .= ',' . $email;
                }
            }
        }
        return $recipient;
    }
    

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

    Notes:

    • The defined Product categories can be term Ids, term slugs or term names.
    • Each product category need to be defined in the related products as has_term() WordPress conditional function doesn't handle parent terms.

    ###Addition to handle parent product categories:

    // Custom conditional function that handle parent product categories too
    function has_product_categories( $categories, $product_id = 0 ) {
        $parent_term_ids = $categories_ids = array(); // Initializing
        $taxonomy        = 'product_cat';
        $product_id      = $product_id == 0 ? get_the_id() : $product_id;
    
        if( is_string( $categories ) ) {
            $categories = (array) $categories; // Convert string to array
        }
    
        // Convert categories term names and slugs to categories term ids
        foreach ( $categories as $category ){
            $result = (array) term_exists( $category, $taxonomy );
            if ( ! empty( $result ) ) {
                $categories_ids[] = reset($result);
            }
        }
    
        // Loop through the current product category terms to get only parent main category term
        foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
            if( $term->parent > 0 ){
                $parent_term_ids[] = $term->parent; // Set the parent product category
                $parent_term_ids[] = $term->term_id; // (and the child)
            } else {
                $parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
            }
        }
        return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
    }
    
    // Adding custom recipients based on product categories
    add_filter( 'woocommerce_email_recipient_new_order', 'custom_email_recipient_new_order', 10, 2 );
    function custom_email_recipient_new_order( $recipient, $order ) {
        // Not in backend when using $order (avoiding an error)
        if( ! is_a($order, 'WC_Order') ) return $recipient;
    
        // Define the email recipients / categories pairs in the array
        $recipients_categories = array(
            'email.one@email.com'   => 'category-one',
            'email.two@email.com'   => 'category-two',
            'email.three@email.com' => 'category-three',
        );
    
        // Loop through order items
        foreach ( $order->get_items() as $item ) {
            // Loop through defined product categories
            foreach ( $recipients_categories as $email => $category ) {
                if( has_product_categories( $item->get_product_id(), array( $category ) ) && strpos($recipient, $email) === false ) {
                    $recipient .= ',' . $email;
                }
            }
        }
        return $recipient;
    }
    

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

    Note: The Product categories can be term Ids, term slugs or term names.


    Similar: Different recipients based on products sold in WooCommerce email notification