skip to Main Content

I have created a ‘BOGOF‘ (buy one get one free) coupon, using the normal woocommerce coupon method.

The coupon gives the user 100% percentage discount on 1 other item in the cart.


Coupon settings

General:

  • Discount type: Percentage discount Coupon

  • amount: 100

Usage limits:

  • Limit usage to X items: 1

When used:

  • Coupon applies 100% to a random item in the cart (default behavior, I guess)

Desired:

  • It needs to take 100% off the cheapest item in the cart.

With the following code I try to achieve my goal, unfortunately without the desired result

function filter_woocommerce_coupon_get_discount_amount( $discount, $discounting_amount, $cart_item, $single, $instance ) { 
    $price_array = array();

    foreach( $cart_item as $item ) {
        echo $item->price;
        if($item->price > 0){
            array_push($price_array, $item->price);
        }
    }

    $lowestPrice = min($price_array);

    if( $lowestPrice < $discount ){
        $discount = $lowestPrice; 
    }

    return $discount; 
}    
add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_woocommerce_coupon_get_discount_amount', 10, 5 );

3

Answers


  1. First there is a big mistake in your code as $cart_item variable hook argument is the current cart item but not the cart items array…

    The following will apply a coupon discount of 100% on the cheapest cart item (commented code):

    add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_wc_coupon_get_discount_amount', 10, 5 );
    function filter_wc_coupon_get_discount_amount( $discount_amount, $discounting_amount, $cart_item, $single, $coupon ) { 
        // Define below your existing coupon code
        $coupon_code = 'BOGOF';
    
        // Only for a defined coupon code
        if( strtolower( $coupon_code ) !== $coupon->get_code() ) 
            return $discount_amount;
    
        $items_prices = [];
        $items_count  = 0;
    
        // Loop through cart items
        foreach( WC()->cart->get_cart() as $key => $item ){
            // Get the cart item price (the product price)
            if ( wc_prices_include_tax() ) {
                $price = wc_get_price_including_tax( $item['data'] );
            } else {
                $price = wc_get_price_excluding_tax( $item['data'] );
            }
    
            if ( $price > 0 ){
                $items_prices[$key] = $price;
                $items_count       += $item['quantity'];
            }
        }
    
        // Only when there is more than one item in cart
        if ( $items_count > 1 ) {
            asort($items_prices);  // Sorting prices from lowest to highest
    
            $item_keys = array_keys($items_prices);
            $item_key  = reset($item_keys); // Get current cart item key
    
            // Targeting only the current cart item that has the lowest price
            if ( $cart_item['key'] == $item_key ) {
                return reset($items_prices); // return the lowest item price as a discount
            }
        } else {
            return 0;
        }
    }
    

    Code goes in functions.php file of your active child theme (or active theme). Tested and works.

    Login or Signup to reply.
  2. If you want use your own discount not only 100% replace return reset($items_prices); to the return $discount_amount;

    Login or Signup to reply.
  3. I made a rather small tweak to this – I noticed that if I had lots of items in my cart, it would give a 100% discount to MULTIPLE of the cheapest product. So if a user had, so 10 t-shirts at £10 each, it was giving a £100 discount. I modified this slightly below, which might help someone in the future:

    add_filter('woocommerce_coupon_get_discount_amount', 'tfcc_cheapest_free', 10, 5);
    function tfcc_cheapest_free($discount, $discounting_amount, $cart_item, $single, $coupon) {
        // IF TYPE MATCHES PERFORM CUSTOM CALCULATION
        if ($coupon->type == 'cheapest_free'){
    
          $items_prices = [];
              $items_count  = 0;
    
              // Loop through cart items
              foreach( WC()->cart->get_cart() as $key => $item ){
                  // Get the cart item price (the product price)
                  if ( wc_prices_include_tax() ) {
                      $price = wc_get_price_including_tax( $item['data'] );
                  } else {
                      $price = wc_get_price_excluding_tax( $item['data'] );
                  }
    
                  if ( $price > 0 ){
                      $items_prices[$key] = $price;
                      $items_count       += $item['quantity'];
                  }
              }
    
              // Only when there is more than one item in cart
              if ( $items_count > 1 ) {
                  asort($items_prices);  // Sorting prices from lowest to highest
    
                  $item_keys = array_keys($items_prices);
                  $item_key  = reset($item_keys); // Get current cart item key
    
                  // Targeting only the current cart item that has the lowest price
                  if ( $cart_item['key'] == $item_key ) {
                      return reset($items_prices)/$cart_item['quantity']; // return the lowest item price as a discount
                  }
              } else {
                  return 0;
              }
    
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search