Search code examples
phpwordpresswoocommerceproductshipping-method

Enable free shipping for products on sale in WooCommerce


In WooCommerce, is it possible to automatically apply free shipping to any product that is on sale?

Every month we have different products on sale, and all sale products automatically qualify for free shipping. For sale products I currently have to manually change the shipping class to "free shipping" and then back to "standard shipping" when the sale is over. I would like to automate this so any product that is on sale automatically qualifies the order for free shipping.

I can apply free shipping per product ID, but I have not been able to figure out applying this to sale products.

function wcs_my_free_shipping( $is_available ) {
    global $woocommerce;
 
    // set the product ids that are eligible
    $eligible = array( '360' );
 
    // get cart contents
    $cart_items = $woocommerce->cart->get_cart();

    // loop through the items looking for one in the eligible array
    foreach ( $cart_items as $key => $item ) {
        if( in_array( $item['product_id'], $eligible ) ) {
            return true;
        }
    }
 
    // nothing found return the default value
    return $is_available;
}
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'wcs_my_free_shipping', 20 );

Solution

  • To make free shipping available, you could use is_on_sale();

    function filter_woocommerce_shipping_free_shipping_is_available( $is_available, $package, $shipping_method ) {  
        // Loop through cart items
        foreach( $package['contents'] as $cart_item ) {
            // On sale
            if ( $cart_item['data']->is_on_sale() ) {
                // True
                $is_available = true;
                
                // Notice
                $notice = __( 'free shipping', 'woocommerce' );
                
                // Break loop
                break;
            }
        }
        
        // Display notice
        if ( isset( $notice ) ) {
            wc_add_notice( $notice, 'notice' );
        }
     
        // Return
        return $is_available;
    }
    add_filter( 'woocommerce_shipping_free_shipping_is_available', 'filter_woocommerce_shipping_free_shipping_is_available', 10, 3 );
    

    Optional: Hide other shipping methods when free shipping is available

    function filter_woocommerce_package_rates( $rates, $package ) {
        // Empty array
        $free = array();
    
        // Loop trough
        foreach ( $rates as $rate_id => $rate ) {
            if ( $rate->method_id === 'free_shipping' ) {
                $free[ $rate_id ] = $rate;
                
                // Break loop
                break;
            }
        }
        
        return ! empty( $free ) ? $free : $rates;
    }
    add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );