跳转到主要内容
Script 示例

Migrating a BOGO that ran across the whole cart

How most agency-written BOGOs worked: pool every eligible unit, sort it, then peel off the discounted ones. Sort ascending and the cheapest units are free. Sort descending and they are not. The class names differ by one word.

可重建
这个 Script 做了什么

It pooled every eligible unit in the cart, sorted them by price, and discounted a share of them.

商家用 2 种不同写法写过这段逻辑,它们的含义并不相同。每种写法都列在下方,各自配有对应的购物车和数字。

在您自己的店铺里试一试

把它粘贴到 Scripts 救援,看看会重建成什么

  1. 用本页任意 Script 旁边的按钮复制 Ruby 代码。
  2. 在 Shopify 后台打开 Stackable,依次进入工具、Scripts 救援。
  3. 粘贴进去,读一读工具说它会创建什么,再和本页的设置逐项对照。

Scripts 救援属于 Pro 套餐。在您填写旧 Script 的折扣金额、且两个数字精确到最小货币单位完全一致之前,不会发布任何内容。

Bogo cross line interleaved (D17)

可重建

危险配对 D17。这个文件和它的搭档看起来几乎一样,行为却不同,在判断您手上是哪一个之前,请把两份都读一遍。

原始 Ruby

class InterleavedPartitioner
  def initialize(paid_item_count, discounted_item_count)
    @paid_item_count = paid_item_count
    @discounted_item_count = discounted_item_count
  end

  def partition(cart, applicable_line_items)
    sorted_items = applicable_line_items.sort_by { |line_item| line_item.variant.price }.reverse
    discounted_items = []
    paid_items_seen = 0
    discounted_items_seen = 0

    sorted_items.each do |line_item|
      line_item.quantity.times do
        if paid_items_seen < @paid_item_count
          paid_items_seen += 1
        else
          discounted_items_seen += 1
          discounted_items.push(line_item.split(take: 1))
          if discounted_items_seen == @discounted_item_count
            paid_items_seen = 0
            discounted_items_seen = 0
          end
        end
      end
    end

    discounted_items
  end
end

CAMPAIGNS = [
  BogoCampaign.new(
    ProductTagSelector.new("bogo"),
    PercentageDiscount.new(100, "Buy 2 get 1 free"),
    InterleavedPartitioner.new(2, 1)
  ),
]

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

Output.cart = Input.cart
它会变成什么

识别为 Buy X, get Y,重建为 bxgy 类型的优惠。下面是优惠实际保存时使用的配置键,您可以逐项核对自己的重建结果。

逐项列出的设置
设置项配置键
Offer typebxgytype
Countingper_groupcounting
Recurrencerepeatrecurrence
Tier 1min qty 2 -> free itemtiers[0]
Buy quantity2bxgy.buyQty
Get quantity1bxgy.getQty
Get selectionsame_itembxgy.getSelection
Reward on the get units100% offbxgy.getDiscountPct
Free units are additionaltruebxgy.freeUnitsAreAdditional
Target scopetagstarget.scope
Target includesbogotarget.includeIds
MethodautomaticdiscountMethod
Allocationstandardstacking.allocation
Combines with other discountsnostacking
系统会请您确认
  • Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect.
系统会告知您
  • Your Script used Shopify's own item ordering to choose what to discount. We use the campaign's allocation order, which can pick a different item in a mixed cart.
用于验证的购物车

基于我们的公开演示店铺 Meridian Goods 搭建,因此这里的每个价格都可以复现,而不必凭信任接受。下方的折扣金额,是结账时运行的同一个引擎针对这个购物车算出的结果。

  • No Meridian Goods product carries the tag bogo. Set it on Aria Wireless Earbuds in Shopify before you build the cart, and on nothing else.
触发这个优惠的购物车,以及它的花费
商品数量单价
Aria Wireless Earbuds3$79.00
小计$237.00
折扣-$79.00
总额$158.00

未登录,或以没有标签的客户身份登录。

工具用来核对您的金额

发布之前,工具会询问您原来的 Script 对一个现有购物车做了什么。把它设为 3 件 Aria Wireless Earbuds,单价 $79.00,答案就是固定的。

折扣金额为 $79.00。顾客实际支付的总额为 $158.00。

比对精确到您所用货币的最小单位。差一分钱,发布就仍然被拦住,这正是这一步的意义。

必须没有任何结果的购物车
  • drop to 1 of the same product, under what the rule needs
不应触发这个优惠的购物车
商品数量单价
Aria Wireless Earbuds1$79.00
小计$79.00
总额$79.00

未登录,或以没有标签的客户身份登录。

Bogo cross line low to high (D17)

可重建

危险配对 D17。这个文件和它的搭档看起来几乎一样,行为却不同,在判断您手上是哪一个之前,请把两份都读一遍。

原始 Ruby

class LowToHighPartitioner
  def initialize(paid_item_count, discounted_item_count)
    @paid_item_count = paid_item_count
    @discounted_item_count = discounted_item_count
  end

  def partition(cart, applicable_line_items)
    sorted_items = applicable_line_items.sort_by { |line_item| line_item.variant.price }
    total_applicable_items = sorted_items.map(&:quantity).reduce(0, :+)
    discounted_items_to_find = (total_applicable_items / (@paid_item_count + @discounted_item_count)) * @discounted_item_count
    discounted_items = []

    sorted_items.each do |line_item|
      break if discounted_items_to_find <= 0
      take = [line_item.quantity, discounted_items_to_find].min
      discounted_items.push(line_item.split(take: take))
      discounted_items_to_find -= take
    end

    discounted_items
  end
