Tourist
5 1 0

## Buy 3 get 1 free, except for discounted products - script breaks after 4 items have been a...

Hey, so on our website we have a "buy 3 get 1 free" type of deal, and we're about to a clearance page. The items on the clearance page shouldn't count towards our buy 3 get 1 free deal.

The script first checks to see if the item is an item at full price. (8.99 or 9.99). If it is not, then it's a discounted variant (select few variants per product will be discounted to 6.29) and is skipped by the script all together.  If it is a matching full priced item, I check to see if it has a type attribute (we only use this attribute for gifts, so that's why we haven't added a check for the type "gift" directly) then I set the variable for how many gifts are in the cart based on that. If it does not contain the gift type, then I increment the total products, excluding gifts or anything that doesn't have the product tag, to get the allowed gifts value. I then use that value to loop over the cart and apply the discount to any allowed gifts, once the allowed limit as passed then the prices should remain unaffected in case a customer managed to get an unearned gift item in the cart.

So the issue I am having with this script is it doesn't work after the first gift is earned.  Once a customer has 3 full priced items in the cart, the 4th free gift is set to free, but the moment I add 4 full priced items the gift is back at full price. It only works correctly exactly at 3 items, and 1 free gift. When a customer has 4 or 5 full priced items, the gift should remain free, and at 6 full items 2 gifts should be free.

I should also note, this script worked fine before I added the check for the discounted items, but I haven't changed the way the math logic works so I do not understand why it's not working as desired.

``````\$totalCart = 0
\$i = 1
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999)
if product.tags.include? 'product'
if line_item.properties.has_key?("type")
while line_item.quantity > 1
line_item.split(take:1)
end
else
\$totalCart = \$totalCart + line_item.quantity
puts \$totalCart
end
end
end
end
Input.cart.line_items.each do |line_item|
if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999)
if line_item.properties.has_key?("type")
\$i = \$i + 1
puts "got here"
line_item.change_line_price(line_item.line_price * 0.0, message: line_item.properties["type"])
else
line_item.change_line_price(line_item.line_price * 1.0, message: "Free gift conditions not met!")
end
end
end
end
Output.cart = Input.cart``````

I appreciate any help anyone has to give regarding this. Thank you!

P.S. My only experience with ruby is shopify script editor, I am a novice in this language no doubt.

Replies 2 (2)
Tourist
5 1 0

## Re: Buy 3 get 1 free, except for discounted products - script breaks after 4 items have be...

I tried rewriting the script to see if I could fix it, but this script handles the same as the prior script I posted.

I have figured out that the script is messing up once an item has more than 1 qty. For example, if I buy 1 product A, 1 product b, and 1 product c, I'm offered that 4th gift for free.  If I have 6 unique products, at 1 quantity each the script does allow the 2nd gift to be free as well, but it's whenever there's more than 1 quantity on a paid for product that the script messes up.

``````\$totalCart = 0

def isProduct?(line_item)
if  line_item.variant.product.tags.include? 'product'
product = true
else
product = false
end
return product
end

if  line_item.variant.product.tags.include? 'product' and line_item.properties.has_key?("type")
product = true
else
product = false
end
return product
end

def isDiscounted?(line_item)
if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999) || line_item.variant.price == Money.new(cents: 1199) || line_item.variant.price == Money.new(cents: 1299)
return false
else
return true
end
end

Input.cart.line_items.each do |line_item|
if isDiscounted?(line_item)
#do nothing
else
if isProduct?(line_item)
#is a product, and is a gift.
while line_item.quantity > 1
line_item.split(take:1)
end
else
#not a gift, but is a product.
\$totalCart = \$totalCart + line_item.quantity
end
end
end
line_item.change_line_price(line_item.line_price * 0.0, message: line_item.properties["type"])
end
end

Output.cart = Input.cart``````

Again, I appreciate any guidance on this whatsoever. Thanks!

Explorer
59 15 21

## Re: Buy 3 get 1 free, except for discounted products - script breaks after 4 items have be...

Hi @Griffing325,

I tried to look at your script, but realized that this one can get a bit complicated. So instead, I used an app am developing called Playwright. While we don't support this exact feature, I was able to make a few adjustments to support your use case.

You can view the script here: http://kaliara.com/shopify-script.rb (it was too large to paste into this post).

Here is a demo of it working for me. Including the following features:

• lowest priced item is the one discounted
• non-eligible item doesn't count (this one is missing the 'product' tag)
• mine shows real-time cart updates, but this is mostly for checkout

Note: keep in mind that you probably cannot test this in the Script Editor debug tool because of the use of line_item.properties)

Let me know if that works for you!

Matthew

Playwright | Create Shopify Scripts without writing code | https://playwrightapp.com