用途
扫描商品变体中的选项值,检测命名不一致的情况(例如 "Sm"、"Small"、"small"、"S" 都表示同一尺码),并按你定义的标准值批量更新。选项命名不一致会破坏尺码筛选、造成顾客困惑,并使搜索应用无法正确分组变体。
前置条件
- 已认证的 Shopify CLI 会话:shopify store auth --store <domain> --scopes read_products,write_products
- API 权限范围:read_products、write_products
参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| store | string | 是 | — | 店铺域名(例如 mystore.myshopify.com) |
| option_name | string | 是 | — | 要标准化的选项(例如 Size、Color) |
| mapping | object | 是 | — | 非标准值到标准值的映射(例如 {"Sm": "S", "small": "S", "Sml": "S"}) |
| filter | string | 否 | — | 可选商品筛选(例如 tag:apparel) |
| dry_run | bool | 否 | true | 预览变更而不执行 mutation |
| format | string | 否 | human | 输出格式:human 或 json |
安全提示
⚠️ productVariantsBulkUpdate 会修改变体选项值。选项值变更会影响变体在店面中向顾客展示的方式,并可能破坏现有购物车链接或已保存的愿望清单。请先以 dry_run: true 运行,在提交前审查所有受影响的变体。
工作流程
- OPERATION: products — query
- 输入:query: <filter>(无筛选时查询全部商品)、first: 250、select options、variants { selectedOptions }、分页游标
- 预期输出:带变体选项值的商品;分页直到 hasNextPage: false
- 将变体选项值与 mapping 的键进行匹配——收集需要更新的变体
- OPERATION: productVariantsBulkUpdate — mutation
- 输入:productId、受影响变体的数组 { id, options: [<normalized_value>] }
- 预期输出:productVariants { id, selectedOptions }、userErrors
GraphQL 操作
# products:query — validated against api_version 2025-01
query ProductVariantOptions($query: String!, $after: String) {
products(first: 250, after: $after, query: $query) {
edges {
node {
id
title
options {
id
name
values
}
variants(first: 100) {
edges {
node {
id
title
sku
selectedOptions {
name
value
}
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
# productVariantsBulkUpdate:mutation — validated against api_version 2025-01
mutation ProductVariantsBulkUpdate($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
productVariantsBulkUpdate(productId: $productId, variants: $variants) {
productVariants {
id
title
selectedOptions {
name
value
}
}
userErrors {
field
message
}
}
}
会话跟踪
Claude 必须在每个阶段输出以下内容。这是强制要求。
开始时输出:
╔══════════════════════════════════════════════╗
║ SKILL: Variant Option Normalizer ║
║ Store: <store domain> ║
║ Started: <YYYY-MM-DD HH:MM UTC> ║
╚══════════════════════════════════════════════╝
每一步之后输出:
[N/TOTAL] <QUERY|MUTATION> <OperationName>
→ Params: <brief summary of key inputs>
→ Result: <count or outcome>
如果 dry_run: true,则在每个 mutation 步骤前加上 [DRY RUN] 前缀,并且不执行它。
完成时输出:
对于 format: human(默认):
══════════════════════════════════════════════
OUTCOME SUMMARY
Products scanned: <n>
Variants needing fix: <n>
Variants updated: <n>
Errors: <n>
Output: option_normalizer_<date>.csv
══════════════════════════════════════════════
对于 format: json,输出:
{
"skill": "variant-option-normalizer",
"store": "<domain>",
"started_at": "<ISO8601>",
"completed_at": "<ISO8601>",
"dry_run": true,
"option_name": "Size",
"outcome": {
"products_scanned": 0,
"variants_needing_fix": 0,
"variants_updated": 0,
"errors": 0,
"output_file": "option_normalizer_<date>.csv"
}
}
输出格式
CSV 文件 option_normalizer_<YYYY-MM-DD>.csv,包含列: product_id, product_title, variant_id, sku, option_name, old_value, new_value
错误处理
| 错误 | 原因 | 恢复方式 |
|---|---|---|
| THROTTLED | 超出 API 速率限制 | 等待 2 秒,最多重试 3 次 |
| userErrors on bulk update | 商品内选项值冲突 | 记录错误,跳过该商品,继续 |
| No matching variants | 目录中未找到 mapping 的键 | 以 0 匹配退出,检查 mapping |
最佳实践
- 先以 dry_run: true 运行并审查检测到的选项值来构建 mapping——你可能会发现比预期更多的变体。
- 一次只标准化一个 option_name(先 Size,再 Color),以保持 mapping 可管理并降低错误风险。
- 标准化后,验证基于选项值的自动集合规则是否仍匹配预期的商品。