Script for Tiered Discount with Code

Solved
Rastaclat
Tourist
4 0 1

Hey!

Our store is trying to implement a tiered discount based on spend and found the below script which executes fairly well for us.  The problem that we're running into is that it allows a user to enter in a discount code at checkout that stacks upon the existing discount.  I'm wondering if anyone has an example script where a single discount code is required in order to execute the below.  The other alternative would be for us to disable entering in a coupon code altogether when we run a promo like this, however we would prefer to track this + allow users from other channels (e.g. ambassadors) to be able to use codes that have a higher % off:

TyTyTy for any help / tips here! 

 

# ================================ Customizable Settings ================================
# ================================================================
# Tiered Discounts by Spend Threshold
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
#
#   - 'threshold' is the spend amount needed to qualify
#   - 'discount_type' is the type of discount to provide. Can be
#     either:
#       - ':percent'
#       - ':dollar'
#   - 'discount_amount' is the percentage/dollar discount to
#     apply (per item)
#   - 'discount_message' is the message to show when a discount
#     is applied
# ================================================================
SPENDING_THRESHOLDS = [
  {
    threshold: 30,
    discount_type: :percent,
    discount_amount: 10,
    discount_message: 'Spend $30 and get 10% off!',
  },
  {
    threshold: 50,
    discount_type: :percent,
    discount_amount: 15,
    discount_message: 'Spend $50 and get 15% off!',
  },
  {
    threshold: 100,
    discount_type: :percent,
    discount_amount: 20,
    discount_message: 'Spend $100 and get 20% off!',
  },
]

