跳转到主要内容
Scripts 迁移救援2026 年 6 月 30 日起弃用

Shopify Scripts 已于2026年6月30日停止运行,现在该怎么办?

如果你的店铺曾使用自定义折扣、BOGO 或捆绑销售 Script,它已于2026年6月30日悄然停止执行,没有报错,没有提醒,日志里也不会留下任何痕迹。本文将说明具体发生了什么、迁移到 Shopify Functions 实际涉及哪些工作,以及 Stackable 能为你重建哪些内容,我们会给出诚实的答案。

实际发生了什么
  • 对所有仍在使用的店铺而言,Shopify Scripts 已于2026年6月30日停止执行。
  • 任何写在 Script 中的自定义折扣、BOGO 或捆绑销售逻辑,都在这一天起停止生效。
  • 这种失效是设计使然的静默失效:如果一个 Shopify Function 的触发条件与某个购物车不匹配,它就不会执行,既不会抛出错误,Shopify 也不会通知你。
为何商家常常措手不及

在 Shopify 社区论坛上,正在经历这场迁移的商家都描述了同一种风险:

我原来的 Script 悄悄地停止应用折扣,我是因为有客户投诉被收取了全价才发现的。没有报错,没有提醒,订单日志里也什么都没有。我在完全没意识到的情况下,用一个失效的配置运行了好几个星期。

这正是从 Scripts 迁移到 Functions 的核心风险:一个 Function 要么配置正确并正常运行,要么配置有误并陷入静默,中间没有任何可见状态。一个不匹配的条件、一个阈值里的拼写错误、一个作用于错误商品系列的规则,产生的静默表现和正常运行完全一样。唯一的应对方法,就是在正式上线前,主动从两个方向分别测试。

迁移实际涉及哪些工作

开始前值得了解的四件事

01

一个 Script 常常会变成三次迁移

一个 Script 文件可能同时涉及折扣逻辑、运费和支付定制。Functions 把这些拆分成三种独立的 Function 类型:折扣、配送和支付,各自单独配置和部署。迁移“你的 Script”通常意味着要迁移多达三个不同的部分,这也是商家对这次迁移抱怨最多的一点。

02

无代码构建工具通常只覆盖折扣和 BOGO

如果你的 Script 还涉及运费或支付方式,折扣类 Function 的无代码构建工具(包括 Stackable)无法覆盖这部分内容。配送和支付方面的定制,需要由开发者直接编写对应的 Function。

03

现在就保存好你的旧 Script 源代码

一旦 Script Editor 被彻底下线,其中存储的代码将无法再找回。请立即导出或复制你的旧 Script 源代码,哪怕现在还没准备好迁移,这样在替换方案上线时你手上仍有参考依据。

04

分别测试“应该触发”和“不应该触发”的购物车

在正式信任一个新 Function 之前,先构建两个测试购物车:一个应该触发它,另一个刻意设计成不应该触发。一个在不该触发时触发的 Function,代价并不亚于一个该触发却静默不触发的 Function。

Scripts 和 Functions 实际上是如何运作的

解释每一个迁移决策的三件事

几乎所有关于什么能重建、什么不能重建的争论,都可以归结为三个事实:Scripts 分为三种类型,每种只有一个名额;Functions 把这三种类型拆分到了四个不同的 API 中;而一个 Function 必须在运行之前就声明它将要读取的每一项数据。掌握了这三点,本页余下的内容就只是算术问题了。

Shopify Scripts 分为三种类型

Script Editor 要求你在写下第一行 Ruby 代码之前先选择一种类型,而这个类型决定了你的代码可以触碰什么。

商品行 Script

改变商品价格的那一类。它们逐行遍历购物车并重新定价,每一种阶梯折扣、BOGO、捆绑价和降价都存在于这里。

运费 Script

作用于配送费率的那一类。它们可以给某个费率打折、隐藏它、重命名它,或者调整顾客看到的列表顺序。这四种操作中只有第一种才是折扣。

支付 Script

作用于支付方式的那一类,有着同样的四个动作:隐藏某种方式、重命名它、调整列表顺序,或者在实际使用中,多数情况下是对特定购物车隐藏它。

现在来看塑造了每一个你会读到的真实 Script 的限制条件:每种类型同一时间只能发布一个 Script。整个店铺只有一个商品行名额。所以,一个同时运行 VIP 折扣、清仓价、消费门槛和季节性促销的商家,并不会写四个 Script。他们会把这四条规则合并写进同一个文件,通常在文件末尾手写一条“保留价格更优的那个”的规则。这就是为什么真实的 Script 看起来如此纠结。它们不是一条写得很差的规则,而是几条从未被允许分开的规则。

