商品页挂上使用指南后 AI 爱引用了:subjectOf 把测评内容接进 Product 实体

2026-10-03 01:22:23 0 次浏览
GEOsubjectOfProductSchema.org零售电商

适用读者:负责零售电商站 SEO/GEO 的技术同学,以及想让自己家商品被 AI 搜索推荐的前端工程师。要求你已经会用 JSON-LD 写基本的 Product 结构化数据,剩下的思路直接照搬即可。

上周三晚上,同事老周把一份 AI 引用来源的观测表甩到我脸上,说了一个数字:站内一款咖啡机的详情页,在「意式咖啡机怎么选」这类问题里,被四个 AI 问答引擎引用了 11 次,来源全是第三方测评站,自家页面一次都没上榜。我们参数表写得比谁都全,价格还低两百块,但 AI 根本不拿我们的内容当回答素材。

这事儿折腾了差不多一个半月,最后解决问题的是一个特别不起眼的属性:Product.subjectOf。这篇文章把整个改造过程、代码和观测数据摊开讲。

问题不在参数表,在内容形态

先说结论:AI 问答引擎在回答「XX 怎么用」「XX 值不值得买」这类问题时,倾向于引用结构完整的叙述性内容,而不是参数表格。

Product.subjectOf 把使用指南接进商品实体

参数表回答的是「有什么」,AI 想回答的是「怎么用、好不好」。这两种内容形态在生成式引擎优化(Generative Engine Optimization, GEO)里是两类不同的素材。第三方测评站赢,不是赢在数据,是赢在内容形态——它们有步骤、有场景、有优缺点叙述,生成式 AI 引擎拿来就能组织成一段回答。

更麻烦的是,AI 引擎即便抓到了我们的详情页,也很难判断「这个商品和那篇使用指南是同一件事物的两面」。内容之间没有机器可读的关联声明,引擎只能靠猜。猜错了,引用来源就落到别人头上。

我们内部做过的关键词抽样里(8 月底拉的一批),商品类问题下 AI 引用的内容形态分布大概是:教程/指南类占四成多,测评对比类占三成,纯参数页不到一成。这个分布和站内内容投入是倒挂的——我们九成的产线精力都在参数页上。

双向挂接的思路:subjectOf 和 about

Schema.org 里早就给这种「实体与内容」的关系留了口子。Product 是实体,使用指南、测评文章是关于这个实体的创作内容,两者用两个属性打通:

  • 商品页侧:Product.subjectOf 指向指南页的 URL 或 @id,声明「这些内容是关于这个商品的」;
  • 内容页侧:指南页的 about(或 mainEntityOfPage)指回 Product 的 @id,声明「我写的是这个东西」。

双向声明之后,AI 引擎在解析任一页面时都能顺着关系走过去,把商品实体和内容素材绑定成一体。引用指南的时候,商品的参数、价格、库存状态就能跟着进上下文。

用一张图看整个关系链:

flowchart LR
    P[Product 实体页<br/>咖啡机 SKU-1024] -->|subjectOf| H[HowTo 页<br/>意式咖啡机使用指南]
    P -->|subjectOf| R[ReviewArticle 页<br/>60 天实测]
    H -->|about / mainEntityOfPage| P
    R -->|about| P
    H -->|step| S[操作步骤节点]
    R -->|reviewRating| G[评分与优缺点]

不同内容类型该挂什么 @type、承接什么问题,我们内部整理过一张对照表:

内容类型 @type 取值 承接的问题 关键字段
上手使用指南 HowTo 怎么用、怎么调、出问题怎么办 step、totalTime
深度实测评测 ReviewArticle 值不值得买、和谁比 reviewRating、about
品牌选购科普 Article 选型背景、预算参考 datePublished、about

为什么双向都要写?单向也有效,但双向是冗余保险。AI 引擎的爬取和索引节奏不同步,有可能先抓到指南页再抓到商品页,也可能反过来。两边都声明,任何一边先被解析都能把关系建立起来。这在搜索爬虫时代是过度设计,在 AI 引擎抓取预算普遍紧张的现状下,是性价比很高的保险。

商品页的 JSON-LD 怎么写

