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