Search code examples
phpwordpresswoocommercecart

Woocommerce conditional shipping cost reduction based on cart amount and item count


I'm looking for a way to make a custom reduction on shipping cost, based on cart total percentage, flat rate and quantity per type of product.


For 6 product : flat shipping rate 20€

  • Total cart is 120€ | Shipping cost = flat rate cost - 10% total cart | 20 - 12 = 8€
  • Total cart is 180€ | Shipping cost = flat rate cost - 10% total cart | 20 - 18 = 2€
  • Total cart is 220€ | Shipping cost = flat rate cost - 10% total cart | 20 - 22 = 0€

For 12 product : flat shipping rate 30€

  • Total cart is 120€ | Shipping cost = flat rate cost - 10% total cart | 30 - 12 = 18€
  • Total cart is 180€ | Shipping cost = flat rate cost - 10% total cart | 30 - 18 = 12€
  • Total cart is 220€ | Shipping cost = flat rate cost - 10% total cart | 30 - 22 = 8€

How can this be done?


Solution

  • This can be done without a plugin…

    1) You will need first in WooCommerce shipping settings for each shipping zone to set an amount of 1 for "Flat rate" method:

    enter image description here

    This amount will be changed in our function to 20€ from 1 to 11 items and 30€for 12 and more items. This amount will be decreased by the 10% cart total amount.


    2) Then using a custom function hooked in woocommerce_package_rates filter hook, you will be able to make a discount on shipping cost based on cart item count and on cart total.

    Here is that code:

    add_filter( 'woocommerce_package_rates', 'custom_package_rates', 10, 2 );
    function custom_package_rates( $rates, $packages ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
    
        // Get some cart data and set variable values
        $cart_count = WC()->cart->get_cart_contents_count();
        $cart_total =  WC()->cart->cart_contents_total;
        $cart_10_percent = $cart_total * 0.1;
        $flat_rate_value = 20; // Default "Flat rate" value
    
        foreach($rates as $rate_key => $rate_values ) {
            $method_id = $rate_values->method_id;
            $rate_id = $rate_values->id;
    
            if( $method_id == 'flat_rate' ){
                if( $cart_count < 6 )
                    $cart_10_percent = 0; // No percent discount
                elseif( $cart_count >= 12 )
                    $flat_rate_value = 30; // "Flat rate" value for 12 or more items
    
                $rate_cost = $flat_rate_value > $cart_10_percent ? $flat_rate_value - $cart_10_percent : 0;
    
                // Set the new calculated rate cost
                $rates[$rate_id]->cost = number_format( $rates[$rate_id]->cost * $rate_cost, 2 );
    
                // Taxes rate cost (if enabled)
                $taxes = array();
                foreach ($rates[$rate_id]->taxes as $key => $tax){
                    if( $tax > 0 ){ // set the new tax cost
                        // set the discounted tax cost
                        $taxes[$key] = number_format( $tax * $rate_cost, 2 );
                    }
                }
                $rates[$rate_id]->taxes = $taxes;
            }
        }
        return $rates;
    } 
    

    Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

    Tested on WooCommerce 3 and works.


    Refresh the shipping caches (needed sometimes):
    1) First empty your cart.
    2) This code is already saved on your function.php file.
    3) Go in a shipping zone settings and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done and you can test it.