WooCommerce: Shipping by Weight (Without a Plugin!)

Woo 2.6 introduced Shipping Zones – and with that we can play with simple PHP to accomplish lots of “advanced” shipping rules, such as shipping by weight.

With many of Business Bloomer fans always asking for this sort of customization, today we’ll see how to do just that. Without the need of just another plugin 🙂

1. Shipping by Weight – Requirements

If you or your client requires shipping by weight, then you first have to make sure ALL simple products and/or single variations have a weight that is not zero. Pretty simple, but sometimes people ask “why shipping y weight doesn’t work”, and the most common mistake is that product has no weight!

Also, under WooCommerce > Settings > Products make sure to select the correct “Weight Unit“, another typical error people make (defaults to Kg I believe).

2. Shipping by Weight – Shipping Methods Setup

You can add unlimited Flat Rates to each Shipping Zone. Also, you can rename each flat rate to something like “Orders Below 1kg”, “Orders Above 10kg”, etc to make the checkout label a little more user-friendly.

In our example, we will setup 3 weight tiers: $10 shipping for orders up to 1kg, $20 shipping for orders up to 5kg and $30 shipping for orders above 5kg.

And here is how to set the WooCommerce shipping methods:

  1. Flat Rate #1 > rename to “Orders Below 1kg” and assign cost = $10
  2. Flat Rate #2 > rename to “Orders Below 5kg” and assign cost = $20
  3. Flat Rate #3 > rename to “Orders Above 5kg” and assign cost = $30

Your final result for the specific zone (I called it “USA – Shipping by Weight”) will look like this:

WooCommerce Shipping by Weight (Shipping Zone Setup)
WooCommerce Shipping by Weight (Shipping Zone Setup)

3. Shipping by Weight – PHP Snippet

Now we need to “tell” WooCommerce that, based on the cart weight, a Flat Rate should be used instead of another. Only in this way we can show the correct flat rate to the end user.

First, take a note of the unique ID of the three flat rates. They should look look something like “flat_rate:9“. For more info on how to find them, check here: https://businessbloomer.com/woocommerce-disable-free-shipping-if-cart-has-shipping-class/#woocommerce-how-to-find-shipping-method-id-woo-2-6-after-the-introduction-of-the-new-shipping-zones

Second, let’s code! We’ll need to “unset” rates based on the total weight, so in total we’ll need 3 conditions: when weight is below 1 (kg), below 5 (kg) and above.


