After my previous question WooCommerce discount: buy one get one 50% off I want to add custom notice to the cart, whenever a particular product(not all the products) gets added to the cart.
I want to check the quantity first, if it's 1 then I want to display a notice to increase the quantity of that product. I have figured something by myself from the internet and I don't think my solution is right:
add_action( 'wp', 'sp_custom_notice' );
function sp_custom_notice() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
//to display notice only on cart page
if ( ! is_cart() ) {
return;
}
global $product;
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
if($product_id == 15730){
//check for quantify if equal to 1 in cart
wc_clear_notices();
wc_add_notice( __("Add one more to get 50% off on 2nd product"), 'notice');
}
}
It will be great if anyone can help me on this.
Updated July 2020
If you are still using the code from my answer to your previous question, you can change it a bit to get this working too:
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// YOUR SETTINGS:
$targeted_product_id = 40; // Set HERE your targeted product ID
// Initializing variables
$discount = $qty_notice = 0;
$items_prices = array();
// Loop through cart items
foreach ( $cart->get_cart() as $key => $cart_item ) {
if( in_array( $targeted_product_id, [$cart_item['product_id'], $cart_item['variation_id']] ) ){
$quantity = (int) $cart_item['quantity'];
$qty_notice += $quantity;
for( $i = 0; $i < $quantity; $i++ ) {
$items_prices[] = floatval( $cart_item['data']->get_price());
}
}
}
$count_items = count($items_prices); // Count items
rsort($items_prices); // Sorting prices descending order
if( $count_items > 1 ) {
foreach( $items_prices as $key => $price ) {
if( $key % 2 == 1 )
$discount -= number_format( $price / 2, 2 );
}
}
// Applying the discount
if( $discount != 0 ){
$cart->add_fee('Buy one get one 50% off', $discount );
// Displaying a custom notice (optional)
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( __("You get 50% of discount on the 2nd item"), 'notice');
}
}
// Display a custom notice on cart page when quantity is equal to 1.
elseif( $qty_notice == 1 ){
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( __( "Add one more to get 50% off on 2nd item" ), 'notice');
}
}
}
Code goes in functions.php file of your active child theme (or active theme) Tested and works.
Note: The wc_add_notice() function absolutely don't need to be echoed
You did pretty good code some minor changes are required try below code :
add_action('woocommerce_before_cart', 'sp_custom_notice');
function sp_custom_notice() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
//to display notice only on cart page
if ( ! is_cart() ) {
return;
}
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id());
if($values['data']->get_id() == 190 && $values['quantity'] == 1 ){
wc_clear_notices();
echo wc_add_notice( __("Add one more to get 50% off on 2nd product"), 'notice');
}
}
}
Related
using the code found on Internet, works perfectly, but it needs to be updated with extra function.
now: if total sum gets 100+ free gift is added. if user removes some products and total gets lower than 100, free gift still stays there
should be: if user removes products and total gets lower than 100, free gift is removed
function aapc_add_product_to_cart() {
global $woocommerce;
$cart_total = 100;
if ( $woocommerce->cart->total >= $cart_total ) {
if ( ! is_admin() ) {
$free_product_id = 6663; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $free_product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $free_product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $free_product_id );
}
}
}
}
add_action( 'template_redirect', 'aapc_add_product_to_cart' );
this works
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users (and avoiding the hook repetition)
if ( ! is_user_logged_in() && did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$threshold_amount = 99.9; // The threshold amount for cart total
$free_product_id = 6663; // ID of the free product
$cart_items_total = 0; // Initializing
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// Check if the free product is in cart
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key;
}
// Get cart subtotal incl. tax from items (with discounts if any)
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// If Cart total is up to the defined amount and if the free products is not in cart, we add it.
if ( $cart_items_total >= $threshold_amount && ! isset($free_item_key) ) {
$cart->add_to_cart( $free_product_id );
}
// If cart total is below the defined amount and free product is in cart, we remove it.
elseif ( $cart_items_total remove_cart_item( $free_item_key );
}
}
I want to give customers with orders above $50 a free gift. Not if a specific product is in the cart (there are some examples here on stackoverflow and below).
After some research I found the following code to add a free product if another specific product is added to the cart.
add_action( 'template_redirect', 'bbloomer_add_gift_if_id_in_cart' );
function bbloomer_add_gift_if_id_in_cart() {
if ( is_admin() ) return;
if ( WC()->cart->is_empty() ) return;
$product_bought_id = 32;
$product_gifted_id = 57;
// see if product id in cart
$product_bought_cart_id = WC()->cart->generate_cart_id( $product_bought_id );
$product_bought_in_cart = WC()->cart->find_product_in_cart( $product_bought_cart_id );
// see if gift id in cart
$product_gifted_cart_id = WC()->cart->generate_cart_id( $product_gifted_id );
$product_gifted_in_cart = WC()->cart->find_product_in_cart( $product_gifted_cart_id );
// if not in cart remove gift, else add gift
if ( ! $product_bought_in_cart ) {
if ( $product_gifted_in_cart ) WC()->cart->remove_cart_item( $product_gifted_in_cart );
} else {
if ( ! $product_gifted_in_cart ) WC()->cart->add_to_cart( $product_gifted_id );
}
}
Found here: https://www.businessbloomer.com/woocommerce-buy-1-product-add-free-product-cart-programmatically/
I also tried this code but it doesn't update if the cart changes:
function aapc_add_product_to_cart() {
global $woocommerce;
$cart_total = 50;
if ( $woocommerce->cart->total >= $cart_total ) {
if ( ! is_admin() ) {
$free_product_id = 12989; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $free_product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $free_product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $free_product_id );
}
}
}
}
add_action( 'template_redirect', 'aapc_add_product_to_cart' );
Is there any way to change that code to work with any product and limit only to the cart total?
Updated
With the following, a free gifted product will be added to cart if subtotal is up to a specific amount:
// Add free gifted product for specific cart subtotal
add_action( 'woocommerce_before_calculate_totals', 'check_free_gifted_product' );
function check_free_gifted_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Settings
$free_product_id = 37;
$targeted_subtotal = 50;
$cart_subtotal = 0; // Initializing
// Loop through cart items (first loop)
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// When free product is is cart
if ( $free_product_id == $cart_item['product_id'] ) {
$free_key = $cart_item_key;
$free_qty = $cart_item['quantity'];
$cart_item['data']->set_price(0); // Optionally set the price to zero
} else {
$cart_subtotal += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// If subtotal match and free product is not already in cart, add it
if ( ! isset($free_key) && $cart_subtotal >= $targeted_subtotal ) {
$cart->add_to_cart( $free_product_id );
}
// If subtotal doesn't match and free product is already in cart, remove it
elseif ( isset($free_key) && $cart_subtotal < $targeted_subtotal ) {
$cart->remove_cart_item( $free_key );
}
// Keep free product quantity to 1.
elseif ( isset($free_qty) && $free_qty > 1 ) {
$cart->set_quantity( $free_key, 1 );
}
}
// Display free gifted product price to zero on minicart
add_filter( 'woocommerce_cart_item_price', 'change_minicart_free_gifted_item_price', 10, 3 );
function change_minicart_free_gifted_item_price( $price_html, $cart_item, $cart_item_key ) {
$free_product_id = 27;
if( $cart_item['product_id'] == $free_product_id ) {
return wc_price( 0 );
}
return $price_html;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
On cart page (the free gifted product is "Beanie"):
On mini cart:
I am using WooCommerce discount: buy one get one 50% off with a notice answer code, if customer purchases a specific product, customer get 50% discount off on the 2nd item.
Now If the targeted product id is a variable product with for example 3 variations "A", "B" and "C", how can I exclude for example the variation "A" from discount calculation? Where should put that condition?
The following will handle variation exclusion from the original answer code:
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// YOUR SETTINGS:
$variable_product_id = 40; // <== HERE your targeted variable product ID
$excl_variations_ids = array( 41, 42); // <== HERE your variations to be excluded
// Initializing variables
$discount = $qty_notice = 0;
$items_prices = array();
// Loop through cart items
foreach ( $cart->get_cart() as $key => $cart_item ) {
if( $variable_product_id == $cart_item['product_id'] && in_array( $cart_item['variation_id'], $excl_variations_ids ) ) {
$quantity = (int) $cart_item['quantity'];
$qty_notice += $quantity;
for( $i = 0; $i < $quantity; $i++ ) {
$items_prices[] = floatval( $cart_item['data']->get_price());
}
}
}
$count_items = count($items_prices); // Count items
rsort($items_prices); // Sorting prices descending order
if( $count_items > 1 ) {
foreach( $items_prices as $key => $price ) {
if( $key % 2 == 1 )
$discount -= number_format( $price / 2, 2 );
}
}
// Applying the discount
if( $discount != 0 ){
$cart->add_fee('Buy one get one 50% off' ,$discount ); // true
// Displaying a custom notice (optional)
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( __("You get 50% of discount on the 2nd item"), 'notice');
}
}
// Display a custom notice on cart page when quantity is equal to 1.
elseif( $qty_notice == 1 ){
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( __( "Add one more to get 50% off on 2nd item" ), 'notice');
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I am trying to add a free product to the cart if the order total is above $199.99
I have achieved this and it is working. The issue is that I need to remove the product if the user then deletes an item from the cart and goes below $199.99 again (to prevent gaming the system).
What I have seems to be working. The problem is that it seems I need to click 2 links before the REMOVE FROM CART action seems to be working (or refresh the page).
What is causing this? Can the remove action be accomplished with AJAX by any chance?
// -------------------------------------------
// ADD PRODUCT IF ORDER MINIMUM ABOVE 200
/*
* Automatically adding the product to the cart when cart total amount reach to $199.99.
*/
function aapc_add_product_to_cart() {
global $woocommerce;
$cart_total = 199.99;
if ( $woocommerce->cart->total >= $cart_total ) {
if ( is_user_logged_in() ) {
$free_product_id = 339; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $free_product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $free_product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $free_product_id );
}
}
}
if ( $woocommerce->cart->total <= $cart_total && $found ) {
WC()->cart->remove_cart_item( $free_product_id );
}
}
add_action( 'template_redirect', 'aapc_add_product_to_cart' );
add_action( 'template_redirect', 'remove_product_from_cart_programmatically' );
function remove_product_from_cart_programmatically() {
if ( is_admin() ) return;
$product_id = 339; // product id
$cart_total = 199.99;
$in_cart = false;
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( $cart_item['product_id'] === $product_id ) {
$in_cart = true;
$key = $cart_item_key;
break;
}
}
if( WC()->cart->total < $cart_total ) {
if ( $in_cart ) WC()->cart->remove_cart_item( $key );
}
}
You should not use template_redirect hook to add or remove a free product based on a cart total threshold amount… Also your code is a bit outdated with some mistakes.
Instead use woocommerce_before_calculate_totals hook that is Ajax enabled, this way:
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users (and avoiding the hook repetition)
if ( ! is_user_logged_in() && did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$threshold_amount = 200; // The threshold amount for cart total
$free_product_id = 339; // ID of the free product
$cart_items_total = 0; // Initializing
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// Check if the free product is in cart
if ( $cart_item['data']->get_id() == $free_product_id ) {
$free_item_key = $cart_item_key;
}
// Get cart subtotal incl. tax from items (with discounts if any)
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// If Cart total is up to the defined amount and if the free products is not in cart, we add it.
if ( $cart_items_total >= $threshold_amount && ! isset($free_item_key) ) {
$cart->add_to_cart( $free_product_id );
}
// If cart total is below the defined amount and free product is in cart, we remove it.
elseif ( $cart_items_total < $threshold_amount && isset($free_item_key) ) {
$cart->remove_cart_item( $free_item_key );
}
}
Code goes on functions.php file of your active child theme (or active theme). Tested and works.
Related: Other similar answer threads
I am looking for the right hook in WooCommerce because I need to add a promotional product to the cart when a certain cart amount of is reached, such as 100 conventional units.
I have also used the hook 'init' but I do not think it's right.
Here is my code:
function add_free_product_to_cart(){
global $woocommerce;
$product_id = 2006;
$found = false;
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 )
{
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values )
{
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
if(!$found)
{
$maximum = 100;
$current = WC()->cart->subtotal;
if($current > $maximum){
$woocommerce->cart->add_to_cart( $product_id );
}
}
}
}
add_action( 'woocommerce_add_to_cart', 'add_free_product_to_cart' );
which hook I should use for that purpose?
Or could you give me a related link to to some similar problem?
Thanks
As you are targeting a certain cart amount to add a promotional product in the cart, you could use woocommerce_before_calculate_totals hook to achieve this with a custom built function.
You have also to remove that promo item if customer update the cart (which is embed in that custom function too).
Here is the code:
add_action( 'woocommerce_before_calculate_totals', 'adding_promotional_product', 10, 1 );
function adding_promotional_product( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$promo_id = 99; // <=== <=== <=== Set HERE the ID of your promotional product
$targeted_cart_subtotal = 100; // <=== Set HERE the target cart subtotal
$has_promo = false;
$subtotal = 0;
if ( ! $cart->is_empty() ){
// Iterating through each item in cart
foreach ($cart->get_cart() as $item_key => $cart_item ){
$product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $cart_item['data']->id : $cart_item['data']->get_id();
// If Promo product is in cart
if( $product_id == $promo_id ) {
$has_promo = true;
$promo_key= $item_key;
} else {
// Adding subtotal item to global subtotal
$subtotal += $cart_item['line_subtotal'];
}
}
// If Promo product is NOT in cart and target subtotal reached, we add it.
if( ! $has_promo && $subtotal >= $targeted_cart_subtotal ) {
$cart->add_to_cart( $promo_id );
// echo 'add';
// If Promo product is in cart and target subtotal is not reached, we remove it.
} elseif( $has_promo && $subtotal < $targeted_cart_subtotal ) {
$cart->remove_cart_item( $promo_key );
}
}
}
This code goes on function.php file of your active child theme (or theme) or in any plugin file.
This code its tested and works.
Related thread: WooCommerce - Auto add or auto remove a freebie product from cart
Code updated on (2018-10-01)