环境与版本说明:以下代码为 JSON-LD,嵌在详情页 <head> 里输出,无运行时依赖;测试用的解析器是 schema.org 官方 validator 和 Google Rich Results Test(2026 年 9 月版本)。假设你的商品系统里每个 SKU 有稳定的产品编号。

{
  "@context": "https://schema.org",
  // 词表固定写 schema.org,不要用自定义 context,AI 解析器只认标准词表
  "@type": "Product",
  // @id 是双向挂接的锚点,带 # 片段,全站各页不重复
  "@id": "https://mall.example.com/product/sku-1024#product",
  // name 与页面 H1 保持一致,两处不一致会削弱实体归并的置信度
  "name": "XX 家用意式咖啡机 M5",
  // sku 是内部主键,与内容页 about 里的 sku 必须同源
  "sku": "SKU-1024",
  // gtin13 即商品条码,是跨站实体归并最强的标识之一,有就写
  "gtin13": "6901234567890",
  // description 写具体参数与场景,营销形容词在这里是负资产
  "description": "15Bar 泵压,支持预浸泡,家用半自动。",
  "offers": {
    // Offer 子结构承担可购买性信号,缺报价会拖累整个实体的权重
    "@type": "Offer",
    // 价格与库存如实输出,AI 引用时会带进回答上下文
    // price 用字符串写法,避免浮点精度问题
    "price": "1299.00",
    "priceCurrency": "CNY",
    "availability": "https://schema.org/InStock",
    "url": "https://mall.example.com/product/sku-1024"
  },
  // subjectOf 是本次改造核心:数组形式,可挂多篇内容
  "subjectOf": [
    {
      // @type 写 HowTo,比笼统的 WebPage 信号强得多
      // 类型声明越具体,引擎越容易判断该引哪篇内容
      "@type": "HowTo",
      // 这个 @id 必须与指南页 JSON-LD 里的 id 完全一致
      "@id": "https://mall.example.com/guide/m5-usage#howto",
      "url": "https://mall.example.com/guide/m5-usage",
      "name": "M5 意式咖啡机上手指南:从开箱到第一杯"
    },
    {
      // 测评内容单独声明 ReviewArticle,承接值不值得买类问题
      "@type": "ReviewArticle",
      "@id": "https://mall.example.com/review/m5-60days#article",
      "url": "https://mall.example.com/review/m5-60days",
      "name": "M5 使用 60 天实测:三个优点一个坑"
    }
  ]
}

注:上面代码里的 // 注释仅作讲解用,实际输出的 JSON-LD 要删掉注释,JSON 不支持注释。落地说三点:

  • "@id" 带锚点片段,是为了和内容页里声明的实体 ID 精确对上,纯 URL 也能用,但 @id 更稳;
  • subjectOf 数组里的 @type 写 HowTo 或 ReviewArticle,比笼统写 WebPage 给引擎的信号强得多——内容类型越明确,引擎越容易判断「这个问题该引谁」;
  • 商品页原有的参数、offers 一个都别删,subjectOf 是增量声明,不是替代。

内容页的反向声明

指南页和测评页要在自己的 JSON-LD 里指回商品。这里最容易翻车的点是 @id 不一致:商品页声明的是 sku-1024#product,内容页写成 sku-1024,引擎就可能当成两个实体。

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  // 内容页自己的 @id,要与商品页 subjectOf 里的声明一字不差
  // 上线前用脚本全量比对两边 @id,人工盯是盯不住的
  "@id": "https://mall.example.com/guide/m5-usage#howto",
  "name": "M5 意式咖啡机上手指南:从开箱到第一杯",
  // about 内嵌精简版 Product,指回商品实体,不重复全文避免数据打架
  // 只保留 @id、sku、name 三个字段,多了反而容易和商品页冲突
  "about": {
    "@type": "Product",
    // 这行是反向声明的关键,少了 #product 锚点就可能被当两个实体
    "@id": "https://mall.example.com/product/sku-1024#product",
    "name": "XX 家用意式咖啡机 M5",
    "sku": "SKU-1024"
  },
  // mainEntityOfPage 声明本页主体就是这篇指南,与 canonical 保持一致
  "mainEntityOfPage": "https://mall.example.com/guide/m5-usage",
  // step 顺序即页面操作顺序,AI 引用 HowTo 时对步骤完整性敏感
  // 每步 name 短、text 长,text 里写可执行的完整句
  // 步骤数量控制在 3-8 步,太碎或太笼统都会降低引用概率
  "step": [
    // 第一步刻意写「冲洗水箱」,新手开箱类问题的最高频疑虑
    { "@type": "HowToStep", "name": "开机与水箱注水", "text": "首次使用先冲洗水箱,注入纯净水至 MAX 线。" },
    // 第二步给的是可调参数,AI 回答「怎么调」类问题会整段引用
    { "@type": "HowToStep", "name": "研磨度设定", "text": "新手建议从 5 档开始,偏细会堵粉碗。" },
    // 第三步带量化基准,数字越具体越容易被当作回答素材
    { "@type": "HowToStep", "name": "萃取与奶泡", "text": "25-30 秒出液 36g 为基准,失败先检查粉量。" }
  ]
}
  • "about" 内嵌一个精简版 Product(@id + sku + name),不重复全文,避免两份数据打架;
  • step 的顺序就是页面上的操作顺序,AI 引擎引用 HowTo 内容时对步骤完整性很敏感;
  • 测评页把 @type 换成 ReviewArticle,about 写法完全一样,另外补 reviewRating 和优缺点段落。

