Search code examples
phpwordpresswoocommercediscount

Shipping discount in WooCommerce based on cart subtotal


I want to activate a shipping cost discount based on the cart subtotal.

Examples:

  • Order subtotal above R$ 350 -> get 50% of Shipping Discount
  • Order subtotal above R$ 450 -> get 70% of Shipping Discount

Therefore, I use the following code:

add_filter( 'woocommerce_package_rates', 'fa_woocommerce_package_rates', 10, 2 );
function fa_woocommerce_package_rates( $rates, $package ) {

    foreach ( $rates as $key => $rate ) {
        $cost = $rate->get_cost();

        // todos os métodos
        $rate->set_cost( $cost * 0.5 ); // 0.5 = 50%

        $rates[ $key ] = $rate;
    }

    return $rates;
}

It works, but i'm struggling to make these rules. Any help would be apreciated.


Solution

  • To determine the shipping discount based on the subtotal you can use the 2nd argument passed to the filter hook, namely: $package. Then you use: $package['cart_subtotal']

    So you get:

    function filter_woocommerce_package_rates( $rates, $package ) {
        // Get subtotal
        $subtotal = $package['cart_subtotal'];
        
        // Greater than
        if ( $subtotal > 350 ) {
            // 50% discount
            $percentage = 50;
    
            // If more, adjust percentage
            if ( $subtotal > 450 ) {
                // 70% discount
                $percentage = 70;
            }
    
            // Loop trough
            foreach ( $rates as $rate_id => $rate ) {
                // Get rate cost
                $cost = $rate->get_cost();
    
                // New rate cost
                $rate->set_cost( $cost - ( $cost * $percentage ) / 100 );
            }
        }   
        
        return $rates;
    }
    add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
    

    To target certain shipping methods, change:

    // Loop trough
    foreach ( $rates as $rate_id => $rate ) {
        // Get rate cost
        $cost = $rate->get_cost();
    
        // New rate cost
        $rate->set_cost( $cost - ( $cost * $percentage ) / 100 );
    }
    

    To:

    // Loop trough
    foreach ( $rates as $rate_id => $rate ) {
        // Get rate cost
        $cost = $rate->get_cost();
    
        // Targeting shipping method, several can be added, separated by a comma
        if ( array_intersect( array( $rate->method_id, $rate_id ), array( 'flat_rate', 'flat_rate:3' ) ) ) {
            // New rate cost
            $rate->set_cost( $cost - ( $cost * $percentage ) / 100 );
        }
    }
    

    Hint: for debugging purposes you can temporarily use the second part from this answer