I would like to know if it is possible to enable free shipping with Woo Commerce only if certain items (or items of certain categories / shipping classes) are included in the cart.

The Free Shipping option only activates on the basis of cart value or via a coupon code so I investigated Flat Rate shipping and discovered that it prioritises the most expensive shipping class over the cheaper ones. This means the free shipping class I created never overrides the default charge.

I understand the logic behind this but it's the opposite of what I need as the idea is to incentivise purchases of higher profit margin products by eliminating delivery charges when they're included in an order.

I don't know if what I am trying to achieve is simply not possible within Woo Commerce. A coupon that only applies to certain products / categories seems to be the closest I can get but I'd rather not force users to enter a code at checkout.

Does anybody know if there any simpler ways to give users who purchase certain products free shipping?

  • 4
    How on earth did this Wordpress plugin related question, upvoted 8 times and favourited 3 times by Wordpress developers get closed as "off-topic" O.o
    – Ben
    Commented Apr 23, 2015 at 4:18
  • @Ben because it's a WooCommerce plugin, and not a WordPress specific question (as stated in the help centre) Commented Oct 31, 2019 at 10:54
  • This question is were I ended up when trying to search for this problem. Therefore I would like to share a newer link for visitors. This is from Wocommerce own Docs and is not 7 years old. This answers the question with a snippet put in the functions.php woocommerce.com/document/… Commented Dec 16, 2021 at 12:06

6 Answers 6


Perhaps this doesn't fully answer your question, but the table rate shipping plugin does give you the option to set a priority for a particular rate. Furthermore, this discussion gives a lot of hints as to where you could look for solutions

  • Thanks. Looking at the documentation for Table Rate Shipping it appears that it will do what I need it to. If my employer goes for the licence I'll update on whether it's of use. Commented Mar 15, 2013 at 11:00
  • Please don't post links to outside resources. Rather summon them here and use the link on top of it. If the link goes, the answer is useless and we're having a hard fight preventing link rot. -1
    – kaiser
    Commented Sep 6, 2013 at 20:48

Does anybody know if there any simpler ways to give users who purchase certain products free shipping?

Actually, when creating a product you can just mark it as a Virtual product right within the product editor and that will exclude shipping completely for that item.

  • 1
    This works for simple products, but not for other types of products -- variable, for example. Nice try though. This will probably work for some people. Commented Sep 6, 2013 at 20:45
  • Why doesn't this work for variable products? You can mark each variation as virtual.
    – BFTrick
    Commented Sep 17, 2013 at 19:37
  • I agree @BFTrick
    – Nathan
    Commented Sep 18, 2013 at 18:09
  • 2
    This is also bad because the system won't access for the customer's SHIPPING address, which is pretty important ;)
    – Kane
    Commented Apr 13, 2015 at 22:37

Here's a snippet colleted from some Gists out of a GitHub issue discussion linked by @Ewout in another answer. I added a var_dump(), so you can uncomment and check what exactly you want to remove.

$available_methods is an array of:

$available_methods as $method_id => $method

Compare against $method_id if you need more specific checks.

// Hide standard shipping option when free shipping is available
add_filter( 'woocommerce_available_shipping_methods', 'wpse90835_hide_standard_shipping_when_free_is_available' );
 *  Hide Standard Shipping option when free shipping is available
 * @param array $available_methods
function wpse90835_hide_standard_shipping_when_free_is_available( $available_methods )
    // Developers!: Dump this to see what you can unset
    # var_dump( $available_methods );

    // remove standard shipping option
    if ( 
        isset( $available_methods['free_shipping'] ) 
        AND isset( $available_methods['flat_rate'] )
        unset( $available_methods['flat_rate'] );

    return $available_methods;

I've created a WooCommerce plugin which allows users to configure advanced settings for free shipping. In the plugin it is possible to select certain products for free shipping.

You can find the plugin free on wordpress.org called WooCommerce Advanced Free Shipping

Hope this helps.


Based on kaiser's code (above) I have created the following code:

 *  Hide free shipping option when Standard Shipping is available
 * @param array $available_methods
function mwe_hide_free_shipping_when_standard_shipping_is_available($available_methods) {

    // remove standard shipping option
    if (isset($available_methods['free_shipping']) AND isset( $available_methods['flat_rate'])) {

    return $available_methods;
add_filter('woocommerce_available_shipping_methods', 'mwe_hide_free_shipping_when_standard_shipping_is_available');

And in turns of setting up WooCommerce, I have Free Shipping and Flat Rate both enabled in the Woo Shipping Options. Then I just set up a Shipping Class, specify it's cost (e.g., £7.95) in the Flat Rate options page, and then just add that shipping class to the products I want to charge £7.95 p&p for.


The "virtual" option will remove all shipping costs, but it also deletes the option to ship to a different address than the customer's billing address. This isn't an issue if the customer buys other, non virtual products as well, but is if it's the only thing they buy.

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