WooCommerce: Free Shipping on a Per Product Basis in the Same Cart

This is a common request from WooCommerce users:

I want to ship specific products for free while some others will have shipping costs, but when a product having free shipping is in cart with another product that has shipping costs, free shipping isn’t available at all, what to do?

There’s a solution to that! And you don’t need any plugins to solve this issue. Based on a post by Mike Jolley, I’d like to explain how to use different shipping methods on a per product basis in the same cart. Let’s say you have two products, one that must be shipped for free, and a second one having a flat shipping cost (that would work with rates based on APIs as well,  like UPS, USPS, Fedex, Canada Post, Australia Post etc…). The 1st step is to create 2 shipping classes, in Products > Shipping Classes:

shipping-classes
Create at least two shipping classes

You need to create a “Free” shipping class. You can create as many other shipping classes as ou want.

The next step is to assign classes to each product:

product1
1st Product Settings
product2
2nd Product settings

Now that you assigned classes to products, you need to define flat rates per classes in WooCommerce > Settings > Shipping > Flat Rate:

flat-rates
Shipping classes flat rates

Make sure that you setup a cost equal to zero for the free shipping class.

Finally you need to filter the shipping package using custom code and separate products from one package to two packages having each its own shipping method. Add the following snippet in the file called functions.php in your theme folder:

Please note that you need to use the free shipping method slug at line 14. And the final result in the cart is the following:

cart
Shipping packages filtered in cart

That’s it! I hope that will save you some headaches! If you enjoyed this post, make sure you share it on Twitter!

Similar posts by awesome folks:

10 responses to “WooCommerce: Free Shipping on a Per Product Basis in the Same Cart”

  1. sharon

    Hi, after created my shipping classes, I went to the shipping setting ‘flat rate’ and add cost but there is no dropdown. May I know what might be possible wrong? I’m using APG shipping.

  2. mgason

    I have free shipping setup in woocommerce as available for orders over $100. I setup 2 shipping classes “allow free” and “paid shipping” I assigned them to the relevant products.
    Products are separated into 2 packages.
    package 1 paid
    package 2 allow free
    Right now if package 1 is $55, and package 2 is $50 the customer gets the free option for package 2 because the order total is over $100. I want the over $100 free shipping rule to apply to the package total not the order total. The customer should not see free shipping as an option until the value of items in package 2 with assigned “allow free” class exceeds $100
    is that possible?

  3. helga

    Salut Remi,

    What is the advantage of separating the items into 2 packages versus just eliminating the free shipping items from the package all together? Something like this:
    https://gist.github.com/helgatheviking/4db6ac3021287e4314db

    -kathy

    1. Your snippet is absolutely fine, but I wanted to highlight in this post is that you can easily separate packages on a per product basis. I used free shipping, but it could be any other shipping method.

  4. Jaydeep

    Hello Remi,

    Hope you are doing well.

    I have a query regarding adding forcefully shipping method product base. So below is my scenario.

    For Example:

    I have 3 Products.

    Product Name: Test1
    Product Price: 5
    Shipping method set = Free shipping.

    Product Name: Test2

    Product Price: 10
    Shipping method set = ‘Flat rate’ cost = 15

    Product Name: Test3
    Product Price: 15
    Shipping method set = International Flat Rate Cost = 10

    So now If I have all above product in my cart than I need below functionality:
    1. Free shipping should be disable if the product of other shipping method in cart.
    2. I need to apply both rest of the shipping method to cart.
    => Flat rate for product Test1.
    => International Flat Rate for Test2

    So my cart should look like below:

    SUBTOTAL : 30
    Flat rate shipping for Test2: 15
    International Flat Rate Cost: 10
    Total: 55

    So How can I achieve this using WooCommerce Hooks and filters. because currently all shipping method available in cart page so user can select any of the method.

    Please help me for the same.

    Thanks,
    Jaydeep

  5. Marcello

    Hi
    Thx for this code, but i have a question about so
    Can u edit code for Multivendors ?
    I have try to use this code in multivendors site, work enough good, calculate more shipping method.
    But do not report to me which shipping has used the seller, just include in all cost
    Thx

  6. jameswirth

    Hey Remi, I must be missing a step, can you advise? Some quick background:

    We sell coffee and merchandise online and have local cofee shops. One thing we sell on the site is pre-charged cards to be used in-store. When we sell these we don’t want to charge for shipping. They can be bought separately or in combination with other merch.
    Scenario 1: customer buys a coffee card only. We want to provide free shipping for this.
    Scenario 2: customer buys a coffee card + other merch. The other merch would have shipping charges, but we don’t want to add anything for the card.
    Scenario 3: customer buys other merch but no card. Normal shipping charges would apply.

    We use API shipping plugins for UPS and USPS. I see your comments say this will work but I’m not sure what I need to do differently for this.

    Here’s what I’ve done:
    1) I set up two shipping classes, one for the free product I want to ship, and a 2nd class for all other products
    2) I added flat rate shipping to the US shipping zone at zero cost
    3) I added the filter to functions.php, changing the slug to my slug in line 14.

    But when I add products to my cart, I’m not getting them broken out so I can’t independently select shopping options. And when I only have the card in the shopping cart, it’s giving me the other shipping options with charges, and I only want the free option (or free pickup) to be available.

    Any suggestions?

    Our staging site is http://woodscoffee.staging.wpengine.com/

  7. bizinbang

    Hello Remi,

    I am tried with your code but it is only working for cart, not for order details page or thank you page. Is there any way we can display shipping cost on order details page or thank you page same as cart page?

    Thanks,
    Sam

  8. tanaya

    sir i have create 3 class
    1) fertilizer class
    2)monthly class
    3)yearly class

    then at shipping zone at flat rate i have take differrent rates for different shipping class .i want 0 rs for yearly shipping class but it not works please help me

  9. yasi

    Hi Remi,

    First of all, I appreciate you and your blog. You deserve a coffee!. You did a splendid job by writing this code. Convert this code to a plugin, it will be superb!

    One question, While enabling the Free shipping rate, how to disable this option if shipping rate a is calculating real-time ( USPS, Canada Post etc) and free option is also available (at the top as an option)

Leave a Reply