# ================================ Script Code (do not edit) ================================
# ================================================================
# DiscountApplicator
#
# Applies the entered discount to the supplied line item.
# ================================================================
class DiscountApplicator
  def initialize(discount_type, discount_amount, discount_message)
    @discount_type = discount_type
    @discount_message = discount_message

    @discount_amount = if discount_type == :percent
      1 - (discount_amount * 0.01)
    else
      Money.new(cents: 100) * discount_amount
    end
  end

  def apply(line_item)
    new_line_price = if @discount_type == :percent
      line_item.line_price * @discount_amount
    else
      [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max
    end

    line_item.change_line_price(new_line_price, message: @discount_message)
  end
end

# ================================================================
# TieredDiscountBySpendCampaign
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
# ================================================================
class TieredDiscountBySpendCampaign
  def initialize(tiers)
    @tiers = tiers.sort_by { |tier| tier[:threshold] }.reverse
  end

  def run(cart)
    applicable_tier = @tiers.find { |tier| cart.subtotal_price >= (Money.new(cents: 100) * tier[:threshold]) }
    return if applicable_tier.nil?

    discount_applicator = DiscountApplicator.new(
      applicable_tier[:discount_type],
      applicable_tier[:discount_amount],
      applicable_tier[:discount_message]
    )

    cart.line_items.each do |line_item|
      next if line_item.variant.product.gift_card?
      discount_applicator.apply(line_item)
    end
  end
end

CAMPAIGNS = [
  TieredDiscountBySpendCampaign.new(SPENDING_THRESHOLDS),
]

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

Output.cart = Input.cart
Accepted Solution (1)

Accepted Solutions
playwright-matt
Shopify Partner
72 18 27

This is an accepted solution.

Hi Sam,

Those codes are for 0% off. The script takes care of the actual discounting. So you just need one code per tiered pricing scheme.

And for extra clarification, this script supports two different codes (currently STANDARD_CODE and AMBASSADOR_CODE). You can change those codes to match the ones you create in the Shopify Admin > Discounts area. Here is a screen shots of my discount codes:

original_codes.png

 

However, if I wanted to change the codes, I would edit this area of the code I supplied you.

DISCOUNT_CODES = {
  'STANDARD_CODE' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

 

Instead I might use a new code for the standard discount called "TIERED_SPECIAL". If so, my code would look like this:

DISCOUNT_CODES = {
  'TIERED_SPECIAL' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

And then I would need to add a new 0% off discount code to match:

new_code.png

In any case, the discount code is only used to activate the portion of the script that creates the actual tiered discounts. 

Hopefully that works for you. If so, feel free to mark this as the accepted solution.

Thanks!
Matthew

Playwright | Create Shopify Scripts without writing code | https://playwrightapp.com
- Was my reply helpful? Please Like and Accept Solution.

View solution in original post

Replies 8 (8)
playwright-matt
Shopify Partner
72 18 27

Hi @Rastaclat

I created an app that lets you create scripts like this without having to write code . It has a "tiered discount" feature, so I borrowed some ideas from that.

Here is an updated script that should allow you to create two different discount codes and point them to different discount tiers. 

 

# ================================ Customizable Settings ================================
# ================================================================
# Tiered Discounts by Spend Threshold
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
#
#   - 'threshold' is the spend amount needed to qualify
#   - 'discount_type' is the type of discount to provide. Can be
#     either:
#       - ':percent'
#       - ':dollar'
#   - 'discount_amount' is the percentage/dollar discount to
#     apply (per item)
#   - 'discount_message' is the message to show when a discount
#     is applied
# ================================================================
SPENDING_THRESHOLDS_STANDARD = [
  {
    threshold: 30,
    discount_type: :percent,
    discount_amount: 10,
    discount_message: 'Spend $30 and get 10% off!',
  },
  {
    threshold: 50,
    discount_type: :percent,
    discount_amount: 15,
    discount_message: 'Spend $50 and get 15% off!',
  },
  {
    threshold: 100,
    discount_type: :percent,
    discount_amount: 20,
    discount_message: 'Spend $100 and get 20% off!',
  },
]

SPENDING_THRESHOLDS_AMBASSADOR = [
  {
    threshold: 30,
    discount_type: :percent,
    discount_amount: 12.5,
    discount_message: 'Spend $30 and get 12.5% off!',
  },
  {
    threshold: 50,
    discount_type: :percent,
    discount_amount: 17.5,
    discount_message: 'Spend $50 and get 17.5% off!',
  },
  {
    threshold: 100,
    discount_type: :percent,
    discount_amount: 22.5,
    discount_message: 'Spend $100 and get 22.5% off!',
  },
]

DISCOUNT_CODES = {
  'STANDARD_CODE' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

# ================================ Script Code (do not edit) ================================
# ================================================================
# DiscountApplicator
#
# Applies the entered discount to the supplied line item.
# ================================================================
class DiscountApplicator
  def initialize(discount_type, discount_amount, discount_message)
    @discount_type = discount_type
    @discount_message = discount_message

    @discount_amount = if discount_type == :percent
      1 - (discount_amount * 0.01)
    else
      Money.new(cents: 100) * discount_amount
    end
  end

  def apply(line_item)
    new_line_price = if @discount_type == :percent
      line_item.line_price * @discount_amount
    else
      [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max
    end

    line_item.change_line_price(new_line_price, message: @discount_message)
  end
end

# ================================================================
# TieredDiscountBySpendCampaign
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
# ================================================================
class TieredDiscountBySpendCampaign
  def initialize(tiers)
    @tiers = tiers.sort_by { |tier| tier[:threshold] }.reverse
  end

  def run(cart)
    applicable_tier = @tiers.find { |tier| cart.subtotal_price >= (Money.new(cents: 100) * tier[:threshold]) }
    return if applicable_tier.nil?

    discount_applicator = DiscountApplicator.new(
      applicable_tier[:discount_type],
      applicable_tier[:discount_amount],
      applicable_tier[:discount_message]
    )

    cart.line_items.each do |line_item|
      next if line_item.variant.product.gift_card?
      discount_applicator.apply(line_item)
    end
  end
end

def discount_code_present(cart, code)
  !cart.discount_code.nil? and (cart.discount_code.code.upcase == code.upcase)
end

CAMPAIGNS = []

DISCOUNT_CODES.each do |discount_code|
  if discount_code_present(Input.cart, discount_code[0])
    CAMPAIGNS = [
      TieredDiscountBySpendCampaign.new(discount_code[1]),
    ]
  end
end

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

Output.cart = Input.cart

 

 

Here is a screen shot of it working for me:

tiered-discounts.png

Don't forget to create the actual discount codes in the Shopify Admin > Discounts screen.

 

Hope that helps!

Matthew 

Playwright | Create Shopify Scripts without writing code | https://playwrightapp.com
- Was my reply helpful? Please Like and Accept Solution.

Rastaclat
Tourist
4 0 1

Hey Matthew,

Thank you for your help here!  The below script worked amazing as far as requiring a discount code to be entered vs. automatically applying.  I just have a question about having the code apply the correct % off depending on the $ threshold.  If I create this coupon in the backend, I'm only able to assign one % off, as Shopify doesn't allow me to create multiple codes with the same discount code name for each % off.  Do you have a workaround for this?

Thanks again!

Sam

playwright-matt
Shopify Partner
72 18 27

This is an accepted solution.

Hi Sam,

Those codes are for 0% off. The script takes care of the actual discounting. So you just need one code per tiered pricing scheme.

And for extra clarification, this script supports two different codes (currently STANDARD_CODE and AMBASSADOR_CODE). You can change those codes to match the ones you create in the Shopify Admin > Discounts area. Here is a screen shots of my discount codes:

original_codes.png

 

However, if I wanted to change the codes, I would edit this area of the code I supplied you.

DISCOUNT_CODES = {
  'STANDARD_CODE' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

 

Instead I might use a new code for the standard discount called "TIERED_SPECIAL". If so, my code would look like this:

DISCOUNT_CODES = {
  'TIERED_SPECIAL' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

And then I would need to add a new 0% off discount code to match:

new_code.png

In any case, the discount code is only used to activate the portion of the script that creates the actual tiered discounts. 

Hopefully that works for you. If so, feel free to mark this as the accepted solution.

Thanks!
Matthew

Playwright | Create Shopify Scripts without writing code | https://playwrightapp.com
- Was my reply helpful? Please Like and Accept Solution.

jschmaing
New Member
1 0 0

Hey Matt,

Can you point me in the right direction on where to paste this script. I have tried the theme.liquid and the cart.liquid but no luck.

 

Thank you,

Jerry

Chris_Turner
New Member
2 0 0

Im not sure why this is happening? Did I miss something?

 Screen Shot 2021-11-08 at 1.00.44 PM.png

# ================================ Customizable Settings ================================
# ================================================================
# Tiered Discounts by Spend Threshold
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
#
#   - 'threshold' is the spend amount needed to qualify
#   - 'discount_type' is the type of discount to provide. Can be
#     either:
#       - ':percent'
#       - ':dollar'
#   - 'discount_amount' is the percentage/dollar discount to
#     apply (per item)
#   - 'discount_message' is the message to show when a discount
#     is applied
# ================================================================
SPENDING_THRESHOLDS_STANDARD = [
  {
    threshold: 100,
    discount_type: :dollar,
    discount_amount: 15,
    discount_message: 'Spend $100 and get $15 off!',
  },
  {
    threshold: 200,
    discount_type: :dollar,
    discount_amount: 40,
    discount_message: 'Spend $200 and get $40 off!',
  },
  {
    threshold: 400,
    discount_type: :dollar,
    discount_amount: 100,
    discount_message: 'Spend $400 and get $100 off!',
  },
]

SPENDING_THRESHOLDS_AMBASSADOR = [
  {
    threshold: 30,
    discount_type: :percent,
    discount_amount: 12.5,
    discount_message: 'Spend $30 and get 12.5% off!',
  },
  {
    threshold: 50,
    discount_type: :percent,
    discount_amount: 17.5,
    discount_message: 'Spend $50 and get 17.5% off!',
  },
  {
    threshold: 100,
    discount_type: :percent,
    discount_amount: 22.5,
    discount_message: 'Spend $100 and get 22.5% off!',
  },
]

DISCOUNT_CODES = {
  'CYBER' => SPENDING_THRESHOLDS_STANDARD,
  'AMBASSADOR_CODE' => SPENDING_THRESHOLDS_AMBASSADOR
}

# ================================ Script Code (do not edit) ================================
# ================================================================
# DiscountApplicator
#
# Applies the entered discount to the supplied line item.
# ================================================================
class DiscountApplicator
  def initialize(discount_type, discount_amount, discount_message)
    @discount_type = discount_type
    @discount_message = discount_message

    @discount_amount = if discount_type == :percent
      1 - (discount_amount * 0.01)
    else
      Money.new(cents: 100) * discount_amount
    end
  end

  def apply(line_item)
    new_line_price = if @discount_type == :percent
      line_item.line_price * @discount_amount
    else
      [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max
    end

    line_item.change_line_price(new_line_price, message: @discount_message)
  end
end

# ================================================================
# TieredDiscountBySpendCampaign
#
# If the cart total is greater than (or equal to) an entered
# threshold, the associated discount is applied to each item.
# ================================================================
class TieredDiscountBySpendCampaign
  def initialize(tiers)
    @tiers = tiers.sort_by { |tier| tier[:threshold] }.reverse
  end

  def run(cart)
    applicable_tier = @tiers.find { |tier| cart.subtotal_price >= (Money.new(cents: 100) * tier[:threshold]) }
    return if applicable_tier.nil?

    discount_applicator = DiscountApplicator.new(
      applicable_tier[:discount_type],
      applicable_tier[:discount_amount],
      applicable_tier[:discount_message]
    )

    cart.line_items.each do |line_item|
      next if line_item.variant.product.gift_card?
      discount_applicator.apply(line_item)
    end
  end
end

def discount_code_present(cart, code)
  !cart.discount_code.nil? and (cart.discount_code.code.upcase == code.upcase)
end

CAMPAIGNS = []

DISCOUNT_CODES.each do |discount_code|
  if discount_code_present(Input.cart, discount_code[0])
    CAMPAIGNS = [
      TieredDiscountBySpendCampaign.new(discount_code[1]),
    ]
  end
end

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

Output.cart = Input.cart

 

japple
New Member
2 0 1

I am looking for a code that works on the cart subtotal not line item price.

For example I used the code provided but if the cart reaches $75 it is giving $10 off each item in the cart instead of just $10 off the order

CRMW
Shopify Partner
9 0 4

We also have the same question – Is there a way to discount the cart subtotal, rather than each individual line item if the cart threshold is met? Specifically, this script doesn't work if we wanted to take $10 off $100, as it would discount $10 for each line item. Thank you!

Derek_Morin
Shopify Expert
212 0 32

@CRMW @japple I know it's not a PLUS script, but our app can apply tiered discounts on the subtotal, rather than on each line_item. Example here
The app works alongside scripts that use discount codes, which means you can stack a tiered discount applied with our app with a discount applied via Script.