Ruby Rules

Within the Nutrition Warehouse's dedicated page for Ruby and Shopify Scripts, you'll find essential code snippets and implementation guides meticulously curated to enhance your e-commerce functionality. These resources empower you to leverage Ruby's powerful scripting capabilities within Shopify, enabling custom discount logic, shipping calculations, and payment processing automation. Explore, implement, and streamline your nutrition-focused store operations with precision and efficiency


Templates

Here is examples and templates to help build out the scripts

Rule Scripts

######################################################
# Spend over 1c on brand X and get product Y for $XXX @ START
# min_spend_qualifier = Money.new(cents: 1) # CHANGE THIS
# fixed_price = Money.new(cents: 100) # CHANGE THIS
# free_prod_sku = "137059" # CHANGE THIS
# free_prod_skus = ["137059"] # CHANGE THIS (these are excluded from the total, so you can't add the 1 of the discounted product and still qualify)
# qualifier_vendor = "Muscletech" # CHANGE THIS
# message = "$1 Pro Clinical" # CHANGE THIS
# cart_total = cart.subtotal_price
# free_prod = cart.line_items.find{ |item| item.variant.skus[0] == free_prod_sku }
# qualifier_vendor_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   vendor = item.variant.product.vendor
#   sku = item.variant.skus[0]
#   if vendor == qualifier_vendor
#     if (free_prod_skus.include? sku) == false && sku != free_prod_sku
#       qualifier_vendor_total += item.line_price
#     end
#   end
# end
# if qualifier_vendor_total >= min_spend_qualifier
#   if free_prod
#     new_line_price = (free_prod.line_price - free_prod.variant.price) + fixed_price 
#     free_prod.change_line_price(new_line_price, message: message)
#   end
# end
# Spend over 1c on brand X and get product Y for $XXX @ END
######################################################


######################################################
# Example - Buy any of X variants and get choice of any 2 Y variants free @ START
# qualifier_skus = ["148597", "147738", "129280", "129348", "129535"]
# qualifiers = cart.line_items.select{ |item| qualifier_skus.include? item.variant.skus[0]  }
# free_prod_skus = ["147752", "147753", "147753", "147755"]
# free_prods = cart.line_items.select{ |item| free_prod_skus.include? item.variant.skus[0]  }
# if qualifiers.length() > 0 && free_prods.length() > 0
#   qty_discounted = 0
#   free_prods.each do |item|
#     if qty_discounted < 3
#       qty_discounted = qty_discounted + item.quantity
#       max_discount = item.variant.price*2
#       new_line_price = item.line_price - max_discount
#       item.change_line_price(new_line_price, message: "Promo")
#     end
#   end
# end
# Example - Buy any of X variants and get choice of any 2 Y variants free @ END
######################################################


######################################################
# Example - Spend "x" on "brand" get "y" and choice of 1 "z" for free @ START
# min_spend_qualifier = Money.new(cents: 10000) # CHANGE THIS
# cart_total = cart.subtotal_price
# free_prod_sku = "130077"
# free_prod = cart.line_items.find{ |item| item.variant.skus[0] == free_prod_sku }
# free_prod_skus = ["135010","135407","135630","143643","143641"]
# free_prod2 = cart.line_items.find{ |item| free_prod_skus.include? item.variant.skus[0] }
# qualifier_vendor = "Genetix Nutrition" # CHANGE THIS
# message = "Example Promo" # CHANGE THIS
# qualifier_vendor_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   vendor = item.variant.product.vendor
#   sku = item.variant.skus[0]
#   if vendor == qualifier_vendor
#     if (free_prod_skus.include? sku) == false && sku != free_prod_sku
#       qualifier_vendor_total += item.line_price
#     end
#   end
# end
# if qualifier_vendor_total >= min_spend_qualifier
#   if free_prod
#     new_line_price = free_prod.line_price - free_prod.variant.price 
#     free_prod.change_line_price(new_line_price, message: "Promo")
#   end
#   if free_prod2
#     new_line_price = free_prod2.line_price - free_prod2.variant.price 
#     free_prod2.change_line_price(new_line_price, message: "Promo")
#   end
# end
# Example - Spend "x" on "brand" get "y" and choice of 1 "z" for free @ END
######################################################


