Shopify Scripts 与 Functions 迁移
Shopify Scripts 是 Shopify Plus 专属的可编程能力,用 Ruby 编写,控制购物车、运费、支付的自定义逻辑。Shopify 已宣布 2024 年 8 月 28 日彻底停用 Scripts,全面迁移到新一代 Shopify Functions。
本文按”Scripts 历史能力 → Functions 替代方案 → Flow 自动化 → 三者协同”展开。如果你仍在维护未迁移的 Scripts 项目,本文的 Functions 部分尤其需要重点关注。
一、Scripts 的三类用途与历史现状
Scripts 历史上分三类:
| 类型 | 用途 | 示例 |
|---|---|---|
| Line Item Scripts | 修改商品价格、折扣 | 满 3 件 9 折 |
| Shipping Scripts | 动态调整运费 | VIP 客户免运费 |
| Payment Scripts | 控制支付方式可用性 | 高客单单隐藏 COD |
重要时间线:
- 2023 年 6 月:Shopify 宣布 Scripts 进入 Sunset
- 2024 年 8 月 28 日:Scripts 完全停用,新功能开发禁止使用
- 2024 年 8 月 28 日后:旧 Scripts 不再生效,必须迁移到 Functions
如果你的店铺仍依赖 Scripts,立即开始迁移——否则相关业务逻辑会失效。
二、Shopify Functions 概述
Functions 是 Scripts 的现代化替代品:
- 不限 Plus:所有 Shopify 套餐都可用(但开发能力门槛较高)
- 服务器端运行:Shopify 服务器上执行,零客户端性能影响
- 多语言:支持 Rust、TypeScript、JavaScript、AssemblyScript
- 更细粒度:分多个 API 类别,每类有明确的输入输出契约
Functions API 类别
| API | 替代 Scripts | 用途 |
|---|---|---|
| Cart Transform | Line Item Scripts(部分) | 修改购物车显示与价格 |
| Product Discount / Order Discount / Shipping Discount | Line Item Scripts(折扣部分) | 应用动态折扣 |
| Delivery Customization | Shipping Scripts | 修改、隐藏、排序配送选项 |
| Payment Customization | Payment Scripts | 修改、隐藏、排序支付方式 |
| Cart Checkout Validation | 新功能 | 拒绝违反规则的购物车 |
| Fulfillment Constraints | 新功能 | 自定义履约规则 |
| Order Routing Location Rule | 新功能 | 订单路由到指定仓库 |
| Local Pickup Delivery | 新功能 | 本地自提点 |
| Pickup Point Delivery | 新功能 | 智能柜 / 自提点 |
开发流程
# 1. 用 Shopify CLI 创建 Function
shopify app generate extension --type product_discount
# 2. 在生成的 src/ 目录编写逻辑
# (Rust 推荐,性能最优;TypeScript 易上手)
# 3. 本地测试
shopify app dev
# 4. 部署
shopify app deployFunction 项目结构(Rust 示例)
my-discount-function/
├── shopify.function.toml # 配置
├── input.graphql # 定义输入数据
├── src/
│ └── main.rs # 核心逻辑
├── Cargo.toml # Rust 依赖
└── README.md三、典型场景迁移
场景 1:满 N 件 9 折
Scripts(旧,Ruby):
# Line Item Script
if Input.cart.line_items.size >= 3
Input.cart.line_items.each do |line_item|
line_item.change_line_price(
line_item.line_price * 0.9,
message: "满 3 件 9 折"
)
end
end
Output.cart = Input.cartFunctions(新,Rust):
use shopify_function::prelude::*;
#[shopify_function]
fn function(input: schema::FunctionRunInput) -> Result<schema::FunctionRunResult> {
let total_quantity: i32 = input
.cart
.lines
.iter()
.map(|line| line.quantity)
.sum();
if total_quantity < 3 {
return Ok(schema::FunctionRunResult { discounts: vec![] });
}
let targets = input
.cart
.lines
.iter()
.map(|line| schema::Target {
cart_line: Some(schema::CartLineTarget {
id: line.id.clone(),
quantity: None,
}),
..Default::default()
})
.collect();
Ok(schema::FunctionRunResult {
discounts: vec![schema::Discount {
message: Some("满 3 件 9 折".to_string()),
value: schema::Value::Percentage(schema::Percentage { value: dec!(10) }),
targets,
conditions: None,
}],
})
}更复杂但更灵活。开发时间约 4-8 工时(首次),熟练后 1-2 小时。
场景 2:VIP 客户免运费
Scripts(旧):
if Input.cart.customer && Input.cart.customer.tags.include?("VIP")
Input.shipping_rates.each do |rate|
rate.apply_discount(rate.price, message: "VIP 免运费")
end
end
Output.shipping_rates = Input.shipping_ratesFunctions(Delivery Customization):
export function run(input) {
const isVIP = input.cart.buyerIdentity?.customer?.hasAnyTag === true;
if (!isVIP) {
return { operations: [] };
}
return {
operations: input.cart.deliveryGroups.flatMap(group =>
group.deliveryOptions.map(option => ({
rename: {
deliveryOptionHandle: option.handle,
title: `免费配送(VIP 福利)`
}
}))
)
};
}注意:Delivery Customization 不能直接改运费金额到零(这是限制)。要实现免运费需要在折扣 Function 中做 Shipping Discount。
场景 3:高客单隐藏 COD
Scripts(旧):
if Input.cart.subtotal_price > Money.new(cents: 50000)
Output.payment_gateways = Input.payment_gateways.reject do |gateway|
gateway.name.downcase.include?("cash on delivery")
end
endFunctions(Payment Customization):
export function run(input) {
const subtotalCents = parseFloat(input.cart.cost.subtotalAmount.amount) * 100;
if (subtotalCents <= 50000) {
return { operations: [] };
}
const codPaymentMethod = input.paymentMethods.find(pm =>
pm.name.toLowerCase().includes('cash on delivery')
);
if (!codPaymentMethod) {
return { operations: [] };
}
return {
operations: [{
hide: { paymentMethodId: codPaymentMethod.id }
}]
};
}四、Shopify Flow
Flow 是 Shopify 自家的低代码自动化工具——基于”触发器 + 条件 + 动作”的工作流引擎。2024 年起向所有 Shopify 套餐开放(之前仅 Plus)。
Flow 与 Functions 的区别
| 维度 | Flow | Functions |
|---|---|---|
| 用户类型 | 运营 / 业务 | 开发者 |
| 开发方式 | 可视化 + 表达式 | 代码(Rust / JS) |
| 执行时机 | 事件触发后异步 | 同步在结账流程中 |
| 用途 | 工作流自动化 | 业务规则定制 |
| 例子 | 高客单订单 Slack 通知 | 高客单隐藏 COD |
简单理解:Flow 改”流程”,Functions 改”价格 / 运费 / 支付”。两者不冲突,互相配合使用。
Flow 常用模板
模板 1:高价值订单通知
触发:Order Created
条件:Order.totalPriceSet > $500
动作:Send Slack message to #vip-orders模板 2:客户分群标签
触发:Customer's order count changes
条件:Customer.totalSpent > $1000
动作:Tag customer with "vip"模板 3:库存预警
触发:Inventory level changes
条件:Variant.inventoryQuantity < 10
动作:Send email to ops@yourstore.com模板 4:拒付订单自动处理
触发:Order risk analysis
条件:Order.riskLevel = "high"
动作:
- Cancel order
- Refund payment
- Tag customer "high-risk"五、第三方自动化工具协同
Flow + Functions 之外,第三方工具填补不同场景:
Zapier
跨工具自动化,Shopify 与外部系统联动:
- Shopify 订单 → QuickBooks 财务
- Shopify 客户 → HubSpot CRM
- 客服邮件 → Slack 通知
价格:$20-$600/月。
Make(Integromat)
类似 Zapier 但更复杂可视化逻辑,价格更亲民:$9-$100/月。
n8n
开源自部署版本。完全可控,运行成本仅服务器开销(约 $5-20/月)。学习曲线陡。
选型决策
| 场景 | 推荐 |
|---|---|
| 店内业务规则 | Shopify Flow |
| Cart / Checkout / Delivery 定制 | Shopify Functions |
| 多工具协同 | Zapier 或 Make |
| 高频复杂工作流 | n8n(自部署) |
六、迁移到 Functions 的项目流程
Step 1:盘点现有 Scripts
Shopify 后台 → Apps → Script Editor → 导出所有 Scripts 代码。
按用途分类:
- 折扣类(多数项目主体)
- 运费类
- 支付类
Step 2:选择 Functions API
每个 Script 对应一个或多个 Function API:
| 原 Scripts | 新 Functions |
|---|---|
| 商品价格折扣 | Product Discount Function |
| 订单整体折扣 | Order Discount Function |
| 运费打折 | Shipping Discount Function |
| 修改 / 隐藏配送方式 | Delivery Customization |
| 修改 / 隐藏支付方式 | Payment Customization |
Step 3:设计
写每个 Function 的输入输出契约。GraphQL Schema 由 Shopify 提供,你只需定义 input.graphql。
Step 4:开发 + 测试
- Shopify CLI 本地生成项目
- 本地用
shopify app dev测试 - 真实订单验证(用 dev store)
Step 5:部署上线
shopify app deploy推送代码- Shopify 后台关联到具体 Discount / Customization
- 灰度切换(先 10% 流量,观察 48 小时)
- 完成切换后关停旧 Scripts
Step 6:监控
部署后监控:
- Function 执行成功率(Shopify Partner 后台可查)
- 错误日志(Function 执行报错会被记录)
- 业务指标(如折扣覆盖率、运费应用率)
七、Functions 的局限
不是所有 Scripts 逻辑都能迁移:
限制 1:执行时间上限
每个 Function 最多 5ms 执行时间。复杂逻辑可能触顶。
限制 2:网络访问
Functions 无法发起 HTTP 请求。需要外部数据时只能通过 input 预先传入(如客户 metafield)。
限制 3:数据访问范围
每类 Function 能访问的数据有 schema 限制。例如 Delivery Customization 看不到客户订单历史。
限制 4:并发限制
每店每分钟 Function 执行次数有上限。高并发店铺需要优化。
八、避免的常见错误
错误 1:仍在 Scripts 上加新功能
Scripts 已停用,任何新需求都应该用 Functions 实现。
错误 2:用 Function 做”非业务规则”事情
Functions 适合”基于输入返回规则结果”的逻辑。不适合:
- 调外部 API
- 发邮件 / 通知
- 写入数据库
这些用 Flow 或 Webhook 实现。
错误 3:Function 逻辑过于复杂
5ms 执行限制让复杂逻辑可能超时。如果逻辑复杂,考虑预计算(如把客户标签 / 分级提前算好存到 metafield)。
错误 4:忽视测试环境
Function 上线后影响真实结账。必须在 dev store 充分测试。
错误 5:试图同时改多个 Function
多个 Function 同时改动 → 出问题难以归因。一个 Function 验证稳定后再启用下一个。