I have one product that is in cheap. I want to give that product away if and only if the cart subtotal is 200 or more.
If the cart subtotal is 200 or more, add the product to the cart and set the price to 0.
If the cart subtotal is less than 200, remove the product from the cart.
On adding and removing, I use a notice to inform the customer. Everything works as planned except for changing the product price.
If someone can please review the code I'm using and fix that one thing, I would be very grateful.
add_action( 'woocommerce_before_calculate_totals', 'free_product_if_cart_minimum', 10, 1 );
function free_product_if_cart_minimum( $cart ) {
// go away if admin
if (is_admin() && !defined( 'DOING_AJAX' )) return;
// say no to hook repetition
if (did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
$minimum_amount = 200;
$free_product_id = 4576;
$cart_items_total = 0;
// cart loop
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// is the free product there?
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key;
// set the price to zero
// I've tried them both without success
// $free_item_key->set_price( 0 );
// $free_product_id->set_price( $price * 0.00 );
}
// cart subtotal incl. tax and discounts
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// add the free product if not already there
if ( $cart_items_total >= $minimum_amount && !isset( $free_item_key ) ) {
$cart->add_to_cart( $free_product_id );
wc_add_notice( 'Thank you! Here\'s your free product.', 'notice' );
}
// if below the minimum, remove the free product
elseif ( $cart_items_total < $minimum_amount && isset( $free_item_key ) ) {
$cart->remove_cart_item( $free_item_key );
// display notice after removal
wc_add_notice( 'Your cart subtotal is less than 200 and therefore, the free product was removed.', 'notice' );
}
}
The following will do the job, setting the free product price to zero when it's in cart:
add_action( 'woocommerce_before_calculate_totals', 'conditionally_add_free_product' );
function conditionally_add_free_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$minimum_amount = 200;
$free_product_id = 4576;
// Initializing
$cart_subtotal = 0;
$cart_items = $cart->get_cart();
// Loop through cart items (first loop)
foreach ( $cart_items as $cart_item_key => $cart_item ){
// When free productis is cart
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key; // Free product found (get its cart item key)
$cart_item['data']->set_price(0);
}
// Get cart subtotal incl. tax and discounts (excluding free product)
else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// When cart total is up to the minimum amount, add the free product if not already there
if ( $cart_subtotal >= $minimum_amount && ! isset($free_item_key) ) {
$cart_item_key = $cart->add_to_cart( $free_product_id );
// display notice after removal
wc_add_notice( __("Thank you! Here's your free product."), 'notice' );
}
// if below the minimum, remove the free product
elseif ( $cart_subtotal < $minimum_amount && isset( $free_item_key ) ) {
$cart->remove_cart_item( $free_item_key );
// display notice after removal
wc_add_notice( sprintf(
__("Your cart subtotal is less than %s and therefore, the free product was removed."), wc_price($cart_subtotal)
), 'notice' );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.