Article Schema 缺少必填字段 author.name

Search Console 在几百个 Article 页面上提示 "Missing field author.name"。byline 字符串明明在那,但 JSON-LD 形状不对 —— 富结果悄悄消失。

Search Console → Enhancements → Articles 开始在几篇文章上提示 “Missing field ‘author.name’“。几天后变成 200 篇。一周后你的文章 SERP 里的署名片段不再出现。让人沮丧的是:你确实有作者啊 —— 标题正下方就写着 “By Jane Lee”。打开 JSON-LD 一看就懂 Google 为什么不满意 —— author 字段要么是个裸字符串,要么是缺少内层 name 属性的对象。Google 的 Article schema 很挑:author 必须是结构化对象,至少要带 @typename。哪怕给一个普通字符串看起来人能读懂,验证也过不去。

常见原因

按生产模板里的命中频次排序。

1. author 是字符串,不是对象

模板写 "author": "Jane Lee"。Schema.org 在很多字段上接受字符串,但 Google 在 Article 富结果上明确要求 authorPersonOrganization 对象。

怎么判断:view-source 看 JSON-LD。"author" 是带引号的字符串就是这个 bug。

2. 数据字段为空,author 变成 { "name": null }

CMS 的 author 字段有时为 null。生成器输出 { "@type": "Person", "name": null }。Google 把这解读为”字段存在但为空”。

怎么判断:一部分文章 author 对象合法,另一部分 name 位置是 null 或空字符串。

3. author 对象有 givenName / familyName 但没 name

生成器把姓名规整地拆分,却从不输出合并的 name 字段。Schema.org 允许拆分形式,但 Google 的 Article 富结果明确要 name

怎么判断:JSON-LD 里有 "givenName": "Jane", "familyName": "Lee",没有 "name"

4. author 是字符串数组而不是对象数组

多作者文章输出 "author": ["Jane Lee", "Sam Park"]。数组形状对,每个元素也得是对象。

怎么判断:view-source 看合著文章,检查数组内容。

5. author 嵌错了父级

生成器把 author 塞进 publishermainEntityOfPage,而不是放在 Article 根级。

怎么判断:在 JSON-LD 里搜 "author",确认它的父键是顶层 Article 对象。

6. CMS 迁移丢了结构化 author 数据

迁移之后新系统只存文本作者。schema 生成器 fallback 到团队 byline 或 “Editorial Team” 这样的字符串。

怎么判断:最近的文章都共享同一个通用 author 字符串;老文章作者各不相同。

开始前

  • 从 Search Console → Enhancements → Articles → “Missing field ‘author.name’” 拉受影响 URL 列表。存档 —— 清理进度要拿它来衡量。
  • 找到输出 JSON-LD 的模板或生成器。
  • 决定数据模型:你有真正的作者表,还是只有自由文本?
  • 确认 author 应该是 Person(典型)还是 Organization(编辑团队署名内容)。

需要收集的信息

  • 5-10 个受影响页面的原始 HTML,重点看 JSON-LD 块。
  • 构造 author 的模板代码。
  • CMS / 数据来源:结构化作者记录,还是自由文本字符串。
  • 站点是否同时有 Article 和 BlogPosting 两种类型,还是只用一种。
  • 典型作者的样本数据(单作者、合著、匿名编辑)。

一步步修

按代价从小到大。

第 1 步:用 Rich Results Test 确认形状

把任一受影响 URL 丢进 Google Rich Results Test。错误信息会引用具体字段路径:author[0].name is missingauthor is a string, expected object。这告诉你 bug 是哪种变体。

第 2 步:修 schema 生成器

最小合法形态:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to bake sourdough",
  "datePublished": "2026-05-10",
  "author": {
    "@type": "Person",
    "name": "Jane Lee"
  }
}

模板代码:

function authorBlock(article) {
  if (!article.author?.name) {
    // No reliable author — omit the field entirely rather than fake it
    return undefined;
  }
  return {
    "@type": "Person",
    "name": article.author.name,
    ...(article.author.url && { url: article.author.url }),
  };
}

const jsonLd = {
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": article.title,
  "datePublished": article.publishedAt,
  ...(authorBlock(article) && { author: authorBlock(article) }),
};

第 3 步:合著文章按规矩来

每位作者一个独立对象:

"author": [
  { "@type": "Person", "name": "Jane Lee", "url": "https://example.com/team/jane" },
  { "@type": "Person", "name": "Sam Park", "url": "https://example.com/team/sam" }
]

代码:

const authorArr = article.authors
  .filter(a => a?.name)
  .map(a => ({ "@type": "Person", "name": a.name, ...(a.url && { url: a.url }) }));

if (authorArr.length === 1) jsonLd.author = authorArr[0];
else if (authorArr.length > 1) jsonLd.author = authorArr;
// else: omit

第 4 步:编辑团队署名走 Organization

没有具名个人的内容:

"author": {
  "@type": "Organization",
  "name": "Acme Editorial",
  "url": "https://example.com/about/editorial"
}

不要造一个假人。

第 5 步:在 CMS 里回填缺失的 author 数据

对受影响 URL:

# Find articles with missing author.name in JSON-LD
for url in $(cat affected.txt); do
  curl -s "$url" | grep -q '"author":\s*"' && echo "STRING_AUTHOR: $url"
  curl -s "$url" | grep -q '"name":\s*null' && echo "NULL_NAME: $url"
done

逐个编辑,或者写一次性脚本设合理默认(老文章设真实作者;匿名设编辑 Org)。

第 6 步:CI 加必填 schema 字段断言

// scripts/validate-schema.mjs
import { parse } from 'node-html-parser';

for (const url of sampleUrls) {
  const html = await fetch(url).then(r => r.text());
  const root = parse(html);
  const ld = root.querySelectorAll('script[type="application/ld+json"]');
  for (const node of ld) {
    const data = JSON.parse(node.text);
    if (data['@type'] !== 'Article' && data['@type'] !== 'BlogPosting') continue;
    if (typeof data.author === 'string') throw new Error(`String author: ${url}`);
    if (!data.author?.name && !Array.isArray(data.author)) throw new Error(`Missing author.name: ${url}`);
  }
}

每次部署都跑。回退能在用户看到之前被发现。

第 7 步:重新申请索引

对修好的 URL 抽样走 URL Inspection → Request indexing。盯 Search Console → Enhancements → Articles,警告数 1-3 周内回落。

验证

  • Rich Results Test 在 5 个修好的 URL 上 author 字段零警告。
  • Search Console → Enhancements → Articles 上 “Missing field ‘author.name’” 数量趋向 0。
  • 受影响 URL 的 SERP 上署名片段重新出现。
  • 每次 PR 上 CI 断言通过。
  • 新文章绝不会在缺少结构化 author 对象的情况下上线。

长期预防

  • 把 schema 字段当作内容合约的一部分:像必填表单字段一样校验。
  • JSON-LD 生成器用 TypeScript 类型 —— 缺字段在编译期就失败。
  • 在 repo README 或 schema-registry 文档里写清楚 author 的标准形态。
  • 确立规则:没有真实作者就用 Organization;绝不 fallback 到字符串。
  • 每季度审一次 Search Console 增强警告,发现慢漂移。

常见坑

  • "author": ""(空字符串)比缺字段还糟。Google 标空值比标缺失更严重。
  • 给 author 用 @type: "Thing"。语法合法,但不是 Google Article 富结果期望的类型。
  • 只在 microdata 或 RDFa 里写 author,JSON-LD 里没有。挑一种格式;Google 文档以 JSON-LD 为主。
  • 加了 author.imageauthor.sameAs,却忘了 author.name。name 才是真正必填的。
  • 把作者的 URL 写成 https://twitter.com/handle 当 name 用。URL 和 name 是不同字段。

FAQ

Q:author 可以是指向作者页的 URL 而不是内联对象吗?

Schema.org 允许这种写法,但 Google 富结果文档推荐用内联 Person 对象配 name。稳妥起见用内联。

Q:匿名社论能拿到 Article 富结果吗?

能,但 author 要是具名 Organization。“Editorial Team” 或刊物名都行。“Anonymous” 或空都不满足。

Q:作者用笔名怎么办?要不要露法律名?

按页面 byline 上写的来。Schema 必须镜像可见内容。byline 写 “J. Doe”,schema 的 name 就是 “J. Doe”。

Q:修完之后 SERP 上的署名片段会立刻回来吗?

不一定 —— 署名片段还取决于更广的信任信号。但修这个警告是前置条件。没有合法的 author.name,片段根本不在候选里。

标签: #SEO #排查 #结构化数据 #article-schema #author