######################################################
# Example - Buy 2 of x & get a choice of 1 y free @ START
# qualifier_skus = ["135004","135406","135629","143642","143640"]
# free_prod_skus = ["135010","135407","135630","143643","143641"]
# qualifiers = cart.line_items.select{ |item| qualifier_skus.include? item.variant.skus[0] }
# free_prod = cart.line_items.find{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifiers
#   qualifier_count = 0
#   qualifiers.each do |item| qualifier_count += item.quantity end
#   if qualifier_count >= 2
#     if free_prod
#       qty = free_prod.quantity
#       price = free_prod.line_price - free_prod.variant.price
#       free_prod.change_line_price(price, message: "Promo bRaw")
#     end
#   end
# end
# Example - Buy 2 of x & get a choice of 1 y free @ END
######################################################

######################################################
# Example - Buy 2 get 1 free @ START
# qualifier_skus = ["130077","146289","124025","124026","127656","130586","124039","129675","124042","124043","124041","124040","130587","124047","131776","130585"]
# qualifiers = cart.line_items.select{ |item| qualifier_skus.include? item.variant.skus[0] }
# qualifier_count = 0 
# qualifiers.each do |item| qualifier_count += item.quantity end
# free_prod_skus = ["130077","146289","124025","124026","127656","130586","124039","129675","124042","124043","124041","124040","130587","124047","131776","130585"]
# if qualifier_count >= 3
#   item = qualifiers.min_by { |item| item.variant.price }
#   new_line_price = item.line_price - item.variant.price
#   item.change_line_price(new_line_price, message: "Promo")
# end
# Example - Buy 2 get 1 free @ END
######################################################


######################################################
# Example Buy X get a choice of Y...n for free @ START
# free_prod_skus = ["145299", "136247"]
# qualifier_skus = ["137602","136803","136802","136806","136805","136807","136804","147248"]
# qualifier = cart.line_items.find{ |item| qualifier_skus.include? item.variant.skus[0] }
# free_prod = cart.line_items.find{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifier
#   if free_prod
#     qualifier_qty = qualifier.quantity
#     max_discount = free_prod.line_price - (free_prod.variant.price * qualifier_qty)
#     free_prod.change_line_price(max_discount, message: "Promo")
#   end
# end
# # Example Buy X get a choice of Y...n for free @ END
#####################################################


########################################
# Example Buy X get Y & Z for free @ START
# free_prod_sku = "136139"
# free_prod_sku2 = "136247"
# qualifier_skus = ["129280","129281","129348","129535","132262","132263","137734","143790","144682","145106","144837","137734","145207","146895","147738","148311"]
# qualifier = cart.line_items.find{ |item| qualifier_skus.include? item.variant.skus[0] }
# free_prod = cart.line_items.find{ |item| item.variant.skus[0] == free_prod_sku }
# free_prod2 = cart.line_items.find{ |item| item.variant.skus[0] == free_prod_sku2 }
# if qualifier
#   if free_prod
#     qualifier_qty = qualifier.quantity
#     max_discount = free_prod.line_price - (free_prod.variant.price * qualifier_qty)
#     free_prod.change_line_price(max_discount, message: "Promo")
#   end
#   if free_prod2
#     qualifier_qty = qualifier.quantity
#     max_discount = free_prod2.line_price - (free_prod2.variant.price * qualifier_qty)
#     free_prod2.change_line_price(max_discount, message: "Promo")
#   end
# end
# Example Buy X get Y & Z for free @ END
######################################


