shopify-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shopify Development Skill

Shopify 开发技能

Use this skill when the user asks about:
  • Building Shopify apps or extensions
  • Creating checkout/admin/POS UI customizations
  • Developing themes with Liquid templating
  • Integrating with Shopify GraphQL or REST APIs
  • Implementing webhooks or billing
  • Working with metafields or Shopify Functions

当用户询问以下内容时使用此技能:
  • 构建 Shopify 应用或扩展
  • 定制 checkout/admin/POS 界面
  • 使用 Liquid 模板开发主题
  • 集成 Shopify GraphQL 或 REST API
  • 实现 webhook 或计费功能
  • 处理 metafields 或 Shopify Functions

ROUTING: What to Build

路由:构建什么

IF user wants to integrate external services OR build merchant tools OR charge for features: → Build an App (see
references/app-development.md
)
IF user wants to customize checkout OR add admin UI OR create POS actions OR implement discount rules: → Build an Extension (see
references/extensions.md
)
IF user wants to customize storefront design OR modify product/collection pages: → Build a Theme (see
references/themes.md
)
IF user needs both backend logic AND storefront UI: → Build App + Theme Extension combination

如果用户想要集成外部服务 或 构建商家工具 或 对功能收费: → 构建一个 应用(查看
references/app-development.md
如果用户想要定制结账流程 或 添加后台界面 或 创建 POS 操作 或 实现折扣规则: → 构建一个 扩展(查看
references/extensions.md
如果用户想要定制店铺前端设计 或 修改商品/集合页面: → 构建一个 主题(查看
references/themes.md
如果用户同时需要后端逻辑 和 店铺前端界面: → 采用 应用 + 主题扩展 的组合方案

Shopify CLI Commands

Shopify CLI 命令

Install CLI:
bash
npm install -g @shopify/cli@latest
Create and run app:
bash
shopify app init          # Create new app
shopify app dev           # Start dev server with tunnel
shopify app deploy        # Build and upload to Shopify
Generate extension:
bash
shopify app generate extension --type checkout_ui_extension
shopify app generate extension --type admin_action
shopify app generate extension --type admin_block
shopify app generate extension --type pos_ui_extension
shopify app generate extension --type function
Theme development:
bash
shopify theme init        # Create new theme
shopify theme dev         # Start local preview at localhost:9292
shopify theme pull --live # Pull live theme
shopify theme push --development  # Push to dev theme

安装 CLI:
bash
npm install -g @shopify/cli@latest
创建并运行应用:
bash
shopify app init          # Create new app
shopify app dev           # Start dev server with tunnel
shopify app deploy        # Build and upload to Shopify
生成扩展:
bash
shopify app generate extension --type checkout_ui_extension
shopify app generate extension --type admin_action
shopify app generate extension --type admin_block
shopify app generate extension --type pos_ui_extension
shopify app generate extension --type function
主题开发:
bash
shopify theme init        # Create new theme
shopify theme dev         # Start local preview at localhost:9292
shopify theme pull --live # Pull live theme
shopify theme push --development  # Push to dev theme

Access Scopes

访问权限范围

Configure in
shopify.app.toml
:
toml
[access_scopes]
scopes = "read_products,write_products,read_orders,write_orders,read_customers"
Common scopes:
  • read_products
    ,
    write_products
    - Product catalog access
  • read_orders
    ,
    write_orders
    - Order management
  • read_customers
    ,
    write_customers
    - Customer data
  • read_inventory
    ,
    write_inventory
    - Stock levels
  • read_fulfillments
    ,
    write_fulfillments
    - Order fulfillment

shopify.app.toml
中配置:
toml
[access_scopes]
scopes = "read_products,write_products,read_orders,write_orders,read_customers"
常见权限范围:
  • read_products
    ,
    write_products
    - 商品目录访问权限
  • read_orders
    ,
    write_orders
    - 订单管理权限
  • read_customers
    ,
    write_customers
    - 客户数据访问权限
  • read_inventory
    ,
    write_inventory
    - 库存水平访问权限
  • read_fulfillments
    ,
    write_fulfillments
    - 订单履约权限

GraphQL Patterns (Validated against API 2026-01)

GraphQL 模式(已针对 API 2026-01 验证)

Query Products

查询商品

graphql
query GetProducts($first: Int!, $query: String) {
  products(first: $first, query: $query) {
    edges {
      node {
        id
        title
        handle
        status
        variants(first: 5) {
          edges {
            node {
              id
              price
              inventoryQuantity
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
graphql
query GetProducts($first: Int!, $query: String) {
  products(first: $first, query: $query) {
    edges {
      node {
        id
        title
        handle
        status
        variants(first: 5) {
          edges {
            node {
              id
              price
              inventoryQuantity
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Query Orders

查询订单

graphql
query GetOrders($first: Int!) {
  orders(first: $first) {
    edges {
      node {
        id
        name
        createdAt
        displayFinancialStatus
        totalPriceSet {
          shopMoney {
            amount
            currencyCode
          }
        }
      }
    }
  }
}
graphql
query GetOrders($first: Int!) {
  orders(first: $first) {
    edges {
      node {
        id
        name
        createdAt
        displayFinancialStatus
        totalPriceSet {
          shopMoney {
            amount
            currencyCode
          }
        }
      }
    }
  }
}

Set Metafields

设置元字段

graphql
mutation SetMetafields($metafields: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      id
      namespace
      key
      value
    }
    userErrors {
      field
      message
    }
  }
}
Variables example:
json
{
  "metafields": [
    {
      "ownerId": "gid://shopify/Product/123",
      "namespace": "custom",
      "key": "care_instructions",
      "value": "Handle with care",
      "type": "single_line_text_field"
    }
  ]
}

graphql
mutation SetMetafields($metafields: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      id
      namespace
      key
      value
    }
    userErrors {
      field
      message
    }
  }
}
变量示例:
json
{
  "metafields": [
    {
      "ownerId": "gid://shopify/Product/123",
      "namespace": "custom",
      "key": "care_instructions",
      "value": "Handle with care",
      "type": "single_line_text_field"
    }
  ]
}

Checkout Extension Example

结账扩展示例

tsx
import {
  reactExtension,
  BlockStack,
  TextField,
  Checkbox,
  useApplyAttributeChange,
} from "@shopify/ui-extensions-react/checkout";

export default reactExtension("purchase.checkout.block.render", () => (
  <GiftMessage />
));

function GiftMessage() {
  const [isGift, setIsGift] = useState(false);
  const [message, setMessage] = useState("");
  const applyAttributeChange = useApplyAttributeChange();

  useEffect(() => {
    if (isGift && message) {
      applyAttributeChange({
        type: "updateAttribute",
        key: "gift_message",
        value: message,
      });
    }
  }, [isGift, message]);

  return (
    <BlockStack spacing="loose">
      <Checkbox checked={isGift} onChange={setIsGift}>
        This is a gift
      </Checkbox>
      {isGift && (
        <TextField
          label="Gift Message"
          value={message}
          onChange={setMessage}
          multiline={3}
        />
      )}
    </BlockStack>
  );
}

tsx
import {
  reactExtension,
  BlockStack,
  TextField,
  Checkbox,
  useApplyAttributeChange,
} from "@shopify/ui-extensions-react/checkout";

export default reactExtension("purchase.checkout.block.render", () => (
  <GiftMessage />
));

function GiftMessage() {
  const [isGift, setIsGift] = useState(false);
  const [message, setMessage] = useState("");
  const applyAttributeChange = useApplyAttributeChange();

  useEffect(() => {
    if (isGift && message) {
      applyAttributeChange({
        type: "updateAttribute",
        key: "gift_message",
        value: message,
      });
    }
  }, [isGift, message]);

  return (
    <BlockStack spacing="loose">
      <Checkbox checked={isGift} onChange={setIsGift}>
        This is a gift
      </Checkbox>
      {isGift && (
        <TextField
          label="Gift Message"
          value={message}
          onChange={setMessage}
          multiline={3}
        />
      )}
    </BlockStack>
  );
}

Liquid Template Example

Liquid 模板示例

liquid
{% comment %} Product Card Snippet {% endcomment %}
<div class="product-card">
  <a href="{{ product.url }}">
    {% if product.featured_image %}
      <img
        src="{{ product.featured_image | img_url: 'medium' }}"
        alt="{{ product.title | escape }}"
        loading="lazy"
      >
    {% endif %}
    <h3>{{ product.title }}</h3>
    <p class="price">{{ product.price | money }}</p>
    {% if product.compare_at_price > product.price %}
      <p class="sale-badge">Sale</p>
    {% endif %}
  </a>
</div>

liquid
{% comment %} Product Card Snippet {% endcomment %}
<div class="product-card">
  <a href="{{ product.url }}">
    {% if product.featured_image %}
      <img
        src="{{ product.featured_image | img_url: 'medium' }}"
        alt="{{ product.title | escape }}"
        loading="lazy"
      >
    {% endif %}
    <h3>{{ product.title }}</h3>
    <p class="price">{{ product.price | money }}</p>
    {% if product.compare_at_price > product.price %}
      <p class="sale-badge">Sale</p>
    {% endif %}
  </a>
</div>

Webhook Configuration

Webhook 配置

In
shopify.app.toml
:
toml
[webhooks]
api_version = "2026-01"

[[webhooks.subscriptions]]
topics = ["orders/create", "orders/updated"]
uri = "/webhooks/orders"

[[webhooks.subscriptions]]
topics = ["products/update"]
uri = "/webhooks/products"
shopify.app.toml
中:
toml
[webhooks]
api_version = "2026-01"

[[webhooks.subscriptions]]
topics = ["orders/create", "orders/updated"]
uri = "/webhooks/orders"

[[webhooks.subscriptions]]
topics = ["products/update"]
uri = "/webhooks/products"

GDPR mandatory webhooks (required for app approval)

GDPR mandatory webhooks (required for app approval)

[webhooks.privacy_compliance] customer_data_request_url = "/webhooks/gdpr/data-request" customer_deletion_url = "/webhooks/gdpr/customer-deletion" shop_deletion_url = "/webhooks/gdpr/shop-deletion"

---
[webhooks.privacy_compliance] customer_data_request_url = "/webhooks/gdpr/data-request" customer_deletion_url = "/webhooks/gdpr/customer-deletion" shop_deletion_url = "/webhooks/gdpr/shop-deletion"

---

Best Practices

最佳实践

API Usage

API 使用

  • Use GraphQL over REST for new development
  • Request only fields you need (reduces query cost)
  • Implement cursor-based pagination with
    pageInfo.endCursor
  • Use bulk operations for processing more than 250 items
  • Handle rate limits with exponential backoff
  • 新开发优先使用 GraphQL 而非 REST
  • 仅请求需要的字段(降低查询成本)
  • 结合
    pageInfo.endCursor
    实现基于游标分页
  • 处理超过250条数据时使用批量操作
  • 使用指数退避策略处理速率限制

Security

安全

  • Store API credentials in environment variables
  • Always verify webhook HMAC signatures before processing
  • Validate OAuth state parameter to prevent CSRF
  • Request minimal access scopes
  • Use session tokens for embedded apps
  • 将 API 凭证存储在环境变量中
  • 处理前始终验证 webhook HMAC 签名
  • 验证 OAuth 状态参数以防止 CSRF 攻击
  • 请求最小必要的访问权限范围
  • 嵌入式应用使用会话令牌

Performance

性能

  • Cache API responses when data doesn't change frequently
  • Use lazy loading in extensions
  • Optimize images in themes using
    img_url
    filter
  • Monitor GraphQL query costs via response headers

  • 数据不频繁变化时缓存 API 响应
  • 扩展中使用懒加载
  • 使用
    img_url
    过滤器优化主题中的图片
  • 通过响应头监控 GraphQL 查询成本

Troubleshooting

故障排除

IF you see rate limit errors: → Implement exponential backoff retry logic → Switch to bulk operations for large datasets → Monitor
X-Shopify-Shop-Api-Call-Limit
header
IF authentication fails: → Verify the access token is still valid → Check that all required scopes were granted → Ensure OAuth flow completed successfully
IF extension is not appearing: → Verify the extension target is correct → Check that extension is published via
shopify app deploy
→ Confirm the app is installed on the test store
IF webhook is not receiving events: → Verify the webhook URL is publicly accessible → Check HMAC signature validation logic → Review webhook logs in Partner Dashboard
IF GraphQL query fails: → Validate query against schema (use GraphiQL explorer) → Check for deprecated fields in error message → Verify you have required access scopes

如果遇到速率限制错误: → 实现指数退避重试逻辑 → 针对大型数据集切换到批量操作 → 监控
X-Shopify-Shop-Api-Call-Limit
响应头
如果认证失败: → 验证访问令牌是否仍然有效 → 检查是否已授予所有必要的权限范围 → 确保 OAuth 流程已成功完成
如果扩展未显示: → 验证扩展目标是否正确 → 检查是否已通过
shopify app deploy
发布扩展 → 确认应用已安装在测试店铺中
如果 webhook 未接收事件: → 验证 webhook URL 是否可公开访问 → 检查 HMAC 签名验证逻辑 → 查看合作伙伴后台的 webhook 日志
如果 GraphQL 查询失败: → 针对 schema 验证查询(使用 GraphiQL 浏览器) → 在错误信息中检查是否有已弃用的字段 → 验证是否拥有必要的访问权限范围

Reference Files

参考文档

For detailed implementation guides, read these files:
  • references/app-development.md
    - OAuth authentication flow, GraphQL mutations for products/orders/billing, webhook handlers, billing API integration
  • references/extensions.md
    - Checkout UI components, Admin UI extensions, POS extensions, Shopify Functions for discounts/payment/delivery
  • references/themes.md
    - Liquid syntax reference, theme directory structure, sections and snippets, common patterns

如需详细的实现指南,请阅读以下文件:
  • references/app-development.md
    - OAuth 认证流程、商品/订单/计费的 GraphQL 变更、webhook 处理程序、计费 API 集成
  • references/extensions.md
    - 结账界面组件、后台界面扩展、POS 扩展、用于折扣/支付/配送的 Shopify Functions
  • references/themes.md
    - Liquid 语法参考、主题目录结构、区块和代码片段、常见模式

Scripts

脚本

  • scripts/shopify_init.py
    - Interactive project scaffolding. Run:
    python scripts/shopify_init.py
  • scripts/shopify_graphql.py
    - GraphQL utilities with query templates, pagination, rate limiting. Import:
    from shopify_graphql import ShopifyGraphQL

  • scripts/shopify_init.py
    - 交互式项目脚手架。运行:
    python scripts/shopify_init.py
  • scripts/shopify_graphql.py
    - GraphQL 工具类,包含查询模板、分页、速率限制。导入:
    from shopify_graphql import ShopifyGraphQL

Official Documentation Links

官方文档链接

API Version: 2026-01 (quarterly releases, 12-month deprecation window)
API 版本:2026-01(季度发布,12个月弃用周期)