If I have a store that offers flat rate shipping of $10 and free shipping for orders over $100 and a customer orders over $100 it doesn't make much sense for them to have to see both free shipping and flat rate shipping on the checkout page. Why would a user even choose flat rate shipping?

How can I use a filter to detect if free shipping is available, filter the flat rate shipping label so it says something like flat rate shipping (free), and then disable the free shipping method.

The end result is that if a user orders less than $100 they see flat rate shipping $10 and if they order over $100 they see flat rate shipping (free!).


2 Answers 2


You can use the woocommerce_available_shipping_methods filter to do that. NB: if you have Role Based Shipping plugin you might find that it removes the Free Shipping option under some circumstances; this code puts it back if shopper has a coupon for Free Shipping.

* if Free Shipping method is available, reduce to just Free Shipping
* @param array $available_methods
* @return array
add_filter('woocommerce_available_shipping_methods', function($available_methods) {
    global $woocommerce;

    // check for coupon with Free Shipping
    if (wpse_114581_has_coupon_free_shipping()) {
        // ensure that Free Shipping is in the list of available methods (again -- Role Based Methods may strip Free Shipping for Guests)
        if (!isset($available_methods['free_shipping'])) {
            $available_methods['free_shipping'] = new WC_Shipping_Rate('free_shipping', 'Free Shipping', 0, array(), '');

    // if both Free Shipping and another method, reduce to just free shipping
    if (isset($available_methods['free_shipping']) && count($available_methods) > 1) {
        $available_methods = array('free_shipping' => $available_methods['free_shipping']);

        // change title on Free Shipping method
        $available_methods['free_shipping']->method_title = 'flat rate shipping (free!)';

    return $available_methods;

* check for coupon with free shipping
* @return bool
function wpse_114581_has_coupon_free_shipping() {
    global $woocommerce;

    foreach ($woocommerce->cart->applied_coupons as $code) {
        $coupon = new WC_Coupon($code);
        if ($coupon->is_valid() === true) {
            if ($coupon->enable_free_shipping()) {
                return true;

    return false;
  • Not counter downvoting that, but closures? Have fun removing that.
    – kaiser
    Dec 14, 2013 at 23:19
  • Closures are a bad idea for published plugins and themes, but shouldn't be a problem for website-specific customisations. Horses for courses :)
    – webaware
    Dec 15, 2013 at 0:12
  • Horses? But yeah, sure. Closures are fine. For those who don't need debugging and overriding and have PHP 5.3+
    – kaiser
    Dec 15, 2013 at 3:41
  • '"woocommerce_available_shipping_methods" filter is deprecated from WooCommerce 2.1.'
    – mirza
    Feb 20, 2019 at 20:27

I got no clue of WooCommerce, but from a brief look at their Action and Filter Reference, I can see various results for *shipping*.

Most of them seem to be located in a file named form-shipping.php:

Template Hooks: Actions

  • woocommerce_before_checkout_shipping_form
  • woocommerce_after_checkout_shipping_form
  • woocommerce_before_shipping_calculator
  • woocommerce_after_shipping_calculator
  • woocommerce_cart_totals_after_shipping
  • woocommerce_checkout_shipping
  • woocommerce_review_order_before_shipping
  • woocommerce_review_order_after_shipping

Template Hooks: Filters

  • woocommerce_cart_shipping_method_full_label
  • woocommerce_shiptobilling_default
  • woocommerce_shipping_calculator_enable_city
  • woocommerce_shipping_calculator_enable_postcode

Class Hooks: Actions

  • woocommerce_calculated_shipping
  • woocommerce_load_shipping_methods
  • woocommerce_shipping_init
  • woocommerce_shipping_method_chosen

Class Hooks: Filters

  • woocommerce_available_shipping_methods
  • woocommerce_cart_needs_shipping
  • woocommerce_cart_ready_to_calc_shipping
  • woocommerce_cart_shipping_packages
  • woocommerce_countries_shipping_to_prefix
  • woocommerce_order_amount_shipping
  • woocommerce_order_amount_shipping_tax
  • woocommerce_order_shipping_method
  • woocommerce_order_shipping_to_display
  • woocommerce_shipping_.$this->id._is_available
  • woocommerce_shipping_calculator_enable_city
  • woocommerce_shipping_calculator_enable_postcode
  • woocommerce_shipping_chosen_method
  • woocommerce_shipping_fields
  • woocommerce_shipping_method_supports
  • woocommerce_shipping_method_title
  • woocommerce_shipping_methods

I guess one of those is the one you're searching for. Maybe there's even a combination of them that you can use to even improve your idea (see that endless list as ... some kind of inspiration).

Anyway, you'll have to write a lot of test callbacks for all that filters until you got the right one. The WooCommerce documentation seems nothing aside from this endless list with the file name (w/o folder). So if you or someone else wants to deal with that: Good luck.


Not the answer you're looking for? Browse other questions tagged or ask your own question.