People are charging a lot to make these, so with the help of OnlyGrowth I worked to make a ton of these that people can copy and paste to use on their stores. This is for Shopify Plus only right now.
1. Getting started with Buy 2 Get 1 Free
PAID_ITEM_COUNT = 2
DISCOUNTED_ITEM_COUNT = 1
# Returns the integer amount of items that must be discounted next
# given the amount of items seen
#
def discounted_items_to_find(total_items_seen, discounted_items_seen)
Integer(total_items_seen / (PAID_ITEM_COUNT + DISCOUNTED_ITEM_COUNT) * DISCOUNTED_ITEM_COUNT) - discounted_items_seen
end
# Partitions the items and returns the items that are to be discounted.
#
# Arguments
# ---------
#
# * cart
# The cart to which split items will be added (typically Input.cart).
#
# * line_items
# The selected items that are applicable for the campaign.
#
def partition(cart, line_items)
# Sort the items by price from high to low
sorted_items = line_items.sort_by{|line_item| line_item.variant.price}.reverse
# Create an array of items to return
discounted_items = []
# Keep counters of items seen and discounted, to avoid having to recalculate on each iteration
total_items_seen = 0
discounted_items_seen = 0
# Loop over all the items and find those to be discounted
sorted_items.each do |line_item|
total_items_seen += line_item.quantity
# After incrementing total_items_seen, see if any items must be discounted
count = discounted_items_to_find(total_items_seen, discounted_items_seen)
# If there are none, skip to the next item
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
# Return the items to be discounted
discounted_items
end
eligible_items = Input.cart.line_items.select do |line_item|
product = line_item.variant.product
!product.gift_card? && product.id == 592406273
end
discounted_line_items = partition(Input.cart, eligible_items)
discounted_line_items.each do |line_item|
line_item.change_line_price(Money.zero, message: "Buy 2 get 1 free")
end
Output.cart = Input.cart
2. Next we move on to Buy 1 Get 1 For $X
PAID_ITEM_COUNT = 1
DISCOUNTED_ITEM_COUNT = 1
# Returns the integer amount of items that must be discounted next
# given the amount of items seen
#
def discounted_items_to_find(total_items_seen, discounted_items_seen)
Integer(total_items_seen / (PAID_ITEM_COUNT + DISCOUNTED_ITEM_COUNT) * DISCOUNTED_ITEM_COUNT) - discounted_items_seen
end
# Partitions the items and returns the items that are to be discounted.
#
# Arguments
# ---------
#
# * cart
# The cart to which split items will be added (typically Input.cart).
#
# * line_items
# The selected items that are applicable for the campaign.
#
def partition(cart, line_items)
# Sort the items by price from high to low
sorted_items = line_items.sort_by{|line_item| line_item.variant.price}.reverse
# Create an array of items to return
discounted_items = []
# Keep counters of items seen and discounted, to avoid having to recalculate on each iteration
total_items_seen = 0
discounted_items_seen = 0
@percent = Decimal.new(50) / 100.0
# Loop over all the items and find those to be discounted
sorted_items.each do |line_item|
total_items_seen += line_item.quantity
# After incrementing total_items_seen, see if any items must be discounted
count = discounted_items_to_find(total_items_seen, discounted_items_seen)
# If there are none, skip to the next item
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
# Return the items to be discounted
discounted_items
end
eligible_items = Input.cart.line_items.select do |line_item|
product = line_item.variant.product
!product.gift_card? && product.id == 415268529
end
discounted_line_items = partition(Input.cart, eligible_items)
discounted_line_items.each do |line_item|
line_discount = line_item.line_price * @percent
line_item.change_line_price(line_item.line_price - line_discount, message: "Buy one, get one 50% off")
end
Output.cart = Input.cart
3. Want to give a % discount instead? Buy 1 Get 1 For X% Off
PAID_ITEM_COUNT = 1
DISCOUNTED_ITEM_COUNT = 1
# Returns the integer amount of items that must be discounted next
# given the amount of items seen
#
def discounted_items_to_find(total_items_seen, discounted_items_seen)
Integer(total_items_seen / (PAID_ITEM_COUNT + DISCOUNTED_ITEM_COUNT) * DISCOUNTED_ITEM_COUNT) - discounted_items_seen
end
# Partitions the items and returns the items that are to be discounted.
#
# Arguments
# ---------
#
# * cart
# The cart to which split items will be added (typically Input.cart).
#
# * line_items
# The selected items that are applicable for the campaign.
#
def partition(cart, line_items)
# Sort the items by price from high to low
sorted_items = line_items.sort_by{|line_item| line_item.variant.price}.reverse
# Create an array of items to return
discounted_items = []
# Keep counters of items seen and discounted, to avoid having to recalculate on each iteration
total_items_seen = 0
discounted_items_seen = 0
@percent = Decimal.new(50) / 100.0
# Loop over all the items and find those to be discounted
sorted_items.each do |line_item|
total_items_seen += line_item.quantity
# After incrementing total_items_seen, see if any items must be discounted
count = discounted_items_to_find(total_items_seen, discounted_items_seen)
# If there are none, skip to the next item
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
# Return the items to be discounted
discounted_items
end
eligible_items = Input.cart.line_items.select do |line_item|
product = line_item.variant.product
!product.gift_card? && product.id == 415268529
end
discounted_line_items = partition(Input.cart, eligible_items)
discounted_line_items.each do |line_item|
line_discount = line_item.line_price * @percent
line_item.change_line_price(line_item.line_price - line_discount, message: "Buy one, get one 50% off")
end
Output.cart = Input.cart
4. Love tiered pricing? Buy X quantity of a product, Get $Y off
DISCOUNTS_BY_QUANTITY = {
10_000 => 20,
1_000 => 15,
100 => 10,
10 => 5,
}
Input.cart.line_items.each do |line_item|
next if line_item.variant.product.gift_card?
quantity, discount = DISCOUNTS_BY_QUANTITY.find do |quantity, _|
line_item.quantity >= quantity
end
next unless discount
message = "$#{discount} off when buying at least #{quantity}."
line_item.change_line_price(
line_item.line_price - (Money.new(cents:100) * discount),
message: message,
)
end
Output.cart = Input.cart
5. More tiered pricing! Buy X quantity of a product, Get Y% off
DISCOUNTS_BY_QUANTITY = {
10_000 => 20,
1_000 => 15,
100 => 10,
10 => 5,
}
Input.cart.line_items.each do |line_item|
next if line_item.variant.product.gift_card?
quantity, discount = DISCOUNTS_BY_QUANTITY.find do |quantity, _|
line_item.quantity >= quantity
end
next unless discount
message = "#{discount}% off when buying at least #{quantity}."
line_item.change_line_price(
line_item.line_price * (Decimal.new(1) - discount.to_d / 100),
message: message,
)
end
Output.cart = Input.cart
6. Offer a discount on a certain product Tag! X% off all products with Y tag
@percent = Decimal.new(25) / 100.0
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
next unless product.tags.include?('myTag')
line_discount = line_item.line_price * @percent
line_item.change_line_price(line_item.line_price - line_discount, message: "25% Off")
end
Output.cart = Input.cart
7. More product tag discounts! $X off all products with Y tag
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
next unless product.tags.include?('MyTag')
line_item.change_line_price(line_item.line_price - Money.new(cents: 500), message: "$5 Off")
end
Output.cart = Input.cart
8. Spend at least $X (value in cart), Get $Y off
min_discount_order_amount = Money.new(cents:100) * 30 #minimum amount needed to have in cart to get discount
total = Input.cart.subtotal_price_was
discount = if total > min_discount_order_amount
500 #discount amount you are offering in cents
else
0
end
message = "Here's $5 off" #discount message shown to customer
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price - Money.new(cents: discount), message: message) unless discount == 0
end
Output.cart = Input.cart
9. Spend at least $X (value in cart), Get Y% off
min_discount_order_amount = Money.new(cents:100) * 30 #number of dollars needed in cart to get the discount
total = Input.cart.subtotal_price_was
discount = if total > min_discount_order_amount
0.2 #discount percentage in decimal form
else
0
end
message = "My message"
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price * (1-discount), message: message) unless discount == 0
end
Output.cart = Input.cart
10. Get $X off on first purchase
customer = Input.cart.customer
discount = 0
message = ""
if customer
if customer.orders_count < 1
discount = 1000 #discount amount in cents
message = "New Customer - $10 off"
end
end
puts discount
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price - Money.new(cents: discount), message: message) unless discount == 0
end
Output.cart = Input.cart
11. Get X% off on first purchase
customer = Input.cart.customer
discount = 0
message = ""
if customer
if customer.orders_count == 0
discount = 0.1 #change the discount given here
message = "Thanks for placing your first order" #change the message shown here
end
puts discount
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price * (1-discount), message: message) unless discount == 0
end
Output.cart = Input.cart
12. Have purchased at least X orders, Get Y% off
customer = Input.cart.customer
discount = 0
message = ""
if customer
if customer.orders_count > 2 #number of orders needed to get discount
discount = 0.2 #percent discount in decimal form
message = "VIP Customer"
end
end
puts discount
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price * (1-discount), message: message) unless discount == 0
end
Output.cart = Input.cart
13. Have purchased at least X orders, Get $Y off
customer = Input.cart.customer
discount = 0
message = ""
if customer
if customer.orders_count > 2 #number of orders placed to get the deal
discount = 1000 #discount amount in cents
message = "VIP Customer - $10 off"
end
end
puts discount
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price - Money.new(cents: discount), message: message) unless discount == 0
end
Output.cart = Input.cart
14. X$ off if customer accepts marketing
customer = Input.cart.customer
discount = 0
message = ""
if customer
if customer.accepts_marketing? #determines if the customer accepts marketing
discount = 1000 #number of Dollars to discount in cents
message = "Accepts Marketing Discount" #message to customer when they get the discount
end
end
puts discount
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next if product.gift_card?
line_item.change_line_price(line_item.line_price - Money.new(cents: discount), message: message) unless discount == 0
end
Output.cart = Input.cart
15. % off on W if X, Y, Z in cart
discounted_product = 1522083265
products_needed = [592406273, 4283854977, 4284984897]
products_seen = []
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
products_seen << product.id if products_needed.include?(product.id)
end
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next unless product.id == discounted_product
line_item.change_line_price(line_item.line_price * 0.90, message: "My Sale") if products_seen.uniq.sort == products_needed.uniq.sort
end
Output.cart = Input.cart
15. $ off on W if X, Y, Z in cart
discount = Money.new(cents: 100) * 5
discounted_product = 1522083265
products_needed = [592406273, 4283854977, 4284984897]
products_seen = []
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
products_seen << product.id if products_needed.include?(product.id)
end
Input.cart.line_items.each do |line_item|
product = line_item.variant.product
next unless product.id == discounted_product
line_item.change_line_price(line_item.line_price - discount, message: "My Sale") if products_seen.uniq.sort == products_needed.uniq.sort
end
Output.cart = Input.cart
