AgentReadyAI visibility appCaffeine & CommerceShopify agency
Caffeine and Commerce
Caffeine and Commerce
By Dylan HuntJune 9th, 2021shopifyscriptsguides

Free Shopify Scripts for Shopify Plus Stores

Shopify Scripts is being retired on June 30, 2026.

The Ruby Scripts and Script Editor used in this tutorial stop running after that date. The replacement is Shopify Functions (also called checkout functions), which is faster, available beyond Shopify Plus, and built for the new checkout. If you run Scripts today, plan your migration now.

Free Shopify Scripts for Shopify Plus Stores

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

Make your store agent-ready

Get found and recommended by AI shopping assistants.

AgentReady adds Schema.org structured data, an llms.txt directory, and an AI-readability audit to your Shopify store, so ChatGPT, Perplexity, and Google can understand and recommend your products. Free for stores under 500 products.

Comments

Every comment here comes from a verified email. Write yours, confirm from your inbox, and it's live.

Loading comments…

Leave a comment

ShareXLinkedInFacebook

Written by Dylan Hunt, Founder, Caffeine and Commerce. We build Shopify stores that rank and that AI agents can read. Have a project? Get in touch.