/**
 * @snippet       Shipping by Weight | WooCommerce
 * @how-to        Watch tutorial @ https://businessbloomer.com/?p=19055
 * @sourcecode    https://businessbloomer.com/?p=21432
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 3.5.4
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 9999, 2 );
  
function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
	
  	if ( WC()->cart->cart_contents_weight < 1 ) {
     
   		if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:6'], $rates['flat_rate:8'] );
	  
	} elseif ( WC()->cart->cart_contents_weight < 5 ) {
	  
		if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:8'] );
	  
	} else {
	  
		if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:6'] );
	  
	}
  
  return $rates;
  
}

And here is the proof:

WooCommerce: Shipping by Weight Demonstration
WooCommerce: Shipping by Weight Demonstration

Where to add this code?

You can place PHP snippets at the bottom of your child theme functions.php file (before "?>" if you have it). CSS, on the other hand, goes in your child theme style.css file. Make sure you know what you are doing when editing such delicate files - if you need more guidance, please take a look at my free WooCommerce Customization video tutorial.

Does this snippet still work?

Please let me know in the comments if everything worked as expected. I would be happy to revise the snippet if you report otherwise (please provide screenshots). I have tested this code with Storefront theme, the WooCommerce version listed above and a WordPress-friendly hosting on PHP 7.

If you think this code saved you time & money, please join other Business Bloomer supporters and avail of 365 days of WooCommerce benefits. Thank you in advance :)

Need Help with WooCommerce?

Check out these free videos, tutorials and tips!

  • how-to-edit-woocommerce-with-php-snippets
  • woocommerce-hooks-add_action-list-visual
  • woocommerce-customize-single-product-page-PHP
  • woocommerce-customize-shop-page-PHP
  • woocommerce-advanced-customization
  • how-to-edit-woocommerce-cart
  • woocommerce-customize-checkout-page-PHP
  • woocommerce-email-customization
  • woocommerce-conditional-logic

Rodolfo Melogli

Author, WooCommerce expert, WordCamp speaker and Internet marketer, Rodolfo Melogli has worked as a WooCommerce freelancer since 2011. He helps entrepreneurs and developers overcome their WooCommerce nightmares :) Rodolfo is the organiser of WordCamp Dublin, the Dublin WooCommerce Meetup, the Dublin Ecommerce Meetup and the Dublin WordPress Meetup. He enjoys interacting with people, travelling and chasing tennis & soccer balls. Of course, he loves pizza too.

81 thoughts on “WooCommerce: Shipping by Weight (Without a Plugin!)

  1. Hey Rodolfo,

    Thanks for the tutorial, I managed to set it up at my shop. Just wondering if there is anyway to make sure the “Shipping class costs” still works if there is only a specific item in the cart. For example, I have one item in my shop which I want to provide for free but costs $1 to post (with a limit of 2 or 3 items for the $1 postage cost). Thanks, Jen

    1. Hello Jen, thanks so much for your comment! Yes, this is possible – unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding! ~R

    2. Thanks for your response. I will try something else, can you help if I want there to be three values one for less than 100g and then from under 1 kg and then 3kg and over.

    3. Jen:

      if ( WC()->cart->cart_contents_weight < 0.1 ) {
      // --
      } elseif ( WC()->cart->cart_contents_weight < 1 ) {
      // --
      } else {
      // --
      }
      
  2. Hello Rodolfo,

    First I want to say I really enjoy reading your tutorials. It has been much help to me many many times 🙂

    This post I also going to use but I got a question regarding this post.
    Is this also possible with the dimensions of a product? A friend of mine has a shop with banisters and the lenght of this product can vary from 1 meter to 4 meters. So when somebody orders a banister of 4 meters the shipping costs should be higher because they have to deliver it with a bigger truck.

    I tried to combine to tutorials of you. This one and
    https://businessbloomer.com/woocommerce-display-product-height-length-width-shop-page/

    but no luck so far. I tried it like this:

    /**
     * @snippet       Shipping by Weight | WooCommerce
     * @how-to        Watch tutorial @ https://businessbloomer.com/?p=19055
     * @sourcecode    https://businessbloomer.com/?p=21432
     * @author        Rodolfo Melogli
     * @compatible    WooCommerce 3.5.4
     * @donate $9     https://businessbloomer.com/bloomer-armada/
     */
     
    add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 9999, 2 );
       
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
    	global $product;
    	$dimensions = $product->get_dimensions();
    
         
        if ( $product->get_length() < 2000 ) {
          
            if ( isset( $rates['flat_rate:1'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:6'] );
           
        } elseif ( $product->get_length() > 2000 ) {
           
            if ( isset( $rates['flat_rate:1'] ) ) unset( $rates['flat_rate:6'], $rates['flat_rate:5'] );
           
        } else {
           
            if ( isset( $rates['flat_rate:1'] ) ) unset( $rates['flat_rate:1'], $rates['flat_rate:1'] );
           
        }
       
      return $rates;
    	
       
    }
    

    Got an idea or is this not possible at all?

    Once again, love you work and looking forward to new tutorials:)

    Kind regards.

    1. Hey Joep, thanks so much for your comment! Yes, this is possible – unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding! ~R

  3. Hi!

    Can it be combined with the WC built-in free shipping above a certain order total?
    First, I’d like the code to check if the order total is above like $50, then run this weight check.
    Could you please help with this?

    1. Hello Anna, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding! ~R

  4. Thanks Rodolfo,
    WOW, Its work great for me, just tweak little more and Limitize my Shipment Charges with 3 catagories
    1. 150g to 500g, 2. 501g to 1Kg, 3. 1Kg to 3Kg+

    Really you are a amazing man, i am really grateful to you for this great help. i have completed my First WooCommerce project with the help of your Custom Code.
    Love you and Respectful to you.
    Kind Regards,
    Aqeel

    1. Thank you 🙂

  5. Thanks for sharing. Is there any way to show the weight of the product? You in the example have written in red Weight 34 Kilos.

    Is it possible to show the weight of each item?

    1. Hello Ivan, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  6. Hi Rodolfo,
    thank you for your plugin, is it still working? I have tried to use it in my website, but I cannot see any change on website, I can see there all 3 options, I put it at the end of functions.php

    Here is the code I adjusted to my site:

     
    add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
       
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
         
        if ( WC()->cart->cart_contents_weight < 1000 ) {
          
            if ( isset( $rates['flat_rate:11'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:12'] );
           
        } elseif ( WC()->cart->cart_contents_weight < 100 ) {
           
            if ( isset( $rates['flat_rate:7'] ) ) unset( $rates['flat_rate:11'], $rates['flat_rate:12'] );
           
        } else {
           
            if ( isset( $rates['flat_rate:12'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:11'] );
           
        }
       
      return $rates;
       
    }
    

    I am a WP beginner, so maybe I have done something wrong in some unexpected way:)

    Thank you

    1. Hey Petra, thanks for your comment! 100 is also < than 1000 so the first two statements will mess with each other - you need to edit those calls and make sure they target different weight ranges. Hope this helps 🙂

  7. Where is the mistake?

    add_filter( 'woocommerce_package_rates', 'tariffa_spedizione_a_peso', 10, 2 );
       
    function tariffa_spedizione_a_peso( $rates, $package ) {
         
        if ( WC()->cart->cart_contents_weight < 3 ) {
          
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:6'], $rates['flat_rate:7'] );
           
        } elseif ( WC()->cart->cart_contents_weight < 8 ) {
           
            if ( isset( $rates['flat_rate:6'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:7'] );
           
        } else {
           
            if ( isset( $rates['flat_rate:7'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:6'] );
           
        }
       
      return $rates;
       
    }
    
    1. Hey there 🙂 It’s in the “elseif”: “<8" can be also "<3" (first condition). You need to also add ">=3″. Hope this helps

  8. Hi,
    Great website you have here. I use it ALOT when developing custom functions 🙂
    Saves me huge amount of time.
    I was wondering if you could help me.
    Im trying to change shipping cost based on zip code “programmatically”.
    So I just have one rate called “flat_rate”
    And then I want to change it based on user input in the Zip code field.

    Ive been trying all sorts of functions from the web.
    This is what I have now that works but it does not get ZIP code input.

    add_filter( 'woocommerce_package_rates', 'custom_shipping_rate_cost_calculation', 10, 2 );
    function custom_shipping_rate_cost_calculation( $rates, $package ) {
    
    $postal_code = $package[ 'destination' ][ 'postcode' ]; // This does not work !
    
        foreach( $rates as $rate_key => $rate ) {
            if ( 'flat_rate' === $rate->method_id ){
    
                // Get rate cost and Custom cost
                $initial_cost = $rates[$rate_key]->cost;
                //$additional_cost = 10000;
    
                // Calculation
                $new_cost = $initial_cost + $postal_code;
    
                // Set Custom rate cost
                $rates[$rate_key]->cost = round($new_cost, 2);
    
                // Taxes rate cost (if enabled)
                $new_taxes = array();
                $has_taxes = false;
                foreach ( $rate->taxes as $key => $tax ){
                    if( $tax > 0 ){
                        // Calculating the tax rate unit
                        $tax_rate = $tax / $initial_cost;
                        // Calculating the new tax cost
                        $new_tax_cost = $tax_rate * $new_cost;
                        // Save the calculated new tax rate cost in the array
                        $new_taxes[$key] = round( $new_tax_cost, 2 );
                        $has_taxes = true;
                    }
                }
                // Set new tax rates cost (if enabled)
                if( $has_taxes )
                    $rate->taxes = $new_taxes;
            }
        }
    
        return $rates;
    }
    
    1. Aron, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  9. Thank you so much. It really helped me alot.

    1. Excellent 🙂

  10. I’m thinking about implementing this, but am also considering using the free plugin “WooCommerce Weight Based Shipping by weightbasedshipping.com”. Is your method above better because we can customize the code directly? Thanks!

    1. Hello Owen – thanks so much for your comment! My method is just “one of the methods”, so you should use the option you feel more comfortable with – there are pros and cons either way 🙂

  11. Hi,

    I am a beginner trying to set up weight based shipping fee on my website. I tried integrating some third party plugins but they were causing issues within the theme so I had to delete them. I came across your blog and have been following the steps mentioned to set up the weight based shipping fee on my website but I am encountering an issue getting the unique id. I am sharing the exact point from the blog here for your reference- “First, take a note of the unique ID of the three flat rates. They should look look something like “flat_rate:9“. For more info on how to find them, check here: https://businessbloomer.com/woocommerce-disable-free-shipping-if-cart-has-shipping-class/#woocommerce-how-to-find-shipping-method-id-woo-2-6-after-the-introduction-of-the-new-shipping-zones
    I need 3 shipping zones which I could create without any difficulty but when I am trying to inspect the check out page, I am able to get the unique id of only the first zone. How do I get the unique id of the second and third zones. Can you please help me figure this out. And in case there is a nice plugin that I could use, please share the name of that as well.

    1. Hey Mounika – thanks so much for your comment! You’re on the wrong page – you need to get the ID of the “shipping rate”, which is one of the rates that belong to a “shipping zone”. So, open the zone, and look for the IDs for each rate that belongs to that zone. Hope this helps!

  12. So I dug into it, successfully finished work on the before-mentioned mini plugin prototype for a client of mine, and while doing so, stumbled into something rather nasty: If you’re wondering why the displayed rate in the cart / checkout process might not change, NO MATTER WHAT YOU DO ..

    .. its thanks to something called “WooCommerce Shipping Rate Cache”.

    So for testing purposes, head over to the WooCommerce settings > “Checkout”, and activate the “Debug Mode”.

    But for your live site, that won’t suffice, so you might want to manually delete the transients in which the “Shipping Rate Cache” is being stored. Several articles point you towards the wp_options table, and tell you to search for ‘wc_ship*’. More correct, you have to search for ‘_transient_wc_ship* (in SQL Query terms: ‘… LIKE “%_transient_wc_ship%”). Now after finding these, you ought to delete em manually.

    A more workable solution is what a few tutorials point out: There is an option in the WooCommerce settings, located under Status > Tools, which lets you delete all or just specific transients. You’d have to always use them before doing changes to your code IF you want to see changes to the live site, but nevertheless, its easier than having to manually look up the transients and delete them in your database.

    cu, w0lf.

    1. Nice 🙂

  13. For those interested in turning this into something more complete, eg. a (very simple) plugin, that just handles the PHP part:

    The data we are using to test here is stored in the `woocommerce_shipping_zone_methods` table (instance_id = the instance). And the descriptions of the resp. shipping methods are stored in the options-table by the option_name scheme `woocommerce_flat_rate_{instance_id}_settings`. The value is a serialized associative array which might be auto-converted into an array when fetching the data using the get_option() function (if not, maybe_unserialize() should help).

    With this, one should be theoretically be able to build a semi-dynamic version of the PHP snippet, where you just have to decide for yourself what keywords / trigger words you are going to use to distinguish between lower, equal and higher weight values. The keywords themselves have to be taken from the description field, which is stored as ‘title’ in the aforementioned serialized array

    In the current example, this would be “Below ” and “Above”. So anything with “Below” in its title equals $x < $y, where $x is the current weight, and $y is our parsed-out weight value found in the description field, eg. "1kg".

    Of corpse you'd have to stick to a specific scheme when creating the shipping method descriptions, so that the later on happening parsing does work properly.

    cu, w0lf.

    1. Thanks Wolk 🙂

  14. I need different rates for different countries with shipping by weight.
    Shipping to UK has different shipping rates on weight from the shipping rate to USA.
    There is a way to do it?

    1. Hello Rubb, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  15. Hello,
    I’m getting the following message:
    “Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.”

    This is the code I’m using:

    add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
       
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
         
        if ( WC()->cart->cart_contents_weight < 0.5 ) {
          
            if ( isset( $rates['flat_rate:7'] ) ) unset( $rates['flat_rate:9'], $rates['flat_rate:13'], $rates['flat_rate:10'] , $rates['flat_rate:11'], $rates['flat_rate:12']);
           
        } elseif ( WC()->cart->cart_contents_weight < 1 ) {
           
            if ( isset( $rates['flat_rate:9'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:13'], $rates['flat_rate:10'] , $rates['flat_rate:11'], $rates['flat_rate:12']);
    		
    	} elseif ( WC()->cart->cart_contents_weight < 1.5 ) {
           
            if ( isset( $rates['flat_rate:13'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:9'], $rates['flat_rate:10'] , $rates['flat_rate:11'], $rates['flat_rate:12']);
    		
    	} elseif ( WC()->cart->cart_contents_weight < 2 ) {
           
            if ( isset( $rates['flat_rate:10'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:9'], $rates['flat_rate:13'] , $rates['flat_rate:11'], $rates['flat_rate:12']);
    		
    	} elseif ( WC()->cart->cart_contents_weight < 2.5 ) {
           
            if ( isset( $rates['flat_rate:11'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:9'], $rates['flat_rate:13'] , $rates['flat_rate:10'], $rates['flat_rate:12']);
    	
    	} elseif ( WC()->cart->cart_contents_weight < 3 ) {
           
            if ( isset( $rates['flat_rate:12'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:9'], $rates['flat_rate:13'] , $rates['flat_rate:10'], $rates['flat_rate:11']);
           
        } else {
           
            if ( isset( $rates['flat_rate:12'] ) ) unset( $rates['flat_rate:7'], $rates['flat_rate:9'], $rates['flat_rate:13'] , $rates['flat_rate:10'], $rates['flat_rate:11']);
           
        }
       
      return $rates;
       
    }
    

    Please help me out!

    1. Hey Gautham, thanks so much for your comment! I think the error has nothing to do with my snippet… try using FTP instead of the WordPress Editor to tweak PHP 🙂

  16. Rololfo,
    I have a shopping cart I need to do something like this for. We are in USA and ship everwhere. I need to be able to do this based on lbs (2-4lbs = $10 ship, 5-10lbs = $20 ship for USA, then 2-4lbs = $25 ship, 5-10lbs = $45 ship for Canada, 2-4lbs = $45 ship and 5-10lbs = $90 ship international etc….i will need more such as 5lbs for each as well) Is this a scenario I can use your suggestion? I did not want to try it unless you thought it is a good option for me as I need this site up within a week!

    1. Hey Tiffany, thanks so much for your comment! Yes, this is totally possible, however targeting the country on top of the weight thresholds might be a little too complex from a coding point of view. If you’re familiar with code, then it’s definitely easy to do 🙂

  17. Thanks for this – neat and exactly what I was after (c:

    For others reading this that want to also do this by country you just have to repeat the code for each country in if tags according to each country, like this (I also had four shipping options):

    
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
        global $woocommerce;
        $shipping_zone = WC_Shipping_Zones::get_zone_matching_package( $package );
    
        $zone=$shipping_zone-&gt;get_zone_name();
        
        if ($zone == 'Europe') {
        
            if ( WC()-&gt;cart-&gt;cart_contents_weight cart-&gt;cart_contents_weight cart-&gt;cart_contents_weight cart-&gt;cart_contents_weight cart-&gt;cart_contents_weight cart-&gt;cart_contents_weight &lt; 5 ) {
           
                if ( isset( $rates[&#039;flat_rate:3&#039;] ) ) unset( $rates[&#039;flat_rate:4&#039;], $rates[&#039;flat_rate:3&#039;], $rates[&#039;flat_rate:6&#039;] );
            
            } else {
           
                if ( isset( $rates[&#039;flat_rate:3&#039;] ) ) unset( $rates[&#039;flat_rate:4&#039;], $rates[&#039;flat_rate:5&#039;], $rates[&#039;flat_rate:3&#039;] );
            }
        }
       
      return $rates;
       
    }
    
    
  18. Love what you did there. Sadly I’m one of the people who won’t be able to use this elegant solution. Like in so many such scenarios, the Americans sadly only cater for their own market. “Outside USA” doesn’t even come into play. The world is huge – which might come as a surprise. So for shipments that cross borders (and therefore cost more), it’s back to the drawing board.

  19. Working awesome without plugin. Thank you

  20. Works perfectly, thank you Rodolfo for your snippets!

  21. HI Rodolfo,

    How do i get other id for the flat_rate shipping like flat_rate:2. I got one and how do I understand what will be the others?

  22. I think there is a bug with the code.
    For example, if you set:
    1kg = $1
    2kg = $2
    3kg = $4

    If the item weighs 1kg and the customer sets the quantity to 2 then it should be 2kg and therefore = $2 but the code doesn’t do that?

    1. Hey Peter, thanks for your comment! I just tested this again on the latest version of Woo and it works perfectly, even after updating the quantity. There must be some other issue/conflict.

      To troubleshoot, go to WP Dashboard > WooCommerce > System Status: what errors do you see in red font?

      Also, take a look at this tutorial to see how to troubleshoot: https://businessbloomer.com/woocommerce-troubleshooting-mistakes-to-avoid/

      Finally, can you try switching temporarily to “Twentyseventeen” or “Storefront” theme and let me know if it works?

      Hope this helps!

      R

  23. Awesome!
    Thank you 🙂

  24. Thank you for this code snippet.
    But how can we use this code for shipping to different countries.

    1. Hey Sjoerd, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  25. Hey! Nice work! Thank you!

  26. I pasted your code exactly into the functions.php and it’s still breaking the site.
    What am I doing wrong? Can anybody help me with this?

    <?php
    //
    // Recommended way to include parent theme styles.
    //  (Please see http://codex.wordpress.org/Child_Themes#How_to_Create_a_Child_Theme)
    //  
    add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
    function theme_enqueue_styles() {
        wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
        wp_enqueue_style( 'child-style',
            get_stylesheet_directory_uri() . '/style.css',
            array('parent-style')
        );
    }
    //
    // Your code goes below
    //
    
     
    add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
       
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
         
        if ( WC()->cart->cart_contents_weight < 1 ) {
          
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:6'], $rates['flat_rate:8'] );
           
        } elseif ( WC()->cart->cart_contents_weight < 5 ) {
           
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:8'] );
           
        } else {
           
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:6'] );
           
        }
       
      return $rates;
       
    }
    
    1. Hey Chris, thanks so much for your comment! The snippet works on my test website, so you will need to enable WP_DEBUG to know what else is breaking your website 🙂

  27. Here`s the complete php functions file
    I`m using elegant themes divi child theme
    Keeping getting site can`t be reached

    1. Sorry here`s the complete code

      
      add_filter( 'woocommerce_package_rates', ‘funsical_woocommerce_tiered_shipping', 10, 2 );
         
      function funsical_woocommerce_tiered_shipping( $rates, $package ) {
           
          if ( WC()->cart->cart_contents_weight < 6.5 ) {
            
              if ( isset( $rates['flat_rate:13’] ) ) unset( $rates['flat_rate:14’], $rates['flat_rate:15’] );
             
          } elseif ( WC()->cart->cart_contents_weight < 12.9) {
             
              if ( isset( $rates['flat_rate:13’] ) ) unset( $rates['flat_rate:13’], $rates['flat_rate:15’] );
             
          } else {
             
              if ( isset( $rates['flat_rate:13’] ) ) unset( $rates['flat_rate:13’], $rates['flat_rate:15’] );
             
          }
         
        return $rates;
         
      }
      
    2. Christian, thanks so much for your comment! Unfortunately this is custom troubleshooting work and I cannot help here via the blog comments. Thanks a lot for your understanding! ~R

  28. hi,
    the code is working fine, but it missed the tax calculation. Can you please explain?

    1. Hey Andy, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  29. Hi I need help setting up this. I have not been able to quite understand it. I tried to do it and my website was unavailable.

    Orders Below 15.84oz: $5.00
    Orders Below 72oz: $10.00
    Orders below 144oz: $15.00
    Orders below 320oz: $20.00
    Orders over 320oz: $25.00

    /**
    * @snippet Shipping by Weight | WooCommerce
    * @how-to Watch tutorial @ https://businessbloomer.com/?p=19055
    * @sourcecode https://businessbloomer.com/?p=21432
    * @author Rodolfo Melogli
    * @testedwith WooCommerce 2.6.8, WordPress 4.7
    */
     
    add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
       
    function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
         
        if ( WC()->cart->cart_contents_weight < 15.84 ) {
          
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:6'], $rates['flat_rate:8'] );
           
        } elseif ( WC()->cart->cart_contents_weight < 72 ) {
           
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:8'] );
        
        } elseif ( WC()->cart->cart_contents_weight < 144 ) {
           
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:8'] );    
           
        } elseif {
           
            if ( isset( $rates['flat_rate:5'] ) ) unset( $rates['flat_rate:5'], $rates['flat_rate:6'] );
           
        }
       
      return $rates;
       
    }
    
    
    1. Hola Marcela, thanks so much for your comment! Unfortunately this is custom troubleshooting work and I cannot help here via the blog comments. Thanks a lot for your understanding! ~R

    2. Hi Marcela, try to code it according to this code. I also have 5 shipping classes and this code works for me.

      /**
      * @snippet Shipping by Weight | WooCommerce
      * @how-to Watch tutorial @ https://businessbloomer.com/?p=19055
      * @sourcecode https://businessbloomer.com/?p=21432
      * @author Rodolfo Melogli
      * @testedwith WooCommerce 3.2.6
      */

      add_filter( ‘woocommerce_package_rates’, ‘bbloomer_woocommerce_tiered_shipping’, 10, 2 );

      function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {

      if ( WC()->cart->cart_contents_weight cart->cart_contents_weight cart->cart_contents_weight cart->cart_contents_weight < 30 ) {

      if ( isset( $rates['flat_rate:11'] ) ) unset( $rates['flat_rate:11'], $rates['flat_rate:12'], $rates['flat_rate:13'], $rates['flat_rate:17'] );

      } else {

      if ( isset( $rates['flat_rate:11'] ) ) unset( $rates['flat_rate:11'], $rates['flat_rate:12'], $rates['flat_rate:13'], $rates['flat_rate:16'] );

      }

      return $rates;

      }

  30. Hi I am trying to set up this in my shipping by weight. I have made the flat shipping fees but I set them up in wordpress to be onces. I need help setting up this to match my cart as in the example

  31. Code works great – we used this method for our US to Canada calculations. Not quite at the point of needing Table Rate Shipping yet even with 4500 SKUs and a huge mix of different products.

    1. Brilliant, great to know 🙂

  32. Thanks for the article, this really helps. Although, I’m a bit confused: isn’t ‘shipping classes’ meant for this? I was under the impression shipping zones is more geographical and classes is for anything else. If I’m wrong, I’d love an article explaining the difference between the 2.

    1. Hey Maarten, thanks for your comment!

      Shipping classes can be used to group products of similar type and used by some shipping methods, such as Flat Rate Shipping, to provide different rates to different classes of product.

      Source: https://docs.woocommerce.com/document/product-shipping-classes/

      So, shipping classes don’t really help with weight calculations. Does this help?

  33. Thank you soooo much!

    I was using a plugin for that, but that didn’t work out with WPML as the translations where somwhow cached because of the ID. This is really awesome as it unfolds some shipping-cost tweaking to me.

    1. Excellent 🙂 Glad it helped!

  34. Thanks so much! I set this up with all my U.S. shipping weights and it worked great.

    However…..that was for my U.S. shipping. My International shipping rates use the same weight, but different pricing. How do I add those in the php code? I set up 3 different shipping zones with the flat rate pricing. One for USA, one for Canada or Mexico and one for International (not Canada or Mexico).

    I would really appreciate your help if you can. 🙂

    Thank you!

    1. Hello Cindy, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom work and I cannot provide a complementary solution here via the blog comments. Thanks a lot for your understanding! ~R

  35. hi… can u share how source code to calculate each shipping by weight? i still confused about this…
    for e. g. my shipping cost 5$/kg and i need add this every 1 kilos charge 5$. and please tell me how put this code on php woocommerce thanks alot

    1. Sarah, thanks for your comment! Sorry but I can’t help you directly. Try watching https://businessbloomer.com/woocommerce-customization-hangout/ for some PHP tips

  36. Thanks a lot for your sharing. It is very useful for me without plugin.

  37. Hey,
    I have an odd question, which doesn’t quite have to do with this article, but I’ve been looking for an answer for days and this is the one thing that gets sort of close to it.
    So, I’m making a website that sells PVC banners. The product page lets you customize the size and a couple of other things, and the price changes. For that, I’ve used a plugin called Woo Price Calculator, and it works fine.
    But, of course, if the size is bigger, also is the weight and the shipping price.
    Is there a way to calculate the weight and apply the shipping prices trick from this post to it?
    Thanks.

    1. Hey Gabriele, thanks for your comment! Of course there is always a PHP way, but it would be time consuming as this is custom to your plugin. Sorry but I can’t help here in the comments 🙂

  38. Hey

    Thank you for this, it works perfectly.
    But how would I adapt this so I can add more weight bands? I would like at least another 1 option.
    Thank you.

    1. Hey Guto thanks for your comment! My snippet has 3 bands, so adding the fourth shouldn’t be a problem if you have minimal coding knowledge. Good luck 🙂

  39. Hi

    thanks for your code snippet, I just use the code snippet in one of my site and it is working.

    1. Thanks so much for your feedback Faruk!

Questions? Feedback? Support? Leave your Comment Now!
_____
If you are writing code, please wrap it between: [php]code_here[/php]. Failure to complying with this (as well as going off topic) will result in comment deletion. You should expect a reply in about a week - this is a popular blog but I need to get paid work done first. Please consider joining #BloomerArmada to ask me 1-to-1 WooCommerce questions. Thank you :)
¯¯¯¯¯

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.