end

CAMPAIGNS = [
  BogoCampaign.new(
    ProductTagSelector.new("bogo"),
    PercentageDiscount.new(100, "Buy 2 get 1 free"),
    LowToHighPartitioner.new(2, 1)
  ),
]

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

Output.cart = Input.cart
它会变成什么

识别为 Buy X, get Y,重建为 bxgy 类型的优惠。下面是优惠实际保存时使用的配置键,您可以逐项核对自己的重建结果。

逐项列出的设置
设置项配置键
Offer typebxgytype
Countingper_groupcounting
Recurrencerepeatrecurrence
Tier 1min qty 2 -> free itemtiers[0]
Buy quantity2bxgy.buyQty
Get quantity1bxgy.getQty
Get selectioncheapest_eligiblebxgy.getSelection
Reward on the get units100% offbxgy.getDiscountPct
Free units are additionaltruebxgy.freeUnitsAreAdditional
Target scopetagstarget.scope
Target includesbogotarget.includeIds
MethodautomaticdiscountMethod
Allocationstandardstacking.allocation
Combines with other discountsnostacking
系统会请您确认
  • Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect.
用于验证的购物车

基于我们的公开演示店铺 Meridian Goods 搭建,因此这里的每个价格都可以复现,而不必凭信任接受。下方的折扣金额,是结账时运行的同一个引擎针对这个购物车算出的结果。

  • No Meridian Goods product carries the tag bogo. Set it on Aria Wireless Earbuds and Impact Phone Case in Shopify before you build the cart, and on nothing else.
触发这个优惠的购物车,以及它的花费
商品数量单价
Impact Phone Case2$24.00
Aria Wireless Earbuds1$79.00
小计$127.00
折扣-$24.00
总额$103.00

未登录,或以没有标签的客户身份登录。

工具用来核对您的金额

发布之前,工具会询问您原来的 Script 对一个现有购物车做了什么。把它设为 3 件 Impact Phone Case,单价 $24.00,答案就是固定的。

折扣金额为 $24.00。顾客实际支付的总额为 $48.00。

比对精确到您所用货币的最小单位。差一分钱,发布就仍然被拦住,这正是这一步的意义。

必须没有任何结果的购物车
  • drop to 1 of the same product, under what the rule needs
不应触发这个优惠的购物车
商品数量单价
Impact Phone Case1$24.00
小计$24.00
总额$24.00

未登录,或以没有标签的客户身份登录。

两个看起来一样的文件

下面每一对都是同一种 Script 写法的两个版本。它们只差一两行,效果却不同,所以在判断自己手上是哪一个之前,请把两个都读一遍。

危险配对 D17

Bogo cross line interleaved (D17)

可重建

重建为 bxgy 优惠。

在它自己的购物车中的折扣:$79.00

不同的行
class InterleavedPartitioner
    sorted_items = applicable_line_items.sort_by { |line_item| line_item.variant.price }.reverse
    paid_items_seen = 0
    discounted_items_seen = 0
      line_item.quantity.times do
        if paid_items_seen < @paid_item_count

另有 11 行差异,在它自己的页面上。

阅读BOGO across the cart

Bogo cross line low to high (D17)

可重建

重建为 bxgy 优惠。

在它自己的购物车中的折扣:$24.00

不同的行
class LowToHighPartitioner
    sorted_items = applicable_line_items.sort_by { |line_item| line_item.variant.price }
    total_applicable_items = sorted_items.map(&:quantity).reduce(0, :+)
    discounted_items_to_find = (total_applicable_items / (@paid_item_count + @discounted_item_count)) * @discounted_item_count
      break if discounted_items_to_find <= 0
      take = [line_item.quantity, discounted_items_to_find].min

另有 3 行差异,在它自己的页面上。

阅读BOGO across the cart

常见问题

Will Stackable rebuild this script?
Yes. Every spelling on this page is rebuilt today as a bxgy offer, and the cart above is the one that proves it.
What cart proves it works?
3 x Aria Wireless Earbuds at $79.00. The engine takes $79.00 off, and checkout charges $158.00.
What will I have to check before publishing?
Your Script limited this to a tag, vendor, or product type. We carried that filter over, so confirm it selects the products you expect. Your Script used Shopify's own item ordering to choose what to discount. We use the campaign's allocation order, which can pick a different item in a mixed cart.

相关的 Script 类型

Buy one get one free

A set of paid units earns an extra unit at no charge.

Buy X get Y, inclusive

The same buy-and-get offer, counted so the reward sits inside each set rather than beside it.

Limit the discounted units

The discount applied to the first few units only, with the rest at full price.

粘贴您的 Script,看看它如何被重建

在您发布之前,重建结果会与原来的 Script 收取的金额进行核对。

我们使用必要 Cookie 来运行本网站,并仅在获得你许可的情况下,使用分析 Cookie 来了解访问情况。详见我们的 Cookie 政策.