######################################################
# Example - Spend $X on "Brand", get Y...n Free @ START
# free_prod_skus = ["147030", "146936"] # CHANGE THIS
# qualifier_vendor = "ATP Science" # CHANGE THIS
# message = "Example Promo" # CHANGE THIS
# qualifier_min_spend = Money.new(cents: 7000) # CHANGE THIS
# qualifier_vendor_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   vendor = item.variant.product.vendor
#   sku = item.variant.skus[0]
#   if vendor == qualifier_vendor
#     if (free_prod_skus.include? sku) == false
#       qualifier_vendor_total += item.line_price
#     end
#   end
# end
# products_to_discount = cart.line_items.select{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifier_vendor_total >= qualifier_min_spend
#   if products_to_discount
#     products_to_discount.each do |item|
#       max_discount = item.variant.price
#       new_price = item.line_price - max_discount
#       item.change_line_price(new_price, message: message)
#     end
#   end
# end
# Example - Spend $X on "Brand", get Y...n Free @ START
#######################################################

#######################################################
# Example Buy Buy X & Y get Z free @START
# qualifier_skus1 = ["148326","148327","148328","147458","147459","145242","147314","137001","137002","133953","127852","124019","133171","124020","124018"]
# qualifier_skus2 = ["147460", "147461"]
# free_prod_skus = ["145821"]
# qualifier1 = cart.line_items.find{ |item| qualifier_skus1.include? item.variant.skus[0] }
# qualifier2 = cart.line_items.find{ |item| qualifier_skus2.include? item.variant.skus[0] }
# free_prod = cart.line_items.find{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifier1 && qualifier2
#   if free_prod
#     qty = free_prod.quantity
#     price = free_prod.line_price - free_prod.variant.price
#     free_prod.change_line_price(price, message: "Free Bag")
#   end
# end
# Example Buy Buy X & Y get Z free @END
#######################################################

#######################################################
# Example spend $X on "BRAND" and get 1 item free in list @ START
# free_prod_skus = ["145829", "145828"] # only one of these will be free, even if multiple are in cart
# qualifier_vendor = "Muscletech"
# message = "Free MT Grass Fed 100% Whey Protein 1.8lb"
# qualifier_min_spend = Money.new(cents: 5000)
# qualifier_vendor_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   vendor = item.variant.product.vendor
#   sku = item.variant.skus[0]
#   if vendor == qualifier_vendor
#     if (free_prod_skus.include? sku) == false
#       qualifier_vendor_total += item.line_price
#     end
#   end
# end
# products_to_discount = cart.line_items.select{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifier_vendor_total >= qualifier_min_spend
#   if products_to_discount
#     products_to_discount.each_with_index do |item, index|
#       if index == 0 
#         max_discount = item.variant.price
#         new_price = item.line_price - max_discount
#         item.change_line_price(new_price, message: message)
#       end
#     end
#   end
# end
# Example spend $X on "BRAND" and get 1 item free in list @END
#######################################################


#################### Spend over $xxxx and get Y @start ##################################
# min_spend_qualifier = Money.new(cents: 9999) # CHANGE THIS
# free_prod_sku = "149538" # CHANGE THIS
# free_prod = cart.line_items.find{ |item| item.variant.skus[0] == free_prod_sku }
# message = "Promo" # CHANGE THIS
# qualifier_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   sku = item.variant.skus[0]
#   if sku != free_prod_sku
#     qualifier_total += item.line_price
#   end
# end
# if qualifier_total > min_spend_qualifier
#   if free_prod
#     new_line_price = free_prod.line_price - free_prod.variant.price
#     free_prod.change_line_price(new_line_price, message: message)
#   end
# end
########################### Spend over $xxxx and get Y @end ###########################