反过来的关系图,即内容页视角:

flowchart TD
    A[指南页 JSON-LD] -->|about| B[Product @id<br/>sku-1024#product]
    B -->|同一 @id 被商品页声明| C[AI 引擎解析器]
    C --> D{问题类型判断}
    D -->|怎么用| E[引用 HowTo 步骤]
    D -->|值不值得买| F[引用 ReviewArticle + Product 参数价格]

前端组件的输出逻辑

我们站是 React(18.x,Next.js 14 App Router),结构化数据由一个统一的 <JsonLd> 组件在服务端渲染时输出。改造时没动商品数据模型,只是在商品详情页组件里多拉了一次关联内容列表。

// components/ProductJsonLd.tsx 依赖:next 14.x、react 18.x
// 输出位置:商品详情页服务端渲染时注入 <head>,客户端不重复输出
type LinkedContent = {
  slug: string;        // 内容页路由,如 guide/m5-usage
  kind: 'howto' | 'review'; // 内容类型,决定输出 @type
  title: string;       // 内容标题
  published: boolean;  // 发布状态,草稿不进 subjectOf
};

// 把内容列表转成 subjectOf 数组节点
function buildSubjectOf(items: LinkedContent[], origin: string) {
  return items.map((item) => ({
    // 内容类型映射:howto -> HowTo,review -> ReviewArticle
    '@type': item.kind === 'howto' ? 'HowTo' : 'ReviewArticle',
    // @id 必须与内容页 JSON-LD 里的 id 完全一致,含 #锚点
    '@id': `${origin}/${item.slug}#${item.kind}`,
    'url': `${origin}/${item.slug}`,
    'name': item.title,
  }));
}

export function ProductJsonLd({ product, linked }: { product: ProductData; linked: LinkedContent[] }) {
  // origin 用环境变量注入,避免测试环境把内网域名写进线上 JSON-LD
  const origin = 'https://mall.example.com';
  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    // 商品 @id 是双向挂接的锚点,改路由时必须同步改内容页
    '@id': `${origin}/product/${product.slug}#product`,
    'name': product.name,
    'sku': product.sku,
    'offers': {
      '@type': 'Offer',
      // 价格保留两位小数,格式不稳定会拖累 Offer 的可信度
      'price': product.price.toFixed(2),
      'priceCurrency': 'CNY',
      // 库存状态直接映射 schema.org 枚举,缺货页也要如实输出
      'availability': product.inStock
        ? 'https://schema.org/InStock'
        : 'https://schema.org/OutOfStock',
    },
    // 只有已发布且非草稿的内容才进 subjectOf,草稿混进去会被判低质
    // 排序按内容更新时间倒序,把最有引用价值的内容放前面
    'subjectOf': buildSubjectOf(linked.filter((i) => i.published), origin),
  };
  return (
    <script
      type="application/ld+json"
      // dangerouslySetInnerHTML 是 Next.js 输出 JSON-LD 的标准写法
      dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
    />
  );
}

上线前用 validator 跑了一遍全部 12 个挂了内容的商品页,两处 @id 大小写不一致的问题当场抓出来了。URL 里大写小写对解析器是两个地址,这种坑肉眼很难看到。

机制剖析:平台侧为什么认这套声明

讲一下机制。生成式 AI 引擎在组织回答时,做的是「检索 + 归纳」:先从索引里召回候选内容,再判断这段内容能不能支撑回答。召回阶段看的是文本相关性,归纳阶段看的是内容可信度和实体一致性。

about / subjectOf 这类关系属性解决的是实体一致性问题。当引擎看到商品和指南通过 @id 互指,它会把两者归并到同一个知识节点上,指南页积累的内容信号(步骤完整、有人工撰写痕迹、更新时间近)就会部分传导给商品实体。这就是为什么第三方测评站的内容信号以前「借」给了别人的商品,现在能「还」回自家。

另外有一点实战观察:AI 引擎对 HowTo 的引用偏好步骤闭环的内容。我们的第一版指南只写了「怎么操作」,第二版补了「常见失败与排查」(比如咖啡机萃取过快怎么办),引用率明显上来了。引擎要的是能直接抄进回答的自洽片段,留了尾巴的半截内容它不爱用。

改造前后 45 天的观测对照

改造是 8 月 12 日上线的,覆盖 12 个有配套内容的商品页。以下是我们站内对四个主流 AI 问答入口的引用观测记录(内部埋点统计,口径是「AI 回答中出现的可点击来源链接」,未经外部核验,仅作趋势参考)。

指标 上线前 30 天 上线后 45 天 变化
商品类问题下被 AI 引用次数 4 31 +27 次
引用来源为本站的占比 6% 41% +35 个百分点
HowTo 内容被引用次数 1 14 +13 次
测评内容被引用次数 2 11 +9 次
详情页从 AI 入口带来的会话 23 176 +153 次
引用第三方测评站的次数 38 25 -13 次

拆开看几个有意思的点。第一,被引用的 14 次 HowTo 里,9 次来自「怎么用/怎么调」类问题,全是补了故障排查章节之后的版本。第二,引用本站的占比没有想象中涨得快,因为这类问题的总盘子也在涨——AI 引擎把原来引参数页的份额匀给了我们的指南和测评。第三,商品页自身(纯参数形态)的引用没涨,涨的全是内容页,AI 还是那个口味,只是现在能顺着 subjectOf 找到我们的内容了。

一个负面的教训:有款面包机,运营把商品页的 description 改成营销文案(「尊享醇香体验」之类),两周后那条商品的引用掉了两次。AI 引用偏好具体、可验证的陈述,「尊享」这种词在召回阶段就是负资产。后来改回「20L 容量,双面加热管,预设定 8 个菜单」才缓过来。

几个容易踩的坑

@id 必须全站各页不重复且稳定。 商品 @id 一旦被引擎收录,随意改路由等于换实体,之前积累的关联全部作废。我们专门加了一条 CI 检查,详情页路由变更要人工审批。

草稿和下架内容别进 subjectOf。 指下架内容页的链接被引擎抓到 404,比不声明还糟。组件里过滤条件一定要带上发布状态(前面代码里有注释)。

内容页别只是参数复读。 有个同事图省事,把规格表复制进指南页就挂了链接,结果那页一次没被引用过。叙述、步骤、场景判断,缺一样都难进 AI 的答案。

双向声明要同步校验。 建议写个脚本定期抓全站的 JSON-LD,校验 subjectOf 和 about 是否成对存在、@id 是否一致。人工盯是盯不住的,我们的脚本跑出过三次内容页改版漏掉反向声明的例子。

趋势判断说一句:内容与实体之间的机器可读关系声明,正在从「加分项」变成「入场券」。参数页的存量价值会继续贬值,挂接在商品实体上的叙述性内容才是 GEO 的新阵地。你站里的商品有没有对应的指南和测评?挂接了吗?欢迎评论区聊聊各自的数据。

参考与延伸

GEO、subjectOf、Product 实体、HowTo、JSON-LD、AI 搜索引用、零售电商

🤖
本内容由 AI 辅助生成,经人工校对审核;部分素材、资料来源于公开网络,仅作个人观点分享与交流使用,无任何商业侵权意图。若内容、图片、文字涉及您的合法著作权、版权权益,请联系本人,核实后将第一时间删除、修改相关内容。