用途
该技能用于解决 Shopify 商品图片替代文本(alt text)缺失或质量低下的问题。AI 购物智能体无法读取图片像素,只能依赖图片的 alt text 来理解商品外观,包括颜色、材质、风格和用途。空白或文件名式 alt text(例如“IMG_2931.jpg”)无法向智能体传达任何信息,导致智能体既无法将商品与视觉类查询(如“red linen midi dress”)匹配,也无法向购物者准确描述商品。该技能会找出缺失或低价值 alt text 的商品图片,并依据商品标题、选项、类型和标签,生成简洁、描述性的 alt text 写回 Shopify。它对应修复 agentiq.report 中的 listing-image-alt-text 发现项。
前提条件
- 已认证的 Shopify CLI 会话:
shopify auth login --store <domain> - 所需 API 权限范围:
read_products、write_products、write_files
参数
所有技能都接受以下通用参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| store | string | 是 | — | 商店域名(例如 mystore.myshopify.com) |
| format | string | 否 | human | 输出格式:human(默认)或 json |
| dry_run | bool | 否 | false | 预览变更但不实际执行 |
技能专属参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| collection_id | string | 否 | — | 限定到某个 collection 的 GID |
| tag | string | 否 | — | 限定到某个商品标签 |
| overwrite | bool | 否 | false | 为 true 时,还会重写文件名式/占位符 alt text;为 false 时仅填充空白项 |
| max_chars | int | 否 | 125 | alt text 长度上限(兼顾可访问性与智能体可读性) |
安全提示
⚠️ 第 3 步(fileUpdate)会将 alt text 写入线上媒体。当 overwrite: true 时会替换已有 alt text,且无法批量撤销。请先运行 dry_run: true 并逐张图片检查拟用的 alt text。默认设置(overwrite: false)只填充空白项,风险较低。
工作流程步骤
OPERATION: products — query
输入:first: 250,可选 collection/tag 过滤;字段包括 title、productType、tags、options、media{ MediaImage{ id image{ altText } } };持续分页直到取完。
预期输出:带当前 alt text 的商品媒体,以及生成优质 alt text 所需的商品上下文。
COMPUTE(无 API 调用):对每张 alt text 为空白(或在 overwrite 模式下为占位符)的图片,根据标题 + 相关选项值(颜色/材质/风格)+ 商品类型组合 alt text,并裁剪到 max_chars。输出预览表(image id → 拟用 alt)。
OPERATION: fileUpdate — mutation
输入:files: [{ id: <MediaImage id>, alt: <generated alt> }],分批提交(每批 ≤ 25 条)。
预期输出:更新后的文件;收集 userErrors。
GraphQL 操作
# products:query — validated against api_version 2025-01
query AltTextProducts($first: Int!, $after: String, $query: String) {
products(first: $first, after: $after, query: $query) {
edges {
node {
id
title
productType
tags
options { name values }
media(first: 20) {
edges {
node { ... on MediaImage { id image { altText url } } }
}
}
}
}
pageInfo { hasNextPage endCursor }
}
}
# fileUpdate:mutation — validated against api_version 2025-01
mutation AltTextUpdate($files: [FileUpdateInput!]!) {
fileUpdate(files: $files) {
files { ... on MediaImage { id alt } }
userErrors { field message code }
}
}
会话跟踪
Claude 必须在每个阶段输出以下内容,这是强制要求。
开始时输出:
╔══════════════════════════════════════════════╗
║ SKILL: <skill name> ║
║ 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
<Metric label>: <value>
Errors: 0
Output: <filename or "none">
══════════════════════════════════════════════
当 format: json 时,输出:
{
"skill": "<skill-slug>",
"store": "<domain>",
"started_at": "<ISO8601>",
"completed_at": "<ISO8601>",
"dry_run": false,
"steps": [
{
"step": 1,
"operation": "<OperationName>",
"type": "query",
"params_summary": "<string>",
"result_summary": "<string>",
"skipped": false
}
],
"outcome": {
"metric_key": 0,
"errors": 0,
"output_file": null
}
}
输出格式
human:更新图片数量 + 一份 CSV(product、image_id、old_alt、new_alt)。json:{ images_updated, images_skipped, errors, output_file }。
错误处理
| 错误 | 原因 | 恢复方式 |
|---|---|---|
| THROTTLED | API 速率限制 | 等待 2 秒,最多重试 3 次 |
| userErrors 非空 | 文件 id 无效 / 不是 MediaImage | 记录消息,跳过,继续执行 |
| Alt 超出限制 | 生成文本过长 | 在单词边界处裁剪到 max_chars |
最佳实践
- alt text 应以具体名词 + 区分性属性开头(如“Charcoal merino crew-neck sweater”),而非营销套话——这才是智能体用于匹配的内容。
- 首轮保持
overwrite: false,安全地修复最严重的缺口(空白项);之后再经过人工审核执行一次overwrite: true,处理文件名式 alt text。 - 不要堆砌关键词——一句准确的话胜过逗号堆叠的表述,对屏幕阅读器用户也更友好。
- 之后可重新运行
shopify-admin-agentic-readiness-audit,确认 alt-text 覆盖率这一维度的改善。