WooCommerce: Sort Shipping Costs from Low to High

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!

Sort shipping costs from low to high in WooCommerce
Sort shipping costs from low to high in WooCommerce

PHP snippet: Sort Shipping Rates by Price @ WooCommerce Cart/Checkout

/**
 * @snippet       Sort Shipping Rates by Price - WooCommerce
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @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
      
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

  • WooCommerce: How to Fix the “Cart is Empty” Issue
    For some reason, sometimes you add products to cart but the cart page stays empty (even if you can clearly see the cart widget has products in it for example). But don’t worry – it may just be a simple cache issue (and if you don’t know what cache is that’s no problem either) or […]
  • WooCommerce: “You Only Need $$$ to Get Free Shipping!” @ Cart
    This is a very cool snippet that many of you should use to increase your average order value. Ecommerce customers who are near the “free shipping” threshold will try to add more products to the cart in order to qualify for free shipping. It’s pure psychology. Here’s how we show a simple message on the […]
  • WooCommerce: Cart and Checkout on the Same Page
    This is your ultimate guide – complete with shortcodes, snippets and workarounds – to completely skip the Cart page and have both cart table and checkout form on the same (Checkout) page. But first… why’d you want to do this? Well, if you sell high ticket products (i.e. on average, you sell no more than […]
  • WooCommerce: Disable Payment Method If Product Category @ Cart
    Today we take a look at the WooCommerce Checkout and specifically at how to disable a payment gateway (e.g. PayPal) if a specific product category is in the Cart. There are two tasks to code in this case: (1) based on all the products in the Cart, calculate the list of product categories in the […]
  • WooCommerce: Add Privacy Policy Checkbox @ Checkout
    Here’s a snippet regarding the checkout page. If you’ve been affected by GDPR, you will know you now need users to give you Privacy Policy consent. Or, you might need customer to acknowledge special shipping requirements for example. So, how do we display an additional tick box on the Checkout page (together with the existing […]

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

40 thoughts on “WooCommerce: Sort Shipping Costs from Low to High

  1. 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?

    1. 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!

  2. 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!

  3. 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:

    if ( empty( $rates ) ) return $rates;
       
    if ( ! is_array( $rates ) ) return $rates;
    
    1. Spot on! Thanks for that – snippet updated

      1. 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!

  4. 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.

    1. Hi Sasha, try with $a->cost > $b->cost

  5. 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

    1. 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?

  6. 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.

    1. Sure. But my fix is when you have dynamically generated shipping rates, so it works on the go

  7. It’s working, thank you!

    1. Awesome

  8. It looks as if this is not working anymore ๐Ÿ™

    1. nevermind, please forget comment, it is working ๐Ÿ™‚

      1. Nice!

  9. 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?

    1. 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!

  10. It’s possible to order from high to low? Thanks.

    1. Of course – just play with the uasort function

  11. 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??

    1. Hello Amanda, thanks for your comment ๐Ÿ™‚ Are you using a custom plugin for free shipping?

  12. 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?

    1. Hey Nathan, I’ve revised the snippet. Can you try this version please?

    2. I tried that revised snippet and unfortunately there’s no difference.

      1. Sure it’s my snippet? Those 2 functions are not “directly” inside it, unless they are called from somewhere else

  13. It breaks some stores because it resets the indexes

    replace with

    uasort($rates, function ($a, $b) { return $a->cost – $b->cost; });
    return $rates;

    1. Thanks for that Chris, much appreciated!

    2. @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!

  14. 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

    1. 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 ๐Ÿ™‚

  15. 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

    1. Excellent ๐Ÿ™‚

  16. Hi Rodolfo,

    It works now. Just cleared the cache and cart items. Thanks and Sorry

  17. 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

  18. Heads up… this seems to break “WooCommerce Advanced Shipping” with WP 4.9.4 (and possibly earlier)

    Not sure why but developer informed.

    1. 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 ๐Ÿ™‚

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

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