查看合并了四个活动的真实 Script

四个 Function API 取代了它们

Shopify 并没有用单一的东西取代 Scripts,而是用四个 API 取代了它们,划分依据是代码被允许改变什么,而不是它在购物车的哪个环节运行。

Discount Function API

减免金额。商品折扣、订单折扣和运费折扣现在都统一归入这一个 API。如果你的 Script 改变过价格,它就属于这里。

Shopify 的官方文档

Delivery Customization API

隐藏、重命名和重新排序配送选项。Shopify 明确表示,这是唯一能够在结账时定制配送选项的 API,因此无论一款折扣应用怎么搭建,都无法触及这一层。

Shopify 的官方文档

Payment Customization API

隐藏、重命名和重新排序支付方式,此外还包括账期条款以及订单是否需要人工审核。这是旧 Script Editor 中支付那一半功能的集中地。

Shopify 的官方文档

Cart and Checkout Validation API

以提示信息拦截结账。购买限额、年龄验证和最低订单规则都属于这里。它返回的是错误提示,因此只能阻止一笔订单,而不能悄悄地更改它。

Shopify 的官方文档

Stackable 是一款 Discount Function 应用,并且仅此而已。我们构建的是折扣函数,所以你的 Script 对价格做过的任何事,包括运费折扣,我们都能重建。我们不提供配送定制、支付定制或验证函数,所以隐藏某个运费方式、重命名某种支付方式,或限制购买数量,并不是我们因为没做而拒绝,而是这原本就是另一种应用。

把这两部分放在一起,你就会得到商家往往在事后才发现的那句话:一个 Script 常常会变成三次迁移。一个既隐藏了某个运费方式、又拦截了某种支付方式的商品行 Script,如今会变成一个折扣函数、一个配送定制和一个支付定制,需要分别编写和部署。我们更希望你在这里读到这一点,而不是在重建之后才发现。

查看一个其实根本不是折扣的运费 Script

Function 是纯函数,每个字段都要提前声明

Script 是作为普通 Ruby 代码运行的,针对购物车当时恰好持有的任何内容。而 Function 运行在沙盒中,Shopify 保证它不具备以下任何一项:

  • 没有网络。Function 无法在顾客结账时调用你的 ERP、你的会员积分服务商或任何其他服务。
  • 没有时钟。Function 无法查询当前时间,所以“周二半价”必须变成一个定时折扣,而不是代码里的一个判断条件。
  • 没有随机性。无法为十分之一的顾客掷骰子决定结果。
  • 没有文件系统,也无法获取一个未曾申请过的字段。Function 读取的每一项数据都必须提前在输入查询中声明,而这个查询有一个由 Shopify 设定的硬性成本上限。

Shopify 的官方文档

最后这条规则是让商家付出代价最大的一条,值得说清楚这个代价究竟由谁承担。并不是 Shopify 隐藏了这些数据。我们自己的结账查询已经达到 Shopify 允许的最高成本,所以再多要一个字段,就意味着要放弃另一个。我们今天拒绝的 Script 类型中,有九种恰恰是因为这个原因被拒绝,别无其他,包括跳过已经打折的商品、读取省份或邮政编码,以及检查客户下过多少笔订单。这些 Shopify 全部都提供,只是我们还没有为它们腾出空间。这是我们自己的差距,把它说成平台限制就是撒谎。

整个库里,只有两项拒绝属于真正的 Shopify 限制,二者都源于同一个事实:一个店铺上的所有折扣函数在同一时刻运行,彼此看不到对方做了什么。所以,一个曾经询问“这件商品是否已经打过折”、或以已经打折后的小计来衡量门槛的 Script,无论出多少代价,今天都无法由我们或任何其他人重建。拒绝列表上的其余部分都是我们自己该修复的问题,我们在应用内和库中的每一页都是这样标注的。

查看那两个真正属于 Shopify 限制的拒绝案例
代价最大的那个差别

设定价格,不等于减免金额

如果你在手动重建 Script 之前只读一段内容,就读这一段。两个文件可以调用同一个方法、使用同一个常量、写着同样的提示信息,含义却截然相反。下面两个都是真实存在的、都很常见,而它们之间的差别,仅仅是一个减号。

这个把价格设定为 $9.99

FIXED_PRICE = Money.new(cents: 999)

Input.cart.line_items.each do |line_item|
  next unless line_item.variant.product.product_type == "Clearance"
  line_item.change_line_price(FIXED_PRICE * line_item.quantity, message: "Clearance $9.99 each")
end

