I am trying to automatically trigger a coupon to be applied in the cart specifically for when there are 4 items in the cart.
The coupon is pre-created in the Woocommerce back-end of the site "tasterbox"
I am using an amended version from this answer code:
Add WooCommerce coupon code automatically based on product categories
Here is my code version:
add_action( 'woocommerce_before_calculate_totals', 'wc_auto_add_coupons', 10, 1 );
function wc_auto_add_coupons( $cart_object ) {
// Coupon code
$coupon = 'tasterbox';
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Initialising variables
$is_match = false;
$taster_item_count = 4;
// Iterating through each cart item
foreach ( WC()->cart->get_cart() as $cart_item ) {
// If cart items match 4
if( $cart->cart_contents_count == $taster_item_count ){
$is_match = true; // Set to true
break; // stop the loop
}
}
// If conditions are matched add the coupon discount
if( $is_match && ! $cart_object->has_discount( $coupon )){
// Apply the coupon code
$cart_object->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('TASTER BOX ADDED'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $has_category && $cart_object->has_discount( $coupon )){
// Remove the coupon code
$cart_object->remove_coupon( $coupon );
// Optionally display a message
wc_add_notice( __('SORRY, TASTERBOX NOT VALID'), 'alert');
}
}
However I can not get it to auto apply the coupon when there are 4 items in the cart. It seems like something simple to do, but I'm stuck.
Any help appreciated.
There is some little mistakes and errors in your code. Try the following instead:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_cart_items_count', 25, 1 );
function auto_add_coupon_based_on_cart_items_count( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Setting and initialising variables
$coupon = 'tasterbox'; // <=== Coupon code
$item_count = 4; // <=== <=== Number of items
$matched = false;
if( $cart->cart_contents_count >= $item_count ){
$matched = true; // Set to true
}
// If conditions are matched add coupon is not applied
if( $matched && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('TASTER BOX ADDED'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $matched && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
// Optionally display a message
wc_add_notice( __('SORRY, TASTERBOX NOT VALID'), 'error');
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related
So I can use this snippet from the woocommerce docs and it works to add a free product when a cart total is reached. However, our customers need to be able to remove the product from the cart if they don't want it (repeat customers that don't want the same gift every time). With this snippet, the remove from cart button doesn't work for the free product.
/**
* Add another product depending on the cart total
*/
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 2831; //replace with your product id
$found = false;
$cart_total = 30; //replace with your cart total needed to add above item
if( $woocommerce->cart->total >= $cart_total ) {
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
$woocommerce->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
$woocommerce->cart->add_to_cart( $product_id );
}
}
}
}
``
code above is from here: https://docs.woocommerce.com/document/automatically-add-product-to-cart-on-visit/
Removing the product from the cart will actually work, but the problem is that the code will also automatically re-add the product again.
One way to solve this would be to remember that the product has already been added once, and to not re-add the product if the product would be added another time (after it has been removed from the cart for example).
A simple way to do that would be to save that data inside of the WooCommerce session, using WC()->session. Modified code below:
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 2831; //replace with your product id
$found = false;
$cart_total = 10; //replace with your cart total needed to add above item
if( $woocommerce->cart->total >= $cart_total && ! WC()->session->get( 'free_item_given', false ) ) { // <--- ADDED CHECK FOR free_item_given HERE
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ) {
$woocommerce->cart->add_to_cart( $product_id );
WC()->session->set( 'free_item_given', true ); // <--- REMEMBER free_item_given HERE
}
} else {
// if no products in cart, add it
$woocommerce->cart->add_to_cart( $product_id );
WC()->session->set( 'free_item_given', true ); // <--- REMEMBER free_item_given HERE
}
}
}
}
I hope that it solves your problem!
I need to apply a previously created coupon in woocommerce cart based on total spent in shop by logged in users. Example, If user already spent $300 or more in previous orders, in the next order, automatically apply "xxx" coupon.
based on "Apply automatically a coupon based on specific cart items count in Woocommerce" answer thread, that is what I have so far:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_cart_items_count', 25, 1 );
function auto_add_coupon_based_on_cart_items_count( $user_id, $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Setting and initialising variables
$coupon = 'descuentolealtad'; // <=== Coupon code
$matched = false;
$customer = new WC_Customer( $user_id );
if( $customer->get_total_spent >= 60 ){
$matched = true; // Set to true
}
// If conditions are matched add coupon is not applied
if( $matched && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('Descuento de Lealtad aplicado'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $matched && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
// Optionally display a message
//wc_add_notice( __('Descuento de Lealtad removido'), 'error');
}
}
I'm trying to use the dedicated get_total_spent() function from woocommerce but is giving me a blank screen.
Any help is appreciated.
Edit
That is my working code very different as I am using a negative fee:
add_action('woocommerce_cart_calculate_fees' , 'discount_based_on_customer_orders', 10, 1);
function discount_based_on_customer_orders( $cart_object ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Getting "completed" customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed' // Only orders with status "completed"
) );
// Orders count
$customer_orders_count = count($customer_orders);
// The cart total
$cart_total = WC()->cart->get_total(); // or WC()->cart->get_total_ex_tax()
// First customer order discount
if( empty($customer_orders) || $customer_orders_count == 0 ){
$discount_text = __('Loyalty Discount', 'woocommerce');
$discount = -7;
}
}
Updated - There is many mistakes in your code like:
For this hook there is only one variable argument: $cart… and not $user_id and $cart
Since Woocommerce 3, use the method get_total_spent() and not the property get_total_spent.
You should first check that user is logged in too.
Use the following revisited code instead:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_total_spent', 10, 1 );
function auto_add_coupon_based_on_total_spent( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_user_logged_in() )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Setting and initialising variables
$coupon = 'summer'; // <=== Coupon code
$spent_amount = 60;
$customer = new WC_Customer(get_current_user_id());
// If conditions are matched add coupon is not applied
if( $customer->get_total_spent() >= $spent_amount && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('Descuento de Lealtad aplicado'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif($customer->get_total_spent() < $spent_amount && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
}
}
Code goes in function.php file of your active child theme (or active theme). It should better works.
I wanted to apply a coupon code to cart if cart have minimum 2 items. if not have then the coupon not will apply and show alter message and if have apply then will show a success message here is my code I have tried not working like I want
add_action( 'woocommerce_before_calculate_totals','conditionally_auto_add_coupon', 30, 1 );
function conditionally_auto_add_coupon( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') ) return; // Exit
// HERE set the coupon code (in lowercase)
$coupon_code = 'mycode';
$total_item = 0;
if (WC()->cart->has_discount('mycode')) {
foreach( $cart->get_cart() as $cart_item ){
$total_item++;
}
if($total_item < 2){
$cart->remove_coupon( $coupon_code );
wc_add_notice( __('you have only 1 item in cart'), 'alert');
}
else{
$cart->add_discount( $coupon_code );
wc_add_notice( __('coupon added'), 'notice');
}
}
}
Any help is welcome.
Try the following:
add_action( 'woocommerce_before_calculate_totals', 'auto_apply_coupon_conditionally', 10, 1 );
function auto_apply_coupon_conditionally( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$coupon_code = 'summer'; // HERE set the coupon code (in lowercase)
$applied = in_array( $coupon_code, $cart->get_applied_coupons() ) ? true : false;
$item_count = sizeof( $cart->get_cart() );
$total_item = 0;
// Remove coupon
if ( $item_count < 2 && $applied ) {
$cart->remove_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __('You have only 1 item in cart'), 'error');
}
// Add coupon
elseif ( $item_count >= 2 && ! $applied ) {
$cart->apply_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __('A coupon has been added'), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works
Please use "Smart Coupon For Woocommerce" plugin implementing the auto coupon functionality,
Please refer this code in svn repo.
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');
}
}
}
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)