How to add shipping logic based on Product in Cart – WooCommerce?

Photo of author
Written By geekerhub

Lorem ipsum dolor sit amet consectetur pulvinar ligula augue quis venenatis. 

Client Requirements always play an important role in the development cycle.WooCommerce is a vast platform to meet any needs as per client requirements. Some client needs product based shipping for there WooCommerce Store.

So How to obtain product based shipping in your WooCommerce store without a plugin?

For this, you need to know how many shipping methods are available for your store. Let’s say your store has three shipping methods namely.

  • local shipping.
  • International shipping.
  • country shipping.

Now you need to create metadata based on this shipping method. Creating metadata for the product is easy and please google for adding metadata to the product. Let’s say you have added three metadata (checkbox) namely:

  • Enable local shipping.
  • Enable international Shipping.
  • Enable Country Shipping.

you need to use ‘woocommerce_package_rates’ filter to modify shipping based on product metadata and here goes a code snippet. Let me know in the comment section or contact us if any query in the below snippet.

/*Filter to modify shipping rates based on product meta BY PERCEPTION SYSTEM*/
add_filter('woocommerce_package_rates', 'woo_package_rates_callback', 10, 2);
function woo_package_rates_callback($available_shipping_methods, $package){
    global $woocommerce;
    $shipping_in_products = $hide_available_shippings = array();

    /*Here we get cart item*/
    $items = $woocommerce->cart->get_cart();

    /*Looping cart item details to get the assigned shipping method meta*/
    foreach($items as $item => $values) { 
        $pID             = $values['product_id'];
        $local             = get_post_meta($pID, "local" ,true);
        $international     = get_post_meta($pID, "international" ,true);
        $country         = get_post_meta($pID, "country" ,true);

        if($local == 'yes'){
            if(!in_array('local', $shipping_in_products)){
                $shipping_in_products['first'] = 'local';

        if($international == 'yes'){
            if(!in_array('international', $shipping_in_products)){
                $shipping_in_products['second'] = 'international';

        if($country == 'yes'){
            if(!in_array('country', $shipping_in_products)){
                $shipping_in_products['third'] = 'country';

    $ship_one         = $shipping_in_products['first'];
    $ship_two         = $shipping_in_products['second'];
    $ship_three     = $shipping_in_products['third'];

    $hide_shipping_list = array(
        'hide_shipping' => array('local', 'international', 'country'),
    if( $ship_one == 'local' && $ship_two =='international' && $ship_three ="country"){
        /*No shipping to hide*/
        $hide_shipping_list = array(
            'hide_shipping' => array(),
    }else if( $ship_one == 'local' && $ship_two =='international'){
        /*hide country shipping*/
        $hide_shipping_list = array(
            'hide_shipping' => array('country'),
    }else if(condition){
    $hide_shipping_args = 'hide_shipping';
    if ( in_array( $hide_shipping_args , array_keys($hide_shipping_list) ) ) {
        if( !empty( $hide_shipping_list[$hide_shipping_args] ) ){
            foreach ($hide_shipping_list[$hide_shipping_args] as $shipping_methods) {
                foreach ($available_shipping_methods as $shipping_method => $value) {
                    if( strpos( $shipping_method, $shipping_methods ) !== false ) {

   return $available_shipping_methods;

Leave a Comment