结构化数据(JSON-LD)实战:让搜索引擎真正读懂你的文章

用 JSON-LD 把文章语义喂给搜索引擎,手把手实现 Article、BreadcrumbList 与 WebSite 三层结构化数据,附 Go 模板代码与验证工具。

搜索引擎能抓取你的页面,但它不一定读懂了。HTML 是给浏览器渲染的,它告诉引擎"这有段文字",却无法区分这段文字是文章标题、作者姓名还是价格。结构化数据(Structured Data)填补这个缺口:它用机器友好的格式,把"这是一篇技术文章、作者是张三、发布于 2026-06-15"明确传达给爬虫。

Google、Bing 和其他主流引擎都支持 Schema.org 词汇表,而 JSON-LD(JSON for Linked Data)是注入这套词汇最干净的方式。

为什么选 JSON-LD 而不是 Microdata / RDFa

三种格式都能表达结构化数据,但 JSON-LD 的工程优势明显:

  • 与 HTML 解耦:以 <script type="application/ld+json"> 独立注入,不需要改动任何现有标签。
  • 模板友好:服务端渲染时只需在 <head> 里输出一段 JSON,逻辑集中。
  • 可读性强:JSON 而非属性散落在 DOM 里,审查、调试都方便。
  • Google 官方推荐文档里明确标注 JSON-LD 为首选格式。

最小可用:Article 类型

对于技术博客,最常用的是 Article(或子类 TechArticle)。最小有效负载如下:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "结构化数据(JSON-LD)实战:让搜索引擎真正读懂你的文章",
  "datePublished": "2026-06-15T08:00:00+08:00",
  "dateModified": "2026-06-15T08:00:00+08:00",
  "author": {
    "@type": "Person",
    "name": "CCVAR"
  }
}
</script>

这已经够 Google 识别文章发布日期,让它在搜索结果里正确显示时效性标签。

逐步增强:完整的文章 Schema

完整版补上图片、摘要、出版者,以及让 Google 的"丰富结果"(Rich Results)能够展示:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "headline": "结构化数据(JSON-LD)实战:让搜索引擎真正读懂你的文章",
  "description": "用 JSON-LD 把文章语义喂给搜索引擎,手把手实现 Article、BreadcrumbList 与 Site 三层结构化数据。",
  "image": "https://ccvar.com/assets/og/json-ld-seo.png",
  "datePublished": "2026-06-15T08:00:00+08:00",
  "dateModified": "2026-06-15T08:00:00+08:00",
  "author": {
    "@type": "Person",
    "name": "CCVAR",
    "url": "https://ccvar.com"
  },
  "publisher": {
    "@type": "Organization",
    "name": "CCVAR 简记",
    "logo": {
      "@type": "ImageObject",
      "url": "https://ccvar.com/assets/logo.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://ccvar.com/zh/posts/json-ld-structured-data-seo"
  }
}
</script>

mainEntityOfPage 是关键:它用 @id 把这段结构化数据锚定到具体 URL,帮引擎建立"这段 JSON 描述的正是当前页面"的关联。

面包屑导航(BreadcrumbList)

面包屑是最容易被忽视却立竿见影的类型。它直接影响搜索结果的 URL 展示方式——Google 会把面包屑替换默认的 URL 显示,让条目更易理解。

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "首页",
      "item": "https://ccvar.com"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "文章",
      "item": "https://ccvar.com/zh/posts"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "结构化数据(JSON-LD)实战",
      "item": "https://ccvar.com/zh/posts/json-ld-structured-data-seo"
    }
  ]
}
</script>

一个页面可以放多个 <script type="application/ld+json"> 块,引擎会各自解析,互不干扰。

站点级:WebSite 与 SearchAction

在首页放置 WebSite 类型,可以让 Google 在搜索结果里展示站内搜索框(Sitelinks Searchbox):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "CCVAR 简记",
  "url": "https://ccvar.com",
  "potentialAction": {
    "@type": "SearchAction",
    "target": {
      "@type": "EntryPoint",
      "urlTemplate": "https://ccvar.com/search?q={search_term_string}"
    },
    "query-input": "required name=search_term_string"
  }
}
</script>

注意 potentialAction 只在首页放一次即可,文章页不需要重复。

用 Go 的服务端模板生成 JSON-LD

如果站点用 Go 驱动,可以直接在模板里构造结构化数据,避免手拼 JSON:

// schema.go
package schema

import (
    "encoding/json"
    "html/template"
    "time"
)

type Article struct {
    Context       string    `json:"@context"`
    Type          string    `json:"@type"`
    Headline      string    `json:"headline"`
    Description   string    `json:"description"`
    Image         string    `json:"image,omitempty"`
    DatePublished time.Time `json:"datePublished"`
    DateModified  time.Time `json:"dateModified"`
    Author        Person    `json:"author"`
    Publisher     Org       `json:"publisher"`
    MainEntityURL string    `json:"mainEntityOfPage,omitempty"`
}

type Person struct {
    Type string `json:"@type"`
    Name string `json:"name"`
    URL  string `json:"url,omitempty"`
}

type Org struct {
    Type string `json:"@type"`
    Name string `json:"name"`
    Logo Logo   `json:"logo"`
}

type Logo struct {
    Type string `json:"@type"`
    URL  string `json:"url"`
}

// ArticleLD 返回可直接嵌入模板的 JSON 字符串
func ArticleLD(post Post, siteURL string) (template.HTML, error) {
    a := Article{
        Context:       "https://schema.org",
        Type:          "TechArticle",
        Headline:      post.Title,
        Description:   post.Excerpt,
        Image:         post.OGImage,
        DatePublished: post.PublishedAt,
        DateModified:  post.UpdatedAt,
        Author:        Person{Type: "Person", Name: post.AuthorName, URL: siteURL},
        Publisher: Org{
            Type: "Organization",
            Name: "CCVAR 简记",
            Logo: Logo{Type: "ImageObject", URL: siteURL + "/assets/logo.png"},
        },
        MainEntityURL: siteURL + post.URL,
    }
    b, err := json.Marshal(a)
    if err != nil {
        return "", err
    }
    return template.HTML(string(b)), nil
}

在 Go 模板里调用:

{{- $ld := articleLD .Post .SiteURL -}}
<script type="application/ld+json">{{ $ld }}</script>

template.HTML 告诉 Go 模板引擎不要转义这段内容,JSON 里的 " 会被正确输出而不是变成 &#34;

验证:Rich Results Test

写完后必须验证,不然很可能字段缺失或类型写错而不自知:

  1. 打开 Rich Results Test
  2. 输入页面 URL(或直接粘贴 HTML 代码片段)
  3. 检查每个类型是否被识别,查看警告和错误

常见问题:

  • datePublished 格式错误(必须是 ISO 8601,如 2026-06-15T08:00:00+08:00,不能只写日期)
  • image 尺寸不足(Article 要求至少 1200×630px)
  • headline 超过 110 字符(AMP 场景下 Google 会截断并给出警告)

另一个工具是 Schema Markup Validator,它基于 Schema.org 规范而非 Google 子集,覆盖面更广。

什么不值得做

结构化数据不是 SEO 银弹,有几点不要迷信:

  • 不能直接提升排名:Google 明确声明结构化数据不是排名信号,它影响的是展示方式(Rich Results),不是位置。
  • 不要标注页面上没有的内容:比如给没有作者信息的页面强行加 author,这违反 Google 的垃圾内容政策,可能导致手动处置。
  • 不要重复冗余字段descriptionmeta description 内容相同没问题,但别试图塞进所有 Schema 字段——只填你真正拥有的数据。

核心原则:结构化数据的价值在于准确描述页面内容,而非堆砌字段刷存在感。引擎足够聪明,会识别不一致和虚假标注。

小结

JSON-LD 的工程成本极低——本质上就是在 <head> 里多一段 JSON——但它能让搜索引擎更精准地理解你的页面,并在合适场景下展示富结果。对于内容站来说,TechArticle + BreadcrumbList + 首页 WebSite 这三层基本覆盖了所有高价值场景,用服务端模板统一生成,维护成本接近零。