Search code examples
phpwordpresswoocommerceproductcart

Free Give-Away product for specific cart subtotal in WooCommerce


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' );
    }
}

Solution

  • 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.