A client had several shipping rates on the cart page automatically generated by FedEx, USPS, UPS and similar plugins via their API. Problem was, they wanted to sort them by price as opposed to grouping them by provider.
Thankfully, with a simple “uasort” PHP function, it’s possible to take the shipping rates array and sort it by amount before returning it back to the screen. If you don’t know PHP, simply copy/paste!
PHP snippet: Sort Shipping Rates by Price @ WooCommerce Cart/Checkout
/**
* @snippet Sort Shipping Rates by Price - WooCommerce
* @how-to businessbloomer.com/woocommerce-customization
* @author Rodolfo Melogli, Business Bloomer
* @compatible WooCommerce 7
* @community https://businessbloomer.com/club/
*/
add_filter( 'woocommerce_package_rates' , 'businessbloomer_sort_shipping_methods', 9999, 2 );
function businessbloomer_sort_shipping_methods( $rates, $package ) {
if ( ! is_array( $rates ) ) return $rates;
uasort( $rates, function ( $a, $b ) {
if ( $a == $b ) return 0;
return ( $a->cost < $b->cost ) ? -1 : 1;
} );
return $rates;
// NOTE: BEFORE TESTING EMPTY YOUR CART
}
In addition to the shipping rates I use the free “Local pickup” option which is placed at the bottom of the list, but it moves it to the top after using this code. Is there a way to exclude this option from price sorting or make it always be at the bottom of the list?
Hello Joe, 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!
Question… should I select: 1. Run Everywhere 2. Run in Admin Area 3. Only run on site front-end 4. Only run once 5. None of the above! I’m using a snippets plugin. Thanks so much for the information!
Try with frontend only
Great snippet! I’ve run across this snippet a few times where it’s run into Fatal Errors returning NULL via the WooCommerce `wc_shipping_methods_have_changed()` core function. If a filter expects a specific return type (in this case, an Array), that type should be returned. In this case, I think whatever `$rates` was when passed in should be returned if the criteria we’re looking for are not met:
Spot on! Thanks for that – snippet updated
Thanks for sharing that update @Howdy_McGee. Also that you Rodolfo! This is a simple, but effective UX update. I have used sort shipping rates on OpenCart as well. People don’t pay attention during checkout so it’s always best to have the lowest priced shipping so the total order is less and not as likely to abandon cart!
Hello. Thanks for your useful article and the codes. but I have an important question.
What we must do if change to: High to low price methods sorting?
We need help for this.
Thanks a lot.
Hi Sasha, try with $a->cost > $b->cost
Hi – is this still known to work? I have UPS and USPS live quotes, but this function seems to have no impact on the order – first it’s UPS, then USPS, even though the prices are not in order among the options. (they are ordered for UPS and ordered for USPS, but not ordered with both mixed in.
We’re hoping to see
UPS Ground – $5
USPS Standard – $7
UPS Next Day – $22
USPS 3 Day – $26
Thank you
Bill
Hi Bill! If UPS and USPS use the “WooCommerce way” to display shipping rates (and not iframes etc.) then yes, it should work. Can you try with a different theme and no other plugins than Woo, UPS and USPS?
We just found you can easily click and drag the order. WooCommerce, Settings, Shipping, Zone Name: US (Edit), UPS. You can then enable which shipping methods and click and drag the order using the 3 lines on the left.
Sure. But my fix is when you have dynamically generated shipping rates, so it works on the go
It’s working, thank you!
Awesome
It looks as if this is not working anymore 🙁
nevermind, please forget comment, it is working 🙂
Nice!
Thanks, this worked great with no modification on my site. However, I would like to sort shipping methods according to a specific list that I believe the customer prefer (the most popular alternatives at the top), or at least be able to put one option (Pick up in store) at the end of the list. How would i go about doing that?
Hi Soren, 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!
It’s possible to order from high to low? Thanks.
Of course – just play with the uasort function
Hi… this code that worked great at first but we have 2 different types of free shipping and it’s only sorting one of them to the top… any idea on how to fix that? Here is an example of what I mean…. if you add any nappies to the basket that total over $99 free shipping is listed and is shown first just as should be – Green Kids Free Shipping.
BUT… if you add drytimes incontinence products to the basket that total over $29 (free shipping threshold for that product line – make sure no nappies are in the cart or free shipping doesn’t turn on) and the Dry Times Free Shipping does not appear first but gets pushed back to last again. Any ideas why??
Hello Amanda, thanks for your comment 🙂 Are you using a custom plugin for free shipping?
Even with your January 10 comment and update, my error log is still full of this error as a result of this code:
[12-Mar-2019 22:54:34 UTC] PHP Warning: array_keys() expects parameter 1 to be array, null given in /home/account/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 468
[12-Mar-2019 22:54:34 UTC] PHP Warning: array_keys() expects parameter 1 to be array, null given in /home/account/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 439
[12-Mar-2019 22:54:34 UTC] PHP Warning: current() expects parameter 1 to be array, null given in /home/account/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 440
Any ideas?
Hey Nathan, I’ve revised the snippet. Can you try this version please?
I tried that revised snippet and unfortunately there’s no difference.
Sure it’s my snippet? Those 2 functions are not “directly” inside it, unless they are called from somewhere else
It breaks some stores because it resets the indexes
replace with
uasort($rates, function ($a, $b) { return $a->cost – $b->cost; });
return $rates;
Thanks for that Chris, much appreciated!
@Chris Awesome you’re the man. This was problem on my store when sorting shipping options. You’d select shipping option from /cart page, it would appear to make ajax call and then it would deselect option & total would not get updated. uasort did the trick. Thank you!
Hi Rodolfo,
Your snippet does what it is supposed to. However, in the cart, I get these warnings:
Warning: array_keys() expects parameter 1 to be array, null given in /home/ballsnba/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 465
Warning: current() expects parameter 1 to be array, null given in /home/ballsnba/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 437
Warning: array_keys() expects parameter 1 to be array, null given in /home/ballsnba/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 465
Warning: current() expects parameter 1 to be array, null given in /home/ballsnba/public_html/wp-content/plugins/woocommerce/includes/wc-cart-functions.php on line 437
This doesn’t bother me except I don’t want my customers to see this! Any ideas? (Caveat: I know nothing about coding; I just paste what I am given into relevant files.)
Thanks for your help.
Richard
Hello Richard, thanks for your comment! First of all, those error messages should be hidden – please use this instead: https://codex.wordpress.org/Debugging_in_WordPress#Example_wp-config.php_for_Debugging
In regard to the errors themselves, it could be you only have one shipping method in certain cases, and therefore you have no array. I’ve now added a new line to the snippet (is_array) to avoid this – let me know if those errors go away 🙂
Thanks for the snippet. I tried yours and several other people’s snippets. I could not get my shipping to sort from low to high.
Then I saw this and did it. Now it works! Great! and thanks for the snippet. 🙂
Clear Customer Sessions” via WooCommerce > Status > Tools
Excellent 🙂
Hi Rodolfo,
It works now. Just cleared the cache and cart items. Thanks and Sorry
🙂
Hello Rodolfo,
Thanks for the hook. I added this function into my theme’s functions.php but its not showing the price from low to high. I am using WooCommerce 3.2.6. Any idea?
Rams
Heads up… this seems to break “WooCommerce Advanced Shipping” with WP 4.9.4 (and possibly earlier)
Not sure why but developer informed.
Hi Martin, thanks for that! My snippets work for default WooCommerce and might not be compatible with third party plugins, so not sure there I’m afraid. I just retested this snippet in Woo 3.3.3 and it still works 🙂