# Build a better stack @ START
# class BuildBetterStackCampaign
#   #init our in-instance variables
#   def initialize(cart)
#     @free_shakers = ["144196","144198","146803","144197","144195"]
#     @excluded_skus = ["144512","144917","144923","146802","132652","143917","143918","143919","143920","144511","149027","149028","149029","149030","149152","149153","149154","149155","134094","147172","147173","147174","147175","147176","143805","148156","148163","133896","133900","133899","136810","136811","149027","149028","149029","149030","148162","148265","135911","148159","143806","136974","143915","143916","148157","144916","143913","143914","136632","145821","136631","148164","147177","147178","147179","147180","147181","136630","148158","145244","145243","148261","148262","148263","148264","148266","148166","147182","147183","147184","147185","147186","149538"]
#     @included_vendors = ["Anabolix Nutrition", "Genetix Nutrition", "B Raw", "Pharma Labs"]
#     @excluded_skus.concat @free_shakers
#     @stacked_items = cart.line_items.select do |item| 
#       sku = item.variant.skus[0]
#       vendor = item.variant.product.vendor
#       (!@excluded_skus.include? sku) && 
#       (@included_vendors.include? vendor) &&
#       (!item.discounted?)
#     end
#     @free_shaker = cart.line_items.find do |item| 
#       sku = item.variant.skus[0]
#       (@free_shakers.include? sku) && 
#       (!item.discounted?)
#     end
#     @qualifying_items = @stacked_items.inject(0) {|sum, h| sum + h.quantity}
#   end
#   def run(cart)
#     if ( @qualifying_items >= 4 ) 
#       # sort by lowest price variant first
#       sorted_stacked_items = @stacked_items.sort_by { |key, value| key.variant.price }
#       # get the first four items
#       first_four_sorted_stacked_items = sorted_stacked_items.take(4)
#       # iterate through the first 4 and discount each line by 15% of one product
#       discounted_qty_remaining = 4
#       first_four_sorted_stacked_items.each do |item|
#         if discounted_qty_remaining >= item.quantity
#           max_discount = item.quantity * (item.variant.price * 0.15)
#           new_price = item.line_price - max_discount
#           item.change_line_price(new_price, message: "Build a Better Stack $#{max_discount.cents/100} saved!")
#           discounted_qty_remaining = discounted_qty_remaining - item.quantity
#         elsif discounted_qty_remaining > 0
#           puts discounted_qty_remaining
#           new_line = item.split(take: discounted_qty_remaining)
#           max_discount = discounted_qty_remaining * (item.variant.price * 0.15)
#           new_price = new_line.line_price - max_discount
#           new_line.change_line_price(new_price, message: "Build a Better Stack $#{max_discount.cents/100} saved!")
#           cart.line_items << new_line
#           discounted_qty_remaining = 0
#         else
#           #nothing required
#         end
#       end
#       # discount 1 of the shaker by 100%
#       if @free_shaker
#         max_discount = @free_shaker.variant.price * 1
#         new_price = @free_shaker.line_price - max_discount
#         @free_shaker.change_line_price(new_price, message: "Build a Better Stack $#{max_discount.cents/100} saved!")
#       end
#     end
#   end
# end
# Build a better stack @ END


#######################################################
# Example spend over $X on ANYTHING and get 1 item free in list @ START
# free_prod_skus = ["145829", "145828"] # only one of these will be free, even if multiple are in cart
# message = "Free gift!"
# qualifier_min_spend = Money.new(cents: 9900)
# qualifier_total = Money.new(cents: 0)
# cart.line_items.each do |item|
#   sku = item.variant.skus[0]
#   if !free_prod_skus.include? sku
#     qualifier_total += item.line_price
#   end
# end
# products_to_discount = cart.line_items.select{ |item| free_prod_skus.include? item.variant.skus[0] }
# if qualifier_total >= qualifier_min_spend
#   if products_to_discount
#     products_to_discount.each_with_index do |item, index|
#       if index == 0 
#         max_discount = item.variant.price
#         new_price = item.line_price - max_discount
#         item.change_line_price(new_price, message: message)
#       end
#     end
#   end
# end
# Example spend $X on ANYTHING and get 1 item free in list @END
#######################################################

Free Gift OR Free Shipping Over $150

User can select a free gift or free shipping in the slide out cart

Discount Rule Script

free_ship = false
cart_total = Input.cart.subtotal_price.cents
customer = Input.cart.customer

# Subtract discount codes applid to cart
begin
  if Input.cart.discount_code
    discount_code = Input.cart.discount_code
  end
  if discount_code
    if discount_code.amount # Fixed amount discount
      cart_total -= discount_code.amount.cents
    end
  end
rescue
  # Discount subtraction fucked up yo
end

# If the cart total is less than 0, normalise to 0
if cart_total < 0
  cart_total = 0
