Black Friday & Cyber Monday SUPER SALE ALL WEEK:
Grab 40% OFF on plugins
Days
Hours
Minutes
Seconds

How to Apply a BOGO Rule as ‘Buy 2 Get 1 Free’ Recursive Discount in WooCommerce?

Recursive Discounts in WooCommerce

Discover how to apply a recursive discount in WooCommerce such as ‘Buy 2 Get 1 Free’, to offer customers additional value for their purchases. So with this approach, you can allow customers to receive an additional product at a discounted price.

Moreover, it is possible to apply the recursive bogo rule for the same product. But here in this guide, we will explore how to implement recursive discounts using two different products, where A represents the main product and B denotes the free product.

Solution: Implement ‘Buy 2 Get 1 Free’ Recursive Discount in WooCommerce

The code is designed to implement a “Buy N Get N/2” discount logic for the automatically added product according to the following criteria:

Buy 2 Parent Product and get 1 Free Product at a discount.
Buy 4 Parent Product and get 2 Free Product at a discount.
Buy 6 Parent Product and get 3 Free Product Price at a discount and so on.

add_action('woocommerce_cart_calculate_fees', 'ts_discount_and_free_product_based_on_quantity', 10, 1);
add_action('woocommerce_before_calculate_totals', 'ts_set_free_product_price_to_zero');

function ts_discount_and_free_product_based_on_quantity($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    $parent_product_id = 54;
    $free_product_id = 917;

    // Get the price of the specified products
    $parent_product_price = wc_get_product($parent_product_id)->get_price();
    $free_product_price = wc_get_product($free_product_id)->get_price();

    // Initialize the discount amount based on the quantity of the parent product
    $parent_quantity = 0;

    // Check if the parent product is in the cart
    foreach ($cart->get_cart() as $cart_item) {
        if ($cart_item['product_id'] == $parent_product_id) {
            $parent_quantity = $cart_item['quantity'];

            // Check if the parent quantity is an even number (2, 4, 6, 8, ...)
            if ($parent_quantity % 2 == 0) {
                // Calculate the number of times the discount should be applied based on the parent product quantity
                $discount_applications = $parent_quantity / 2;

                // Calculate the total discounted price
                $discounted_price = $discount_applications * $free_product_price;

                // If the discount is applied, display a custom notice
                if ($discounted_price > 0) {
                    wc_clear_notices();
                    wc_add_notice(sprintf(
                        __("Congratulations! Buy %d, get %d free product(s).", 'your-text-domain'),
                        $parent_quantity,
                        $discount_applications
                    ), 'success');

                    // Add a custom fee for the discounted amount
                    $cart->add_fee(__("Discount for Free Product"), -$discounted_price, true);
                    
                    // Check if the free product is not already in the cart
                    $free_product_cart_id = WC()->cart->generate_cart_id($free_product_id);
                    $free_product_in_cart = WC()->cart->find_product_in_cart($free_product_cart_id);

                    // If the free product is not in the cart, add it
                    if (!$free_product_in_cart) {
                        WC()->cart->add_to_cart($free_product_id);
                    }
                }
            }

            // Adjust the price of the parent product in the cart item
            $cart_item['data']->set_price($parent_product_price);

            break; // Exit the loop after finding the parent product
        }
    }

    // Check if the free product is in the cart
    $free_product_in_cart = WC()->cart->find_product_in_cart($free_product_id);

    // Loop through cart items
    foreach ($cart->get_cart() as $cart_item) {
        // Check if the current item is the parent product
        if ($cart_item['product_id'] == $parent_product_id) {
            // Adjust the price of the parent product in the cart item
            $cart_item['data']->set_price($parent_product_price);

            break; // Exit the loop after finding the parent product
        }
    }

    // Adjust the price of the free product after subtotal calculation
    if ($free_product_in_cart) {
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            if ($cart_item['product_id'] == $free_product_id) {
                // Modify the item price to include the original price with strikethrough
                $original_price = wc_get_product($free_product_id)->get_regular_price();
                $cart_item['data']->set_price($original_price);
                break;
            }
        }
    }
}

function ts_set_free_product_price_to_zero($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    $free_product_id = 917;

    // Loop through cart items
    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        if ($cart_item['product_id'] == $free_product_id) {
            // Set the price of the free product to 0
            $cart_item['data']->set_price(0);
            break; // Exit the loop after finding the free product
        }
    }
}

// Function to modify cart item price to include original price with strikethrough
function ts_modify_cart_item_price($price, $cart_item, $cart_item_key) {
    $free_product_id = 917; // Product ID of the free product
    $original_price = wc_get_product($free_product_id)->get_regular_price();

    if ($cart_item['product_id'] == $free_product_id) {
        // Modify the item price to include the original price with strikethrough
        $price = sprintf(
            '<del>%s</del> %s',
            wc_price($original_price), // Format the original price
            $price // Keep the current price
        );
    }

    return $price;
}
add_filter('woocommerce_cart_item_price', 'ts_modify_cart_item_price', 10, 3);
flexi bogo cta banner image


This to the shop owners who are running or planning to run BOGO offers on their WooCommerce store…

BOGO deals are great for increasing your sales, but have you thought about which offers are bringing you more revenue and which offers are not performing that great?

Don’t just set a BOGO deal, track the revenue generated by your deals in real-time with the Flexi BOGO for WooCommerce plugin.

Output

When the specified parent product A is added to the cart, and based on the quantity of the parent product the code provides a discount on the free product B. When there are 2 units of the parent product in the cart, the free product is automatically added to the cart with a discount equivalent to 1 unit of the free product.
Also, the user gets a notice about the discount, and if the above-mentioned conditions are met, the free product is added to the cart with the calculated discount.

Apply a BOGO Rule as 'Buy 2 Get 1 Free' Recursive Discount

To increase your store’s average order value, consider implementing dynamic bulk WooCommerce discount tiers based on quantity. This strategy can effectively optimize pricing based on selected quantity tiers.

Browse more in: Code Snippets, WooCommerce How Tos, WooCommerce Tutorials

Share It:

Subscribe
Notify of
0 Comments
Newest
Oldest
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x