WooCommerce – Hide Shipping Rates if a ‘free-shipping’ Shipping Class is in Cart

Conditionally show the Free Shipping option, only when a product with the ‘free-shipping’ Shipping Class is found in the cart.

If a product with the ‘free-shipping’ Shipping Class is found in the cart, it will show the Free Shipping option and hide all other shipping rates.

If a product with the ‘free-shipping’ Shipping Class is NOT found in the cart, this will hide the Free Shipping option, and only show the other available shipping rates.

Note: there is a huge caveat with this. This shows the Free Shipping option if at least 1 product in the cart has the ‘free-shipping’ Shipping Class, even if there are other products in the cart that are not supposed to be free shipping. This will give free shipping on everything in the cart.

This is useful if you want to hide free shipping, and only show this option if they add certain products to the cart, and you don’t mind that free shipping will apply to the entire cart.


  1. Go to “Products” –> “Shipping Classes” and create a shipping class named “Free Shipping.” The slug should be free-shipping. If you need to use a different name, then you must change the slug on line 47 in the code below. Change ‘free-shipping‘ on line 47 to the exact slug of your shipping class.
  2. Next, give your desired products the free shipping class. To do this, edit the product. In the Product Data metabox, click on the “Shipping” tab. For the “Shipping class,” select “Free Shipping.” Be sure to click “Update” to save your changes.
  3. Next, add the following code to your functions file.
     * Check if the cart has product with a certain Shipping Class
     * @param string $slug the shipping class slug to check for
     * @return bool true if a product with the Shipping Class is found in cart
    function cart_has_product_with_shipping_class( $slug ) {
        global $woocommerce;
        $product_in_cart = false;
        // start of the loop that fetches the cart items
        foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
            $_product = $values['data'];
            $terms = get_the_terms( $_product->id, 'product_shipping_class' );
            if ( $terms ) {
                foreach ( $terms as $term ) {
                    $_shippingclass = $term->slug;
                    if ( $slug === $_shippingclass ) {
                        // Our Shipping Class is in cart!
                        $product_in_cart = true;
        return $product_in_cart;
     * Hide other shipping rates and show Free Shipping
     * when a product with the Free Shipping Class
     * is in cart.
     * @param array $rates Array of rates found for the package
     * @param array $package The package array/object being shipped
     * @return array of modified rates
    function hide_shipping_when_free_is_available( $rates, $package ) {
     	// Only modify rates if a product with free-shipping Shipping Class is present in the cart
      	if ( cart_has_product_with_shipping_class( 'free-shipping' ) ) {
      		// To unset all methods except for free_shipping, do the following
      		$free_shipping          = $rates['free_shipping'];
      		$rates                  = array();
      		$rates['free_shipping'] = $free_shipping;
    	} else {
    		unset( $rates['free_shipping'] );
    	return $rates;
    add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
  4. Finally, go to “WooCommerce” –> “Shipping” –> “Free Shipping” and enable free shipping. Now, the Free Shipping option will only be shown when a product with the free shipping class is added to the cart. Any paid shipping rates will be hidden when the free shipping option is shown.

See more:

Questions and Comments are Welcome

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this: