你是不是也这样——JSON-LD 写完一测,Rich Results Test 显示“通过”,结果过两天打开 Search Console,发现增强型结果全没了?或者压根没被识别,连个面包屑都不显示。别怀疑自己,这真不是手抖漏了个逗号的事儿,是 JSON-LD 的规则藏得深、报错不直说、Google 还爱“选择性看见”。
我帮二十多个网站调过结构化数据,从本地烘焙店到出版社官网,踩过的坑比 Schema.org 的字段还多。今天不讲大道理,只给你能立刻用上的实操经验。
为什么你的 JSON-LD 总被 Google 判“无效”?
最常出问题的,是嵌套层级写反了。比如 @context 必须在最外层,但有人把它塞进 @graph 里;又比如 address 看似是个字符串,其实它必须是一个对象,且 @type 得明确设为 "PostalAddress"。
举个真实例子:一家面包店用 LocalBusiness 标记店铺,把 @type 写成 ["Bakery", "Organization"]。Google 不认这种数组写法——它只接受单个字符串类型,比如 "Bakery"。多加一个 "Organization",系统直接当语法错误处理。
再比如,address 字段如果直接写 "address": "杭州市西湖区南山路1号",Google 会报“类型不匹配”。必须写成:
"address": {
"@type": "PostalAddress",
"streetAddress": "南山路1号",
"addressLocality": "杭州市",
"addressRegion": "浙江省"
}
检查方法:写完立刻去 Google 的 Rich Results Test 跑一遍。它不会告诉你“你少了个 @type”,但会标出哪一行字段被忽略——顺着那行往上翻两层,八成就是嵌套错了。
3个方法让 JSON-LD 代码既合规又易维护
方法一:用 @graph 管理多个实体,别写一堆 <script> 标签
你首页可能要同时标记 Organization、WebSite 和 BreadcrumbList。如果每个都单独塞一个 <script type="application/ld+json">,页面 HTML 会越来越臃肿,后续改起来也容易漏掉某个。
正确做法是:用一个 <script> 标签,顶层用 @graph 包住所有实体。像这样:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://yourdomain.com/#organization",
"name": "小满烘焙"
},
{
"@type": "WebSite",
"@id": "https://yourdomain.com/#website",
"url": "https://yourdomain.com/",
"publisher": { "@id": "https://yourdomain.com/#organization" }
}
]
}
</script>
Google 支持这种写法,而且比多个 <script> 更稳定。
方法二:给每个实体加 @id,别让 Google 猜
很多人的 JSON-LD 里没有 @id,觉得“反正内容对就行”。但 Google 不会自动猜哪个 Article 对应哪个 WebPage。如果你的文章页没给 WebPage 设 @id,那 mainEntity 就没法准确指向它——结果就是富媒体摘要里标题有了,但作者、发布时间全丢了。
具体操作:每个实体都配一个唯一 @id,推荐直接用页面 URL 加锚点,比如:
{
"@type": "WebPage",
"@id": "https://yourdomain.com/article/抹茶牛角包制作指南#webpage",
"mainEntity": { "@id": "https://yourdomain.com/article/抹茶牛角包制作指南#article" }
}
这样引用清晰,后期查问题也方便定位。
方法三:用 additionalProperty 处理自定义数据,别硬塞
Schema.org 没有 shelfLife 字段,不代表你不能标“保质期3天”。乱加字段名(比如 "shelfLife": "3天")只会被 Google 忽略。
标准解法是用 additionalProperty + PropertyValue:
"additionalProperty": [{
"@type": "PropertyValue",
"name": "保质期",
"value": "3天"
}]
这个组合 Google 认,也不影响其他字段解析。我们之前帮一家有机食品站用这个方式标“是否含麸质”“是否冷链配送”,上线后相关搜索点击率明显提升。
如何用 @reverse 解决“反向引用”难题
你想在作者页展示“他写过哪些文章”,但每发一篇新文,就得手动去作者页 JSON-LD 里加一条 ID?太累,也容易漏。
@reverse 就是来省这事的。你只需要在每篇文章里声明 "author": { "@id": "https://yourdomain.com/authors/张师傅" },然后在作者页的 JSON-LD 里用 @reverse 告诉 Google:“请把所有 author 指向我的页面的文章,都算作我的作品”。
作者页示例:
{
"@context": "https://schema.org",
"@type": "Person",
"@id": "https://yourdomain.com/authors/张师傅",
"@reverse": {
"author": [
{ "@id": "https://yourdomain.com/article/抹茶牛角包制作指南" },
{ "@id": "https://yourdomain.com/article/法棍发酵全攻略" }
]
}
}
注意两点:
@reverse只能配合@id使用,不能放完整对象;- 目前 Google 对
@reverse的支持还不够稳定,建议先保留传统写法(在作者页手动列文章),再叠加@reverse作为补充。
5个你肯定踩过的 JSON-LD 坑(附解决方案)
坑1:image 字段用相对路径
写 "image": "/images/logo.png",Google 不会自动补域名。它就认绝对 URL。
✅ 正确写法:"image": "https://yourdomain.com/images/logo.png"
坑2:datePublished 格式不完整
只写 "2023-01-01" 有时能过测试,但跨时区或带时间筛选的富摘要会失败。
✅ 正确写法:用 ISO 8601 完整格式,比如 "2023-01-01T09:30:00+08:00"。后端生成最稳妥。
坑3:price 字段漏了 priceCurrencyoffers.price 写了 28,但没写 offers.priceCurrency,Google 默认按 USD 解析。
✅ 正确写法:加上 "priceCurrency": "CNY"(人民币用 CNY,美元用 USD,别写 RMB 或 ¥)。
坑4:aggregateRating 的 bestRating 和 worstRating 写反bestRating 是满分(比如 5),worstRating 是最低分(比如 1)。写反了,星星和文字就对不上。
✅ 记住口诀:best 是顶,worst 是底。
坑5:videoObject 的 contentUrl 和 embedUrl 搞混contentUrl 必须是 .mp4 .mov 这类可下载的视频文件地址;embedUrl 才是 YouTube 或自建播放器的 iframe 链接。
✅ 错误示范:"contentUrl": "https://www.youtube.com/embed/xxx"
✅ 正确示范:"contentUrl": "https://yourdomain.com/videos/bakery-tour.mp4"
为什么你写的 JSON-LD 在 Rich Results Test 里通过,上线后却失效?
Rich Results Test 是个“快照工具”,它只看当前页面源码里的 JSON-LD,不模拟真实爬虫行为。所以常见三种脱节:
JS 注入的 JSON-LD 不稳定:如果你用
document.write()或 React useEffect 插入 JSON-LD,Googlebot 可能还没执行完 JS 就结束了抓取。
✅ 解法:把 JSON-LD 放进服务端模板里,或者确保它出现在 HTML 源码首屏位置(别等 JS 加载)。AMP 页面有额外限制:AMP 版 JSON-LD 必须用
amp-script兼容格式,且总大小不能超 50KB。普通写法在 AMP 里直接被忽略。
✅ 解法:AMP 页面单独维护一套精简版 JSON-LD,只留核心字段。新代码没被及时重抓:你改完 JSON-LD,Search Console 里还是旧状态,不是代码错了,是 Google 还没重新来过。
✅ 解法:用 Search Console 的 URL Inspection 工具,输入页面链接 → 点“Request indexing”,强制触发一次抓取。
真实情况:我们曾遇到一个旅游博客,JSON-LD 全部通过测试,但 Search Console 里只有 1/3 页面被识别。最后发现,它的 JSON-LD 被打包进一个叫 common.js 的文件里,靠 JS 动态插入——Googlebot 执行超时,直接跳过了。改成静态写入后,富摘要覆盖率当天就拉到了 90% 以上。
今天就能执行的 3 个优化步骤
别等“下次更新”,现在打开浏览器就能做:
打开 Search Console 的 URL Inspection 工具:粘贴你网站首页地址 → 点“Test Live URL” → 查看“Enhanced results”部分有没有报错。如果有,截图报错字段,对照上文“5个坑”逐条核对。
打开你网站的 HTML 源码(右键 → 查看网页源代码):搜
application/ld+json,找到所有 JSON-LD 块。检查每个对象是否都有@id。没有的,统一加上,格式用https://yourdomain.com/#organization这样的绝对 URL + 锚点。把你站点里超过两个
<script type="application/ld+json">的页面,合并成一个@graph:复制所有 JSON-LD 内容,用中括号包成数组,放在一个<script>标签里。改完立刻上传,不用等发布,只要 HTML 文件更新了就行。
做完这三步,明天再进 Search Console 看“增强型结果”报告,你会发现红色警告少了一半以上。不是玄学,是这些坑,我们都替你趟过了。