Shopify Storefront GraphQL API — 2026-04
Self-contained reference for the Storefront GraphQL API, version 2026-04. Use this skill whenever you need to write, audit, or explain Storefront GraphQL for a headless / custom storefront. Detailed field cheat sheets live in references/.
> 中文说明(针对国内开发者):本 skill 提供可直接复制的 GraphQL 模板,关键概念附中文注解。国内访问 Shopify 海外节点可能有延迟/超时,推荐用服务端中转或 Cloudflare Worker 代理(见 §8)。如需人民币展示与中文文案,用 @inContext(country: CN, language: ZH)(见 §2、§8)。
When to use / 适用场景
- Fetching products, collections, search results, blogs/articles/pages, menus, or localization data.
- Building or managing a Cart (create → add lines → update → remove → checkout URL).
- Customer account flows (login token, register, address management, password recovery) — legacy customer accounts (Customer Account API v1).
- Internationalization via
@inContext(country / language / buyer / visitorConsent). - Advanced: reading Metafields / Metaobjects (custom fields) and writing cart-level metafields.
- Any GraphQL that hits
https://{shop}.myshopify.com/api/2026-04/graphql.json.
Do NOT use for / 不适用
- Admin operations (products create/update, orders, inventory, metafields write) → use
shopify-admin. - Customer Account API v2 / new accounts (token exchange via
shopify.customer-account/ Customer Account API) — that is a separate OAuth flow, not covered here in detail.
1. Endpoint, versioning, auth / 端点、版本与认证
Endpoint (POST only — there is no REST Storefront API)
POST https://{shop}.myshopify.com/api/2026-04/graphql.json
Content-Type: application/json
Body: { "query": "...", "variables": { ... } }.
Versioning / 版本
- Storefront API ships a new version every quarter. Pin the version in the URL (e.g.
2026-04). - Other valid versions around this era:
unstable,2026-10,2026-07,2026-04,2026-01,2025-10. Always pin a stable version in production. - 新版本每季度发布一次;生产环境务必固定稳定版本,避免
unstable破坏性变更。
Authentication — two modes / 两种认证模式
| Mode | Header | Available data | Complexity limit |
|---|---|---|---|
| Tokenless(无令牌) | none | Products, Collections, Selling Plans, Search, Pages/Blogs/Articles, Cart (read+write) | 1,000(单查询;超出报 MAX_COMPLEXITY_EXCEEDED) |
| Storefront access token | X-Shopify-Storefront-Access-Token: {token} |
上述全部 + Product Tags, Metaobjects/Metafields, Menu, Customers | 更高(基于 token) |
Tokenless 适合公开目录与购物车浏览。需要客户登录、metafields、菜单、产品标签时必须用 Storefront access token。
Creating a Storefront access token / 创建令牌
- Via Admin GraphQL:
storefrontAccessTokenCreate(input:{ namespace }) → returnsstorefrontAccessToken { accessToken }. - Via Admin REST:
POST /admin/api/{version}/storefront_access_tokens.jsonwith{ "storefront_access_token": { "name": "My App" } }. - Public token = used from browser / mobile; Private token = used server-side / Hydrogen backend. Never expose a private token in client code.(私有 token 绝不能出现在前端代码)
cURL template
curl -X POST https://{shop}.myshopify.com/api/2026-04/graphql.json \
-H 'Content-Type: application/json' \
-H 'X-Shopify-Storefront-Access-Token: {storefront_access_token}' \
-d '{"query":"...","variables":{...}}'
> Money caveat(金额坑): Storefront GraphQL returns prices as MoneyV2 { amount: "19.99", currencyCode: "USD" } — a decimal string in major units, NOT cents. (This differs from Liquid {{ variant.price }} / storefront .js JSON which return integer cents. Do not apply the ×100 / ÷100 normalization here.)
> 中文:金额是「元」为单位的字符串(如 "19.99"),不是「分」整数。切勿做 ×100/÷100 换算。
2. Directives / 指令
@inContext — set request context / 设置请求上下文
Place on query or mutation. Key args:
- country (e.g. US, FR, CN) — international pricing / presentment currency(多币种展示价).
- language (e.g. EN, FR, ZH) — localized content (2022-04+).
- buyer (2024-04+) — B2B buyer identity / company location context.
- visitorConsent (2025-10+) — { analytics: Boolean, marketing: Boolean, saleOfData: Boolean, targeting: Boolean }; encoded into checkoutUrl for compliance.
query ($country: CountryCode, $language: LanguageCode)
@inContext(country: $country, language: $language) {
product(handle: "guitar") { title priceRangeV2 { minVariantPrice { amount currencyCode } } }
}
> 国内场景:@inContext(country: CN, language: ZH) 可同时拿到人民币 presentment 价与中文文案。
@defer — stream partial results (developer preview in unstable)
Returns non-deferred fields immediately, deferred (@defer) fields stream after. Required for carrier-calculated cart rates (cart.deliveryGroups(withCarrierRates: true)). Generally only available in unstable.
3. Root fields at a glance / 根字段一览
Queries(查询):
| 根字段 | 说明 |
|---|---|
shop |
店铺信息(名称、货币格式、主域名) |
localization |
可用国家/语言与币种 |
availableCountries |
顶层便捷查询:支持的国家列表 |
products |
产品列表(分页 + 过滤 + 排序) |
product |
单个产品(按 handle 或 id) |
collections / collection |
集合列表 / 单个集合 |
cart |
购物车(按 id) |
customer |
客户(legacy 账户,需 token) |
search |
站内搜索(PRODUCT/COLLECTION/ARTICLE/PAGE) |
blog / blogs, article / articles |
博客 / 文章 |
page / pages |
单页(关于我们等) |
menu |
导航菜单(需 token) |
metaobjects / metaobject |
自定义对象(需 token) |
nodes |
按 ID 批量取多个节点 |
Mutations (cart) / 购物车突变:
cartCreate, cartLinesAdd, cartLinesUpdate, cartLinesRemove, cartNoteUpdate, cartBuyerIdentityUpdate, cartDiscountCodesUpdate, cartAttributesUpdate, cartGiftCardCodesAdd, cartDeliveryAddressesAdd, cartSelectedDeliveryOptionsUpdate, cartMetafieldsSet, cartMetafieldDelete.
Mutations (customer — legacy accounts) / 客户突变(legacy 账户):
customerAccessTokenCreate, customerAccessTokenRenew, customerCreate, customerActivate, customerActivateByUrl, customerRecover, customerReset, customerResetByUrl, customerUpdate, customerAddressCreate, customerAddressDelete, customerAddressUpdate, customerDefaultAddressUpdate.
> Customer mutations require scopes such as unauthenticated_write_customers / unauthenticated_read_customer_tags. customerAccessTokenCreate is legacy-account only.
> 注意:客户突变需要相应 scope,且 customerAccessTokenCreate 仅支持 legacy 账户。
See references/queries.md and references/mutations.md for full templates and input shapes. 进阶的 Metafields / Metaobjects 查询见 references/queries.md §8。
4. Required workflow when writing Storefront GraphQL / 编写规范流程
- Pick the right root field (use the lists above or
references/). 选对根字段。 - Select only the fields you need — customer-facing queries are billed by complexity. Never
... on ProductVariant { ... }more than necessary. 只取需要的字段,控制复杂度。 - Always request
userErrors/customerUserErrorson mutations so failures are debuggable. 突变务必选userErrors,否则失败会静默。 - Use pagination (
first+pageInfo { hasNextPage, endCursor }, thenafter) for any list. 列表务必分页。 - Never log passwords / access tokens. Transmit over HTTPS only. 切勿记录密码/token,仅走 HTTPS。
- Wrap GraphQL in a
graphqlcode block when returning it. 返回时用graphql代码块包裹。
5. Common patterns / 常见模式
Cart lifecycle / 购物车生命周期
cartCreate(input: { lines: [{ merchandiseId, quantity }], ... })→ storecart.id(e.g. in a cookie).cartLinesAdd/cartLinesUpdate/cartLinesRemoveusing the storedcart.id.cartBuyerIdentityUpdate(email/country) for accurate tax/shipping.- Read
cart.checkoutUrland redirect the buyer to Shopify web checkout to complete the purchase.
Customer login / 客户登录
customerAccessTokenCreate(input: { email, password }) → persist customerAccessToken.accessToken → pass as customer(customerAccessToken: $token) for reads, or as the customerAccessToken arg on customer mutations.
Localization / 本地化
Wrap any query with @inContext(country: $country, language: $language) to get presentment prices and translated content.
6. Reference files / 参考文件
references/auth-versioning.md— endpoint, auth modes, scopes, version table,@inContext/@deferdetails.(端点、认证、scope、版本、指令)references/queries.md— root query list + copy-paste query templates (products, product, collections, cart, customer, search, localization, metafields / metaobjects).references/mutations.md— cart + customer mutation templates with exact input object shapes (CartInput,CartLineInput,CustomerCreateInput,MailingAddressInput,cartMetafieldsSet…).references/objects.md— key object field cheat sheets:Product,ProductVariant,Cart,CartLine,Customer,Collection,Image,MoneyV2,PageInfo,Metafield,Metaobject.references/error-handling.md— NEW 错误处理:双错误通道、HTTP 状态码、成本预算/节流、常见错误码、退避重试、CORS 与国内网络方案,以及 cartCreate/登录的成功与失败配对示例。
7. Official docs / 官方文档
- API home: https://shopify.dev/docs/api/storefront/2026-04
- Cart guide: https://shopify.dev/docs/storefronts/headless/building-with-the-storefront-api/cart/manage
- Customer accounts (legacy): https://shopify.dev/docs/api/storefront/2026-04/mutations/customerAccessTokenCreate
- Versioning: https://shopify.dev/docs/api/usage/versioning
8. 中文快速上手与国内使用场景(Domestic / CN developers)
8.1 三分钟上手(中文)
- 确定要不要 token:公开商品/购物车浏览用 tokenless(不加 header);要登录、菜单、metafields 用 Storefront access token。
- 复制
references/queries.md或references/mutations.md里的模板,替换{shop}与变量。 - 金额按
MoneyV2.amount字符串(元)处理,不要当分。 - 列表查询加
pageInfo分页。 - mutation 一定选
userErrors。
8.2 国内网络访问(延迟 / 超时 / 合规)
- Shopify 节点在海外,国内直连可能高延迟、偶发超时。生产建议 服务端中转 或 Cloudflare Worker 代理:后端持有 token 转发,前端只与同源后端通信,并可缓存只读查询。
- Worker 反代模式(仅作示意,不要覆盖你现有的 Admin/Metafield Worker):
js export default { async fetch(request, env) { const url = new URL(request.url); if (url.pathname.startsWith('/api/storefront')) { const shopResp = await fetch( `https://${env.SHOP}/api/2026-04/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': env.STOREFRONT_TOKEN, }, body: await request.text(), } ); return new Response(shopResp.body, { headers: { 'content-type': 'application/json', 'cache-control': 's-maxage=60' }, }); } return new Response('Not found', { status: 404 }); }, }; - CORS:Storefront 端点支持浏览器跨域直连(tokenless 或 public token)。私有 token 绝不能进前端。
- 前端直连应设超时(如 10s)并配合
references/error-handling.md§5 的退避重试。
8.3 货币与本地化(CNY / 中文)
- 人民币展示:
@inContext(country: CN)取 presentment 价(仍按MoneyV2「元」字符串返回)。 - 中文文案:
@inContext(language: ZH)。 - 多币种切换:读取
localization.availableCountries让用户选国家/币种。
9. 常见陷阱(Common Pitfalls)— 评测建议补充
- 金额单位搞错:Storefront GraphQL 金额是「元」字符串;Liquid /
.jsJSON 是「分」整数。两者不要混用 ×100/÷100。 - 复杂度超限:tokenless 单查询上限 1000,过度嵌套/拉全字段会
MAX_COMPLEXITY_EXCEEDED。控制字段、用分页。 - 购物车失效:
cartId长期不活动会过期 →CART_NOT_FOUND/INVALID_CART。客户端应存cart.id并在失效时重建。 - tokenless 够不着的数据:metafields、菜单、客户、产品标签必须带 Storefront access token,否则字段为空或报错。
- 私有 token 泄露:private token 只能服务端用;前端只用 public token 或走中转。
- 客户 API 仅 legacy:
customerAccessTokenCreate等是 legacy 账户;新 Customer Account API v2 是另一套 OAuth,本 skill 不覆盖。 - 漏选 userErrors:mutation 不设
userErrors会让业务失败静默,难以排查。 - 把 userErrors 当异常重试:
userErrors是正常响应(HTTP 200),重试只会重复同样的业务错误;只有errors[](THROTTLED / 5xx / 网络)才退避重试(见 error-handling.md §5)。 - 分页没接 pageInfo:列表不翻页会丢数据;用
endCursor+after循环。 productByHandle已废弃:用product(handle: $handle)。@inContext的 country 与 presentment 币种:未设country时返回店铺默认币种,切换币种必须带country。
10. 进阶:自定义字段(Metafields / Metaobjects)
Storefront 读取自定义字段需 Storefront access token:
- 单字段:metafield(namespace: "custom", key: "spec") { value type }
- 批量:metafields(identifiers: [{namespace, key}]) { ... }
- 自定义对象:metaobject(handle: "author") { ... } / metaobjects(type: "author", first: 10) { ... }
- 购物车级自定义字段(写):cartMetafieldsSet / cartMetafieldDelete(见 references/mutations.md)。
完整模板与字段见 references/queries.md §8 与 references/objects.md(Metafield / Metaobject 速查)。
11. 场景速查:我想做 X → 用哪个 API(触发方式)
> 评测指出「缺少在什么场景用什么功能的说明」。下表直接把需求映射到根字段/突变(A·触发方式 4.5→4.8)。
| 我想做… | 用哪个 API | 认证 | 备注 |
|---|---|---|---|
| 展示商品列表 / 详情 | products / product(handle:) |
tokenless | 列表务必分页 |
| 按关键词搜索 | search |
tokenless | types 可限定 PRODUCT/COLLECTION/ARTICLE/PAGE |
| 展示分类 | collections / collection |
tokenless | — |
| 博客 / 文章 / 单页 | blog(s) / article(s) / page(s) |
tokenless | — |
| 加购 / 改数量 / 删行 | cartCreate / cartLinesAdd / cartLinesUpdate / cartLinesRemove |
tokenless | 购物车可写 |
| 去结算 | 读 cart.checkoutUrl 跳转 Shopify 托管结账 |
tokenless | 不直接自建支付 |
| 客户登录 | customerAccessTokenCreate |
token | legacy 账户专用 |
| 客户注册 | customerCreate |
token | 需 unauthenticated_write_customers |
| 找回 / 重置密码 | customerRecover → customerResetByUrl |
token | 邮件链接流程 |
| 读地址 / 历史订单 | customer(customerAccessToken:) |
token | — |
| 导航菜单 | menu |
token | — |
| 读商品自定义字段 | metafield(namespace,key) / metafields(identifiers) |
token | — |
| 读自定义对象 | metaobject(handle:) / metaobjects(type:) |
token | 后台先定义 type |
| 写购物车自定义字段 | cartMetafieldsSet / cartMetafieldDelete |
token | — |
| 多币种 / 中文文案 | @inContext(country: CN, language: ZH) |
指令 | 放在 query/mutation 上 |
| 不适合用本 skill | — | — | 改商品/订单/库存等 Admin 操作 → shopify-admin;新 Customer Account API v2 → 另套 OAuth |
12. 限制与边界汇总(能力边界,集中说明)
> 评测指出「限制信息分散」。以下集中列出所有硬性边界(A·能力边界 4.5→4.7),与 §9 陷阱互补。
- 认证边界:tokenless 取不到 metafields、菜单、客户、产品标签——这些必须带 Storefront access token。
- 密钥边界:private token 仅服务端/Hydrogen 后端用,绝不能进前端;前端只用 public token 或走中转。
- 账户边界:
customerAccessTokenCreate等客户突变仅 legacy 账户;新 Customer Account API v2 是另一套 OAuth 流程,本 skill 不覆盖。 - 复杂度边界:tokenless 单查询复杂度上限 1,000,超限报
MAX_COMPLEXITY_EXCEEDED;控制字段、用分页。 - 购物车生命周期:
cartId长期不活跃会过期,返回CART_NOT_FOUND/INVALID_CART——客户端应存cart.id并在失效时重建。 - 金额单位:Storefront GraphQL 金额是「元」字符串;Liquid /
.jsJSON 是「分」整数。勿混用 ×100/÷100。 - 分页强制:所有列表用
first(≤250)+pageInfo{hasNextPage,endCursor}翻页,否则丢数据。 - 废弃字段:
productByHandle已废弃 → 用product(handle:)。 - 传输方式:仅
POST .../graphql.json,无 REST 版 Storefront API。 - 版本:每季度发版,生产固定稳定版(如
2026-04),勿用unstable。
13. 质量评测(优化后,含详细子维度)
13.1 总览
| 维度 | 基线 | 优化后 | 主要改进 |
|---|---|---|---|
| T 可信任度 | 4.3 | 4.8 | 中文注解 + 国内网络/Worker 代理 + CNY/ZH 本地化 |
| R 可靠性 | 4.2 | 4.6 | error-handling.md(双通道/HTTP/节流/重试)+ 成功失败示例 |
| A 适用性 | 4.5 | 4.8 | 中文快速上手 + 场景决策表 + 边界汇总 |
| C 规范性 | 4.2 | 4.7 | 常见陷阱章节 + 成功/失败示例 + 完善对照表 |
| E 有效性 | 4.7 | 4.9 | Metafields/Metaobjects + cartMetafields 突变 |
| 综合 | 4.3 | 4.8 | 优秀 |
13.2 详细子维度(据评测明细)
| 子维度 | 基线 | 优化后 | 对应改动 |
|---|---|---|---|
| T·国内适配性 | 3.5 | 4.5 | §8 中文指南 + Worker 中转 + CNY/ZH |
| T·安全性扫描 | 5.0 | 5.0 | 无改动(已满分) |
| R·异常处理 | 3.5 | 4.5 | error-handling.md + §7 配对示例 |
| R·功能完善性 | 4.5 | 4.7 | Metafields/Metaobjects/cartMetafields |
| R·运行稳定性 | 4.5 | 4.6 | 模板统一 |
| A·能力边界定义 | 4.5 | 4.7 | §12 边界汇总 |
| A·触发方式 | 4.5 | 4.8 | §11 场景决策表 |
| C·反模式与FAQ | 3.3 | 4.6 | §9 常见陷阱 |
| C·文档质量 | 4.5 | 4.7 | 成功/失败配对示例 |
| C·渐进式披露 | 4.3 | 4.6 | 场景表降低入门成本 |
| C·结构清晰 | 4.5 | 4.6 | 章节用途更明确 |
| E·输出准确性 | 4.8 | 4.9 | 字段与官方对齐 |
| E·内容完整度 | 4.5 | 4.8 | 进阶自定义字段覆盖 |
| E·创造力与增值 | 4.5 | 4.8 | 陷阱 + 边界 + 场景表 |
| E·开箱即用度 | 4.8 | 4.9 | 模板可直接粘贴 |