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 tutoraspire.com FREE
* @author Tutor Aspire
* @testedwith WooCommerce 5.0
* @donate $9 https://tutoraspire.com
*/
add_filter( 'woocommerce_package_rates', 'tutoraspire_woocommerce_tiered_shipping', 10, 2 );
function tutoraspire_woocommerce_tiered_shipping( $rates, $package ) {
$threshold = 100;
if ( WC()->cart->subtotal