Output.cart = Input.cart

在一件 $79.00 的商品上,折扣是 $69.01,顾客支付 $9.99。重建为满量优惠,奖励类型是设定价格,按多属性计数并可重复触发,所以每一件都会被重新定价。

完整示例:购物车与设置

这个减免 $9.99

DISCOUNT = Money.new(cents: 999)

Input.cart.line_items.each do |line_item|
  next unless line_item.variant.product.product_type == "Clearance"
  new_price = line_item.line_price - (DISCOUNT * line_item.quantity)
  line_item.change_line_price(new_price, message: "$9.99 off each")
end

Output.cart = Input.cart

在同一件 $79.00 的商品上,折扣是 $9.99,顾客支付 $69.01。重建为满量优惠,奖励类型是每件减免金额,按产品计数且只触发一次。

完整示例:购物车与设置

同样的方法,同样的 $9.99,提示信息的措辞也一样。唯一的破绽是,第二个文件在赋值之前先从 `line_item.line_price` 中做了减法。在一件 $79.00 的商品上读反了方向,单件就会差出 $59.02,无论是往哪个方向出错。而且这两种重建不仅数字不同:一个按多属性计数并可重复触发,另一个按产品计数且只触发一次,所以一旦顾客买了两件,它们的结果也会随之分道扬镳。

这正是常规建议无法捕捉到的失败。一个把文件读反了方向的重建优惠,依然会在该触发的购物车上触发,也依然会在不该触发的购物车上保持静默,所以双向测试根本发现不了它。Scripts 救援换了一个问题来堵住这个漏洞:在允许你发布之前,它会要求你提供一个仍可复现的购物车,说明你原来的 Script 对它收取了多少钱,再把这个数字和重建优惠算出的结果做比对。哪怕只差一分钱,发布也会被拦下。在目前销售 Scripts 迁移服务的五款应用中,我们的调研没有发现任何一款会要求商家证明这笔金额。

把术语翻译过来

每一段 Ruby 代码在活动中会变成什么

重建出错的地方每次都集中在那几个点上,而且几乎从来不是显而易见的地方。奖励部分通常很容易处理。计数方式和是否重复触发,才是金额悄悄发生变化的地方,因为 Script 用算术表达它们,而活动用一个设置项表达它们。

在 Script 中在活动中出错之处
change_line_price(PRICE * qty)奖励为设定价格的满量优惠。是赋值,不是减法。这正是上面说的那个陷阱。单价直接变成了那个常量,所以一件 $79 的商品会以 $9.99 出售。
line_price - (AMOUNT * qty)奖励为每件减免金额的满量优惠。减法才是关键信号。和上一行是同一个常量,账单却完全不同。
line_price * 0.9奖励为 10 的百分比优惠。这个乘数代表顾客保留的部分,而不是节省的部分。如果直接填成 90,就相当于把十分之九的商品目录送了出去。
next unless line_item.quantity >= 3最低数量为 3 的阶梯。阶梯在边界值上是包含的,且只有满足条件中最高的那一档会生效。把一条规则叠加在另一条上的 Script,没有对应的单一优惠可以替代,需要各自拆成一个优惠。
line_items.size > 1最低数量为 2。并不是同一条规则。Script 在这里计数的是购物车行,活动计数的是件数,所以同一行里装着两件相同商品时,现在会满足条件,而原来的 Script 会忽略它。
sets = quantity / (BUY + GET)买 X 送 Y,赠送件数按额外计入。如果只除以购买件数,赠送件数就会被算作包含在内。以买 3 送 1、共九件为例,这会导致差别是送两件还是送三件。只差一个字符,多送出去一半。
customer.tags.include?("vip")客户资格限定为标签。Shopify 会精确匹配标签,包括大小写,而很多 Script 写法会先把两边都转成小写。请在发布之前检查拼写,而不是之后。
product.tags / product_type / vendor目标范围设为标签、产品类型或供应商。遗漏一行范围设置,是这张表里代价最大的错误,因为它会把“对促销标签打 8 折”变成对你卖的所有商品都打 8 折。

这张表里你找不到的一项是产品系列。Script 可以读取商品的标签、类型和供应商,但永远读取不到它的产品系列,所以任何声称在检查产品系列的 Ruby 代码,实际上都没有做到它看起来在做的事。活动可以以产品系列为目标;你原来的 Script 做不到。

每一种情况,都写清楚

查找你的 Script,而不是自己推理