end

# If there's any free gifts in the cart, assign a variable
free_item = false
Input.cart.line_items.each do |item| 
  if item.properties["_free"]
    free_item = true
    break
  end
end

# If the total is over $150 and no free items are added, they qualify for free shipping
if (cart_total > 14999) && (free_item == false)
  free_ship = true
end

# If the total is over $300, they always qualify shipping
# if (cart_total > 30000)
#   free_ship = true
# end

# Delete rates that aren't applicable
if free_ship
  Input.shipping_rates.delete_if {|rate| rate.code == "Standard Shipping (3-8 days)" }
else
  Input.shipping_rates.delete_if {|rate| rate.code == "Free Standard Shipping" }
end

# Testing for Jordan
if customer && customer.email == "jordan@nutritionwarehouse.com.au"
  Input.shipping_rates.each do |rate|
    discount = rate.price
    rate.apply_discount(discount, { message: "Free shipping for JQ" })
  end
end

# Re order rates
DESIRED_RATE_ORDER = [
  "Standard Shipping (3-8 days)",
  "Express Shipping (1-4 days)",
  "Free Standard Shipping",
  "Click & Collect"
]
class ReorderRatesCampaign
  def initialize(desired_order)
	  @desired_order = desired_order.map { |item| item.downcase.strip }
  end
  def run(cart, shipping_rates)
	  shipping_rates.sort_by! { |rate| @desired_order.index(rate.name.downcase.strip) || Float::INFINITY }
  end
end



HIDE_RATES_FOR_PO_BOX = [
  {
    po_box_triggers: [
      "po box", "post office", "p o box", "p.o.box", "p.o. box", "p.o box", "pobox",
      "post office box", "post box", "p. o. box", "po. box", "postal box",
    ],
    rate_match_type: :exact,
    rate_names: ["Express Shipping (1-4 days)"],
  },
]
# ================================================================
# AddressSelector
# Finds whether the supplied address contains any of the entered
# strings.
# ================================================================
class AddressSelector
  def initialize(triggers)
    @triggers = triggers.map { |trigger| trigger.downcase.strip }
  end
  def match?(address)
    address_fields = [address.address1, address.address2].map do |line|
      line.nil? ? "" : line.downcase
    end
    address_fields = address_fields.join(" ")
    @triggers.any? { |trigger| address_fields.include?(trigger) }
  end
end
# ================================================================
# RateNameSelector
#
# Finds whether the supplied rate name matches any of the entered
# names.
# ================================================================
class RateNameSelector
  def initialize(match_type, rate_names)
    @match_type = match_type
    @comparator = match_type == :exact ? '==' : 'include?'
    @rate_names = rate_names.map { |rate_name| rate_name.downcase.strip }
  end
  def match?(shipping_rate)
    if @match_type == :all
      true
    else
      @rate_names.any? { |name| shipping_rate.name.downcase.send(@comparator, name) }
    end
  end
end
# ================================================================
# HideRatesForPOBoxCampaign
# If the shipping address contains any of the entered "PO Box"
# identifiers, the entered rate(s) are hidden.
# ================================================================
class HideRatesForPOBoxCampaign
  def initialize(campaigns)
    @campaigns = campaigns
  end
  def run(cart, shipping_rates)
    address = cart.shipping_address
    return if address.nil?
    @campaigns.each do |campaign|
      next unless AddressSelector.new(campaign[:po_box_triggers]).match?(address)
      rate_name_selector = RateNameSelector.new(
        campaign[:rate_match_type],
        campaign[:rate_names],
      )
      shipping_rates.delete_if do |shipping_rate|
        rate_name_selector.match?(shipping_rate)
      end
    end
  end
end

CAMPAIGNS = [
  ReorderRatesCampaign.new(DESIRED_RATE_ORDER),
  HideRatesForPOBoxCampaign.new(HIDE_RATES_FOR_PO_BOX),
]

CAMPAIGNS.each do |campaign|
  campaign.run(Input.cart, Input.shipping_rates)
end

Output.shipping_rates = Input.shipping_rates