Looking for true BOGOF script for many items in cart.

Solved
CrossoverBart
Tourist
6 1 0

I have found many BOGO scripts that will recognize when a customer has 2 or more items in their cart and make the lowest priced item in the cart free. 

But I would like a BOGOF script that will make free multiple items if you have more items in your cart.  So based on the cart items quantity, you get a certain number of items free:

When 2 or 3 items in cart: lowest priced item is free. 

4 or 5 items in cart: 2 lowest priced items are free

6 or 7 items in cart: 3 lowest priced items are free

etc.

This is a true BOGOF and creates some complexity with the script because the you may have to apply the discount across multiple items depending on the breakdown of lowest priced items in the cart.

Does anyone know of a script that can do this?  Thanks for the help in advance.

0 Likes
CrossoverBart
Tourist
6 1 0

So I tried to modify my origina BOGO script with IF statements for scenarios with 4 or more items in the cart, but it doesn't work.  When I test with 4 or more items in the cart nothing happens or only one item is bogo'd - depending on whats in cart. Please help.

DISCOUNT_PERCENT=100
CART_DISCOUNT_MESSAGE="BOGO For every 2 items, get the least expensive item free"


eligible_items = Input.cart.line_items.select do |line_item|
  product = line_item.variant.product
  !product.gift_card?
end

# Sort eligible items by price, least exensive first
eligible_items = eligible_items.sort_by{|line_item| line_item.variant.price}

total_items = 0
eligible_items.each do |line_item|
  total_items += line_item.quantity
end

if(total_items >= 2 and total_items < 4 )
  # pull the least exensive item
  line_item = eligible_items.first
  # calculate the discount to be applied
  percent = Decimal.new(DISCOUNT_PERCENT) / 100.0
  
  
  # make sure we don't discount multiple items hiding in a single line item
  if line_item.quantity == 1
    line_discount = line_item.line_price * percent
    puts "line_discount = #{line_discount}"
    # Just discount the item directly
    line_item.change_line_price(line_item.line_price - line_discount, message: CART_DISCOUNT_MESSAGE)
  else
    # If only part of the item must be discounted, split the item
    discounted_item = line_item.split(take: 1)
    # Insert the newly-created item in the cart, right after the original item
    position = Input.cart.line_items.find_index(line_item)
    line_discount = discounted_item.line_price * percent
    puts "line_discount = #{line_discount}"
    Input.cart.line_items.insert(position + 1, discounted_item)
    # Discount the new item
    discounted_item.change_line_price(discounted_item.line_price - line_discount, message: CART_DISCOUNT_MESSAGE)
  end
end

if(total_items >= 4 and total_items < 6 )
  # pull the least exensive item
  line_item = eligible_items.first
  # calculate the discount to be applied
  percent = Decimal.new(2 * DISCOUNT_PERCENT) / 100.0
  
  
  # make sure we don't discount multiple items hiding in a single line item
  if line_item.quantity <= 2
    line_discount = line_item.line_price * percent
    puts "line_discount = #{line_discount}"
    # Just discount the item directly
    line_item.change_line_price(line_item.line_price - line_discount, message: CART_DISCOUNT_MESSAGE)
  else
    # If only part of the item must be discounted, split the item
    discounted_item = line_item.split(take: 2)
    # Insert the newly-created item in the cart, right after the original item
    position = Input.cart.line_items.find_index(line_item)
    line_discount = discounted_item.line_price * percent
    puts "line_discount = #{line_discount}"
    Input.cart.line_items.insert(position + 1, discounted_item)
    # Discount the new item
    discounted_item.change_line_price(discounted_item.line_price - line_discount, message: CART_DISCOUNT_MESSAGE)
  end
end  


Output.cart = Input.cart

 

0 Likes
CrossoverBart
Tourist
6 1 0

I'm racking my brain for another way to do this.  It is not uncommon for us to have customers who buy 4-10 items at a time - especially with a BOGO sale, so I need to get this solved.

While not a perfect solution, I would be fine with discounting the cart by the cost of the least expensive item - and multiplying that discount by 2 if there are 4 or 5 items in cart, or by 3 if there are 6 or 7 items, etc.

That would create the correct discount for probably 90% of shopping carts because many of the items we sell are the same price.  90% correct, is something I would settle for at this point.  

But I am not sure how to do this.  How do I create a discount based on the least expensive item price and then apply it multiple times?  I could organize the items by least expensive to get the discount value in $, and then apply the $ discount in reverse order to the higher priced items first.  

Does anyone see a problem with this?

0 Likes
CrossoverBart
Tourist
6 1 0

I could not get my script to work (my programming skills are not great).   So I went back to scouring the web to find a script that already exists.  I have found the one below which the website says does what I want (except it is a 50% discount instead of free), but I get an error when I install it.   I get the following error at the bottom of the script.

Screen Shot 2021-02-03 at 9.52.37 AM.png

I can't follow the logic of the script.  It is beyond my programming skills.  Can anyone please help me spot the error? Thanks.

def partition (cart, line_items)
  sorted_items = line_items.sort_by{|line_item| line_item.variant.price}.reverse
  discounted_items = []
  
  sorted_items.each do |line_item|
    count = sorted_items.quantity /2
    next if count <= 0
    if count >= line_item.quantity
      # If the full item quantity must be discounted, add it to the items to return
      # and increment the count of discounted items
      discounted_items.push(line_item)
      discounted_items_seen += line_item.quantity
    else
      # If only part of the item must be discounted, split the item
      discounted_item = line_item.split(take: count)
      # Insert the newly-created item in the cart, right after the original item
      position = cart.line_items.find_index(line_item)
      cart.line_items.insert(position + 1, discounted_item)
      # Add it to the list of items to return
      discounted_items.push(discounted_item)
      discounted_items_seen += discounted_item.quantity
    end
    
  end
  discounted_items
end

eligible_items = Input.cart.line_items.select do |line_item|
  product = line_item.variant.product
  !product.gift_card? 
end

discounted_line_items = partition(Input.cart, eligible_items)
discounted_line_items.each do |line_item|
  new_line_price = line_item.line_price * 0.5
  line_item.change_line_price(new_line_price, message: "Buy One, Get One 50% Off")
end


Output.cart = Input.cart

 

0 Likes
CrossoverBart
Tourist
6 1 0

This is an accepted solution.

So I have found a solution that I am putting here in case anyone else new to Shopify runs into the same issue.

I am not sure if this solution works on both Shopify and Plus, but on Plus you do not need to use a script, instead you use Automated Discounts.  

You can accomplish this True BOGO by setting up the Automated Discount as so:

Choose Buy X Get Y discount.

For Customer Buys settings, use:

Minimum Qty of Items = 1

and select every item in your store (via specific products or categories.)

For Customer Gets parameters, use:

Quantity = 1

and select every item in your store (via specific products or categories.)

and set the discounted value to FREE.

 

That is it, you have a BOGO that works for however many items you have in the cart and you don't need a script.

 

0 Likes
amosmos
Shopify Expert
64 1 23

Hi,

 

Please note that automated scripts is limited to only one active discount, plus the customer can't use regular coupon codes when an automatic code is applied.

In addition, the example scripts in Shopify docs does what you need: https://help.shopify.com/en/manual/checkout-settings/script-editor/examples/line-item-scripts#buy-on...

I would say that A) I think there is a bug there in the calculation of the number of the discounted items to apply, and B) it seems to give the discount on the cheapest items in the cart, instead of the cheapest item in each "bundle" of BOGO, which is against the customer.

Hope this helps,

Amos

0 Likes