我们已经收录的每一种 Script 类型都有自己的页面:原始 Ruby 代码、它被识别为什么、它变成的确切配置、一个来自我们公开演示店铺、由真实引擎为其算出折扣的购物车,以及一个必须保持静默的购物车。拒绝的情况也用同样的方式写出来,每一条都标注为 Shopify 限制、我们自己的差距,或者需要另一种应用来完成的工作。这正是我们当初开始时想要的参考资料,所以我们把它公开出来。

Script 类型
42
当前可重建
38
已拒绝,附原因
21
Stackable 能做到什么,不能做到什么

关于适用范围的诚实回答

Stackable 基于原生 Shopify Functions 重建基于规则的折扣逻辑,但不会运行任意自定义代码。

Stackable 可以重建的部分

  • 阶梯 / 数量折扣(例如“购买3件及以上立省15%”)
  • 买X送Y及 BOGO 逻辑,包括可重复叠加的阶梯
  • 各优惠之间的明确折扣叠加规则
  • 任意活动的定时开始、结束及即时暂停

以下部分仍需要开发者

  • 你旧 Script 中运行的任意自定义代码(例如定制化的定价公式,或无代码工具无法覆盖的一次性条件)
  • 运费 / 配送定制(属于另一种独立的 Function 类型)
  • 支付定制(属于另一种独立的 Function 类型)
  • 任何无法归结为基于规则的折扣配置的内容

如果你原来的 Script 涉及以下任意一项,任何无代码构建工具(包括 Stackable)都无法覆盖,这需要由开发者编写 Function,而非通过配置界面完成。

常见问题

常见问题

我原来的 Scripts 消失了吗?

Scripts 已于2026年6月30日停止执行,但这并不等同于 Script Editor 中存储的源代码在同一时刻被删除。无论如何,请立即导出或复制你的旧 Script 代码:一旦 Shopify 彻底下线该编辑器,代码将无法再找回。

如果 Function 配置有误,我会收到报错吗?

不会。一个触发条件与购物车不匹配的 Function 只会静默地不触发,没有报错,也没有提醒。在正式投入生产环境之前,务必分别用一个应该触发和一个不应该触发的购物车进行测试。

Stackable 能替代我旧 Script 的所有功能吗?

只能替代基于规则的部分:阶梯及数量折扣、BOGO、折扣叠加和定时排程,全部基于原生 Shopify Functions 重建。Stackable 不运行任意自定义代码。如果你的 Script 做了真正定制化的事情,比如自定义定价公式,或无代码工具无法覆盖的条件,仍然需要开发者直接编写对应的 Function。

我 Script 里处理的运费或支付逻辑该怎么办?

这些属于 Stackable 不涉及的独立 Function 类型(配送和支付)。你需要让开发者将它们与折扣逻辑分开单独迁移。

Scripts 救援属于哪个套餐?

Scripts 救援这个读取你旧 Ruby 代码并重建它的工具,属于 Pro 套餐。Stackable 本身可以免费安装,核心折扣引擎,包括满量阶梯、买 X 送 Y、消费目标、免运费、排期设置和模拟器,在所有套餐中都是免费的。唯独 Ruby 救援不是:它和多店铺、Shopify Flow 一起,都在 Pro 套餐中。

我怎么知道重建后的折扣收取的金额和原来一样?

因为在发布之前,你必须先证明这一点。测试一个应该触发和一个不该触发的购物车是常规建议,但它无法捕捉到最糟糕的那种失败:一个正确触发、金额却算错了的优惠。Scripts 救援会要求你提供一个仍可复现的购物车,说明你原来的 Script 对它收取了多少钱,再把这个数字和重建优惠算出的结果做比对,在两者精确到分毫一致之前,发布始终被拦住。我们对目前销售 Scripts 迁移服务的五款应用做了调研,没有发现任何一款会提出这样的要求。

为什么我的 Script 看起来这么复杂?

因为每种类型同一时间只能发布一个 Script。一个同时运行四个促销活动的店铺无法写四个 Script,所以它把四条规则合并写进同一个文件,并在末尾加一条规则来决定哪一个胜出。大多数看起来难以阅读的 Ruby 代码,其实是几条共用一个名额的简单规则,而它们各自单独重建时通常都很干净。

在哪里可以阅读完整的迁移说明?

我们的第一篇博客文章详细介绍了 Scripts 的下线过程和迁移路径,而 Script 示例库里,每一种 Script 类型都有自己的页面,附有原始 Ruby 代码和确切的重建结果。

安装 Stackable,重建你的规则型折扣

批量折扣阶梯、BOGO、叠加和定时促销,从第一天起就运行在原生 Shopify Functions 之上。

Scripts 救援属于 Pro 套餐。Stackable 本身可以免费安装,无需信用卡。

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