The new shipping zone management that was introduced with Woo 2.6 gives us the chance to add flat rate, free shipping and local pick-up methods by default.
But what if a client requires 3Β different rates depending on the order amount (tiered shipping)? For example:Β “For orders up to $100, shipping = $5; for orders up to $250, shipping = $2; for orders above $500, shipping = free”.
Is this possible without using a plugin? Well, the answer, as usual, is absolutely yes! Enjoy!
1. Tiered Shipping – Shipping Zone Setup
Go to WooCommerce > Settings > Shipping and create your shipping zone. In the example, I will target US customers and add 3 shipping methods to it: Flat Rate, Flat Rate and Free Shipping.
2. Tiered Shipping – Shipping Methods Setup
Open each one of the shipping methods previously added to the zone and rename them / set them up like this:
- Flat Rate #1 > rename to “Orders Below $100” and assign cost = $5
- Flat Rate #2 > rename to “Orders Below $250” and assign cost = $2
- Free Shipping > select “Requires a minimum order amount” = $500
Here’s one of the method’s setup:
3. Tiered Shipping – PHP Snippet
Now we need to “tell” WooCommerce that, based on the order amount, a Flat Rate should be used instead of the other. Only in this way we can show the correct shipping method to the end user.
First, take a note of the unique ID of the two flat rates. They should look look something like “flat_rate:9“. For more info on how to find it, check the “How to Find Shipping Class ID” paragraph here: https://businessbloomer.com/woocommerce-disable-free-shipping-if-cart-has-shipping-class
Second, let’s code! We’ll need to “unset” flat rate #2 if we are under $100, otherwise we’ll require to “unset” flat rate #1.
/**
* @snippet Tiered Shipping Rates | WooCommerce
* @how-to Get CustomizeWoo.com FREE
* @author Rodolfo Melogli
* @testedwith WooCommerce 5.0
* @community https://businessbloomer.com/club/
*/
add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
$threshold = 100;
if ( WC()->cart->subtotal < $threshold ) {
unset( $rates['flat_rate:1'] );
} else {
unset( $rates['flat_rate:2'] );
}
return $rates;
}
Hi there,
Added this code, changing the amount to 30 (Β£30) but when the threshhold is below 30 it only shows the option for flat_rate:6.
It's not showing any errors so not sure what I'm doing wrong.
Your code hides Flat Rate 1 below 30 (so the only remaining is Flat Rate 6)
Is there a way to have it just change UPS Ground to $5.00 to override the UPS LIVE RATES calculated?
I don’t know of a command to have it update the price.
If UPS uses the “WooCommerce way” of returning rates, and it’s therefore possible to override them, then yes
Code isn’t working for me, not sure if it’s outdated or not compatible with our theme. Using eStore theme.
Only 2 shipping methods:
flat_rate:1 is over $100
flat_rate:5 is under $100
Thanks for any thoughts!
Hi Joe! Have you tried emptying the cart before testing the shipping conditional?
Did exactly what I needed and saved me from installing yet another plugin. Thank you!
Awesome!
Hi,
Thank you for this code, works beautifully! Is it possible to calculate the cart total after discounts and replace shipping methods based on that?
Thanks!
Hey Devi! Sure, that sounds possible. Check the other cart totals functions here and you should find the solution: https://www.businessbloomer.com/woocommerce-get-cart-info-total-items-etc-from-cart-object/
Cart total seems to be optimal way of doing it.
How to change it? im not developer, so that guide you link to did not help
For example, you can sub “WC()->cart->subtotal” with “WC()->cart->total”. Let me know if it works
Hi,
I am trying to replace a flat rate shipping method with another with a threshold of $250, using this code, but gives the error –
syntax error, unexpected ‘function’ (T_FUNCTION)
The code I used is
Could be a problem with your single quote symbols – you need to use -> ‘ and not “backticks”. Otherwise the problem is not related to my snippet
HI
Thank you for the code.
How can I add a notice to the customer?
I need the customer to know that there has to a minimum amount, to be able to choose shipping?
I have only 2 options available for customer:
1. Local pickup
2. Shipping if amount in cart is minimum 400
Hi Helle thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello,
I have a $15 shipping cost for orders less than $150 and free shipping for over than that. I write this code and tried it several times but it’s not working.
Would you please tell me where the problem is?
You’re unsetting the opposite thing
Hello,
I am just trying to create a $5 charge on a bill amount of less than $150. Free shipping above $150. Should I remove the Else condition?
I am new to this and trying to learn things. This is my first demo project. This might sound naΓ―ve π
;
No prob at all. You can do that from the Woo settings!
Hi! Great post! How can I limit it to certain categories?
I suggest you take a look at “conditional logic”: https://businessbloomer.com/woocommerce-conditional-logic-ultimate-php-guide/. Enjoy π
Woah thank you so much for this!
What about if I want a flat rate of Β£7 for the first item in the cart and then an additional Β£4 for each additional item thereafter? Is this possible using similar code to this?
Thank you
Hello Charlotte, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Thanks so much for all of your help. These tutorials are a life saver! I can always find just what I’m looking for and I appreciate that so much!
Thank you!
Bonjour,
Merci pour ce code! Comment conserver l’option Point de vente quand mΓͺme?
Guylaine
Guylaine, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello, I use this usefull code ans it works prefectly on my website ! So thanks a lot Rodolfo ! I try now to add a new condition with the cart amount, especialy when it’s higher than 80β¬. This is the last part of the code beloow but it doesn’t work… I’m sure there is an issue but I’m not able to fix it. Could you take a look on it ? Sorry for my english, I’m French… π
Here is the long code :
Hey Philippe, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello, thank you for this code. Really useful. Is it possible to make it taxable?
Thank you in ahead!
You can do that from the shipping rate settings I believe
Hello, thank you for the amazing code! It’s working well for me with three shipping options, however, if the customer updates the quantity (and therefore moves to the next threshold) directly on the “cart” page, it displays all shipping options. Any idea why this would be happening? Thanks so much!
Hello Kyle, I just tested this again with Storefront theme and it works perfectly. Maybe your theme (or another plugin) is messing/conflicting with my snippet?
To troubleshoot, disable all plugins but WooCommerce and also switch temporarily to “Twentyseventeen” theme (load the snippet there in functions.php) – does it work? If yes, you have a problem with your current theme or one of the plugins.
Hope this helps!
R
LOL – I am not adding any value here, but I was impressed by the fact that you responded to everyone who left a message! That is excellent customer interaction!
Ah, thank you!
Hi Rodolfo,
My product prices are priced offering Free shipping from zones 1-4. When a customer buys a product and the postcode recognises this as Zone 5 or above the product price needs to increase by Β£15 per shipment if the customer orders more than 1. Is there a way where I can charge per shipment? I have tried applying “Flat Rate” but the shopping cart only recognizes this as one chargeable item. Is there something you can suggest that will do that for my customers or a plugin?
Currently I’m working on my woocommerce website so it’s not live yet.
Hello Jay, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hi Rodolfo and thank you so much in advance for your suggestion.
I would like to set up extra fee only for Cash Payment past package received when order is up to 25 β¬.
Can you help me ?
thanks
Hello Roberto, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hi this snippet works perfectly on the cart page but for some reason not calculating correctly on the checkout page, any ideas?
Hello Jon, thanks so much for your comment! I just retested this on the latest version of WooCommerce and it still works. Unfortunately this looks like custom troubleshooting work and I cannot help here via the blog comments. Thanks a lot for your understanding! ~
Great article. I tried this out but it still shows all the choices instead of just the one for the correct range. Does this work with other extensions also installed like the UPS and USPS ones from WooCommerce?
Hey Patrick! Did you empty the Cart before re-testing? Also, it depends on how UPS / USPS are coded, I don’t think they’re shipping rates are called “flat_rate:18” – they’re possibly something else.
I have similar code with the same problem – but only on the 3rd shipping rate.
Hello Jessica, thanks for your comment! I think you have an issue in the first IF π
How Can I Write this in code? I tried but it show wrongly.
I have THREE
$65 Above – FREE SHIPPING
33 Above – $8
0 to 32 – $15
Hello Vir, 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
I’m struggling with shipping fees right now. I already have states and cities enabled, the problem now is: how to add cities into the calculation. I mean, if a customer is buying from city X (state A) fee is going to be $5, but if he purchases from city Y ( State A), fee would be $9. Do you have any idea on how to do it?
Hello Yara, 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
Here is the code I added for three different shipping options based on quantity in the cart:
I made this tutorial: https://www.easywebdesigntutorials.com/adjust-shipping-price-when-quantity-changes/
Excellent, thanks Paal!
Hi there, When I post the php code for this the latest version of WordPress rejects it with multiple ‘Unexpected Token’ errors. Ive double checked all the ‘ and , punctuation and it seems fine.
Can anyone suggest anything that may be causing this please?
Here is a screengrab of the errors: https://www.dropbox.com/s/el65759iea14zqh/Unexpected%20Token%20errors.png?dl=0
Thanks in advance! π
Sorry, I was putting the code into the css, I’ve tried it in the functions and now I get:
Your PHP code changes were rolled back due to an error on line 28 of file wp-content/themes/uk-cbd-oil/functions.php. Please fix and try saving again.
syntax error, unexpected ‘add_filter’ (T_STRING)
Here is a screengrab again π
https://www.dropbox.com/s/fc5ihk2x9qidugw/string_error.png?dl=0
Hey Brian, that’s the weirdest PHP error I’ve ever seen π Do you have this at the beginning of the file:
Rodolfo,
Very helpful snippet and I almost have it working. I have two levels; less than $100, less than $200 then anything over $200 is free shipping. Shipping costs display properly until I exceed $200 in my cart total then both the Free Shipping option and Less than $200 option appears. How do I get rid of the Less than $200 option?
Thank you.
Hey there, thanks for your comment! You can use this snippet: https://businessbloomer.com/woocommerce-hide-shipping-options-free-shipping-available/
I’m trying to do something a bit more advanced because my client has three different flat rate tiers as well as two free shipping tiers. Idea is when you hit $100, the free shipping should trigger but also so should a flat rate tier for expedited shipping and the first two flat rate tiers go away. This isn’t working for me, but am I at least in the right ballpark?
Hey Adam, thanks so much for your comment! I don’t see anything wrong with this, try emptying the Cart before testing again π
Sorry i posted on the wrong post. This code works great on woocomerce 3.2.6 and WordPress 4.9.1. Also in theme-functions.php file. i had to add some custom code of mine also but it works like a charm.
Thank you guys, i really appreciate
Cool π
I was wondering if there is a way to charge 2.50 if an order is over $300 for the signature required but have customers be able to waive the signature and 2.50 charge if they don’t want to sign for it. is this possible?
Hello Connor, 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
Hi is there anyway to simply change the free shipping trigger to occur based on the subtotal (i.e. not effected by he use of coupons) rather than the order total?
Thanks
Z
Zed, thanks for your comment! Yes, sure, you can do that. You just need to find the correct order total function: https://docs.woocommerce.com/wc-apidocs/class-WC_Order.html
Is it possible to assign both the country and total suborder based shipping cost in this php code. Please help me
Hey Gopinathan, 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
Hi Rodolfo, how much would you charge for implementing this for me?
Wesley, thanks so much for your comment! If you’d like to get a quote, feel free to contact me here. Take care π
Done, thank you sir.
Thank you!
Thank you, this was super handy! Worked absolutely perfectly!
Thanks Nicola π
Hi Rodolfo,
I am new to php and I’m looking to create different “thresholds” to different shipping zones. For example, shipping zone A needs a minimum spend of 100 in order to get free shipping; and shipping zone B needs to spend 200 for free shipping. How would I implement this into the code you provided? Is it even possible lol. Thank you so much!
Hey Thy, thanks for your comment! Yes, of course this is possible, but I’m afraid it’s custom work and I can’t help via the blog comments. Thank you π
Sorry, I didn’t wrap the php
Hey Jamie, thanks so much for your comment! Yes, this is possible – but unfortunately this is custom troubleshooting work and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R
I understand. Thank you π
π
Hello,
Great article! Really helpful. I’m looking to implement tiered shipping options like this:
up to Β£200.00 Β£ 10.00
Β£200.00-Β£400.00 Β£ 20.00
Β£400.00-Β£800.00 Β£ 30.00
Β£800.00 and Over Β£ 60.00
I’ve written the following, but it’s not working. Any glaring errors that you can see?
$threshold1 = 200;
$threshold2 = 400;
$threshold3 = 800;
if ( WC()->cart->subtotal cart->subtotal cart->subtotal < $threshold3 ) {
unset( $rates['flat_rate:1'], $rates['flat_rate:2'], $rates['flat_rate:7'], );
}
return $rates;
Thank you,
Jamie
Hi there,
This code looks great to use but I was wondering what to do if I only have one flat rate meaning orders up until 250 euros require shipping costs and above it’s free.
Thanks!
Hey Delana, thanks for your comment π You need no snippet for that! Just create 2 shipping methods, and set up the Free Shipping with a minimum threshold π
I have 5 rates, ranging from $0 to > $100, do I repeat this block 5 times and just change the amount?
[php]
$threshold = 100;
if ( WC()->cart->subtotal < $threshold ) {
if ( isset( $rates['flat_rate:1'] ) ) unset( $rates['flat_rate:2'] );
} else {
if ( isset( $rates['flat_rate:2'] ) ) unset( $rates['flat_rate:1'] );
}
return $rates;
{/php]
Hey Liz! No, you’d do something like this:
Hi Rodolfo,
I didn’t see your response here til today when I got back to working on this. Thank you for the model of what to use!!! How do you indicate a threshold for everything above a dollar amount? Threshold 6 is for everything above $100. The other thresholds (have no idea what happened to #2) all calculate properly in the cart but once I have over $100 of products, it displays all of the price points. Site is still in progress ..
Liz, in that code you have a big problem π
When you check:
this also triggers when:
So, you have to work with those ranges and make sure every elseif does not override the previous one.
Hope this helps
This is exactly the solution I was looking for but in my case I have three flat rates (No free shipping):
Orders up to $50 in value = $10 for shipping
Orders from $51-$100 in value = $20 for shipping
Order above $100 in value = $30 for shipping
Do I have to define three different threshold variables? Any guidance would be greatly appreciated.
Stella, thanks for your comment and corect, you’ll need to define a second threshold and do some more work with the if>else in PHP. Good luck π
Hi there,
Currently I’ve got 2 Shipping Zones, one Zone for specific Post Code areas and I’ve followed the tutorial and got it working just fine.
However, in the second Zone for everywhere else I’ve got the same shipping methods setup (but with different prices) but just not sure how to apply them to the snippet?
Darren, thanks for your comment! I’m afraid it’s not 100% clear what you’re trying to achieve. Can you link to a screenshot of your settings and explain your objective again? Thank you π
Precisely what I’ve been looking for for ages, thanks!
Expanding on this method I was also able to unset other superfluous delivery options that had free versions of themselves over a certain amount.
Brilliant, thanks for your feedback Andrew!
Hi Rodolfo,
So sorry I missed your reply back in March.
So basically we’ve got two Shipping Zones – one for Local – Tiered Shipping which we’ve used the code you provided and that works fine – https://pasteboard.co/g432wor4e.png as you can see the shipping option shows based on price (plus a local collection option which is fine).
We’ve got a second Shipping Zone – Rest of UK – Tiered Pricing and want to use the same code or adapt the code. At the moment this is what the checkout page looks like – https://pasteboard.co/g3WO1BxAF.png
So you can see the customer select their shipping price, we would like the shipping to be based on their Subtotal.
So we’d like to be able to adapt the code so that it can be used for both Shipping Zones – Local – Tiered Shipping and Rest of UK – Tiered Pricing.
Hope that makes sense? Darren
Darren, thanks so much for your comment! Yes, it makes sense and it is possible – but unfortunately this is custom work and I cannot provide a complementary solution here on the blog. Thanks a lot for your understanding! ~R