Display a custom notice per product category and buyer country on WooCommerce checkout

Let’s say you have specific product category inside your store – maybe some products that take longer to ship or package to some country. Or maybe some products that require for the buyers to be aware of certain rules before the purchase if they are from a particular country. We’ll, in this post I’ll show you how you can display a notice on the checkout depending on what your customer has in her/his cart. Let’s dive in.

I’ll be using the following WooCommerce action hook to plug into the checkout page:


    woocommerce_after_checkout_billing_form

So, the first thing you’ll wan to note down, is the ID the category you wish to output the notice for on the checkout. We’ll use this category ID in our code to check whether the products in the cart are in fact from this category. If so, and if our buyers comes from a specific country, we’ll show a message to the buyer before they click on the “Order now” button.

Get all the category IDs in the cart

First thing we do, is check all the products in the cart, and store their category IDs in an array, This is how it’s done:


        $cart = WC()->cart->get_cart();
        $products = [];
        $products_cat = [];
        foreach($cart as $cart_item_key => $cart_item) {
        $products[] = $cart_item['product_id'];
        $products_cat[] = wp_get_post_terms($cart_item['product_id'], 'product_cat');
        }
        $cat_ids = [];
        foreach($products_cat as $product_cat) {        
            foreach($product_cat as $category) {
            $cat_ids[] = $category->term_id;
            }
            
        }

So, let’s just quickly go through a few lines that are most interesting to comment:

  1. Line 1 – we’re fetching the data from the cart object
  2. Lines 2-3 – we’re preparing our variables that we’ll store our products and product categories in
  3. Line 4 – we’re looping through the cart items
  4. Line5 – we’re fetching the ‘product_id’ key from the array, which holds the ID of our product
  5. Line 6 – by using ‘wp-get_post_terms’, we’re getting all the terms from the taxonomy ‘product_cat’ for that particular product – ‘product_cat’ is a taxonomy native to WooCommerce, more commonly known as “Product category”. We’re storing all the terms inside $products_cat
  6. We’re looping through all the categories to pick out the IDs. We do this on line 11, where we grab the ‘term_id’ from the array and store it into $cat_ids
  7. $cat_ids is what we’ll be comparing the original category ID for which we wish to display the notice, so bear that in mind.

So, the next part is where we compare our categories. You can compare a single category ID, or you can compare an array of category IDs. In both scenarios, you can use an array, so let’s say you have something like:


    $notice_category = [
0 => 123,
1 => 124
];

The variable above named $notice_category holds two category IDs, 123 and 124. How you obtain this information is up to you. You can hard code it, or you can fetch it from someplace else, for example from WordPress database where you stored it through some type of options page. Of you could even add a custom field to the edit category page and get it from there. But this is beyond the scope of this article. The most important thing to note here is that ‘123’ and ‘124’ are product categories for which we need to display a custom notice on the checkout. So, how do we do this? First, let’s compare our categories with array_intersect:


    if(array_intersect($notice_category, $cat_ids)) {
//show notice
}

So, in the above code block, we’re comparing two arrays, and checking whether our categories from $notice_category are, well, basically attached as product categories to the products in the cart (which are now stored in $cat_ids variable). If this condition is true, we show our notice. So, let’s put the code and see how it’s really done.

Checking the country of the buyer

Because our customer can select the country from the select field, we can’t use PHP to check for the country (well, we could use AJAX and cookies but there’s a simpler way). What we do is, output the notice inside the DOM through PHP, and hide it by default (of course, only if the arrays from our categories from the previous block intersect). The way I’m going to do this, is to append the notice to the country select field, because it makes most sense to display the notice in the same place (or at least close to it) where the customer selects the country. So, this is how we do this:


          if(array_intersect($cat_ids, $cat_ids)) { ?>
        <script>
        jQuery(document).ready(function($) {
        $('.checkoutNotice').appendTo('#billing_country_field');
        });
        </script>
         <div class="checkoutNotice" style="display:none;">
        <div class="innerWrap">
        <?php _e('Some of the products in your cart are difficult to ship to Croatia. Please be aware that shipping might take longer.', 'sage'); ?>
        </div>
        </div>
        <?php }  ?>

So, as you can see above, we’re comparing the categories and displaying (but hiding) the notice in a way where we’re attaching it to the “billing_country_field” container. After this, all we need to do is get the value from the country field the moment our customer selects it. We do this by using the .change() function from jQuery:


     <script>
jQuery(document).ready(function($) {
    $('#billing_country').change(function() {
        var selectedValue = $(this).val();
        if(selectedValue  === 'HR') {
        $('.checkoutNotice').appendTo('#billing_country_field');
        $('.checkoutNotice').show();
        }
        else if(selectedValue != 'HR') {
        $('.checkoutNotice').hide();
        }
        else if(selectedValue === '') {
        $('.checkoutNotice').hide();
        }
});
});
</script>

Let’s comment a few lines:

  1. Line 3 – Monitor the change on our select element with the ID “billing_country”
  2. Line 4 – get the value from the select field
  3. Line 5 – 7 – if our customer just selected the desired country, we append the notice and show it. If not, hide it (lines 9 to 13)

Let’s put it all together


      <?php
add_action('woocommerce_after_checkout_billing_form', __NAMESPACE__ . '\\codeart_print_note');
    function codeart_print_note() {
  
        //get the cart data
        $cart = WC()->cart->get_cart();
        //initalize arrays
        $products = [];
        $products_cat = [];
        //loop through cart data and get products
        foreach($cart as $cart_item_key => $cart_item) {
        $products[] = $cart_item['product_id'];
        //store all product categories inside $products_cat
        $products_cat[] = wp_get_post_terms($cart_item['product_id'], 'product_cat');
        }
        $cat_ids = [];
        //loop through all category data and store only IDs
        foreach($products_cat as $product_cat) {        
            foreach($product_cat as $category) {
            $cat_ids[] = $category->term_id;
            }
            
        }
        //compare the two array, if true output notice
        if(array_intersect($cat_ids, $cat_ids)) { ?>
        <script>
        jQuery(document).ready(function($) {
            //append notice to country select field
        $('.checkoutNotice').appendTo('#billing_country_field');
        });
        </script>
         <div class="checkoutNotice" style="display:none;">
        <div class="innerWrap">
        <?php _e('Some of the products in your cart are difficult to ship to Croatia. Please be aware that shipping might take longer.', 'sage'); ?>
        </div>
        </div>
        <?php }  ?>

        <script>
jQuery(document).ready(function($) {
    //monitor the change on the country select field
    $('#billing_country').change(function() {
        //grab the value of the select field
        var selectedValue = $(this).val();
        //if from a particular country append & show notice
        if(selectedValue  === 'HR') {
        $('.checkoutNotice').appendTo('#billing_country_field');
        $('.checkoutNotice').show();
        }
        //else hide
        else if(selectedValue != 'HR') {
        $('.checkoutNotice').hide();
        }
        else if(selectedValue === '') {
        $('.checkoutNotice').hide();
        }
});
});
</script>
<?php

}

So, there you have it – a way to display a notice to customers from a particular country that are purchasing products from a particular WooCommerce product category. I hope you find this snippet useful!

Hire your codeartist

looking for a development of your own project?

is your agency looking for a partner?