WooCommerce shipping fee that changes when condition is met

WooCommerce has a great documentation about shipping fees. Documentation can be found here. However, there are times we have a more complex requirements that can’t be done by default. In those times, this is the reason why this post has been published.

A simple way of changing the shipping fee using code is this:

1
2
3
4
5
6
7
8
9
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates' );
function woocommerce_package_rates( $rates ) {
 
	foreach($rates as $key => $rate ) {
		$rates[$key]->cost = 10;
	}
 
	return $rates;
}

Above will set all your shipping methods rate to 10. We can add conditional statement to make it more fun. Something like this:

1
2
3
4
5
6
7
8
9
10
11
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates', 10, 2 );
function woocommerce_package_rates( $rates, $package ) {
 
	$new_cost = ( WC()->cart->subtotal < 10 ) ? 4.5 : 2.5;
 
	foreach($rates as $key => $rate ) {
		$rates[$key]->cost = $new_cost;
	}
 
	return $rates;
}

Above will set all your shipping methods rate depending on your cart’s sub total. When it’s less than 10, the cost will be 4.5, otherwise it will be 2.5.
More fun isn’t it?

Now here’s a more complex example just to light up everything.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates', 10, 2 );
function woocommerce_package_rates( $rates, $package ) {
 
	if ( ! WC()->cart->is_empty() ) {
		$required_products = array( 47,31 );
 
		$found = 0;
 
		foreach ( WC()->cart->get_cart() as $cart_item ) {
			if ( in_array( $cart_item['product_id'], $required_products ) && ( $cart_item['quantity'] >= 20 ) ) {
				$found++;
			}
		}
 
		if ( $found == sizeof( $required_products ) ) {
			foreach($rates as $key => $rate ) {
				$deduction = 0;
				if( WC()->cart->subtotal > 1500 ) {
					$deduction = $rates[$key]->cost;
				} elseif ( $rates[$key]->label == 'Via Air' ) {
					$deduction = 5;
				} elseif ( $rates[$key]->label == 'Via Land/Sea' ) {
					$deduction = 10;
				}
 
				$rates[$key]->cost = max( $rates[$key]->cost - $deduction, 0 );
 
				if ( ( $rates[$key]->cost < 1 ) && ( $rates[$key]->label !== 'Free Shipping' ) ) {
					$rates[$key]->label .= ' : Free Shipping';
				}
			}
		}
	}
 
	return $rates;
}

I would want to explain that but here’s a gif of what it will do.

And for my last example, this one will show Free shipping only if a certain product is on the cart.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates', 10, 2 );
function woocommerce_package_rates( $rates, $package ) {
 
	if ( ! WC()->cart->is_empty() ) {
		$required_products = array( 34 );
 
		$found = false;
 
		foreach ( WC()->cart->get_cart() as $cart_item ) {
			if ( in_array( $cart_item['product_id'], $required_products ) ) {
				$found = true;
			}
		}
	}
 
	if ( !$found ) {
		foreach($rates as $key => $rate ) {
			if ( $rates[$key]->label == 'Free shipping' ) {
				unset($rates[$key]);
			}
		}
	}
 
	return $rates;
}

I hope with this, you can create your more complex conditions for the shipping fees.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *