搜索结果只剩一行标题?5 分钟给 Zola 网站加上搜索引擎看得懂的结构化数据
【免费下载链接】zolaA fast static site generator in a single binary with everything built-in. https://www.getzola.org项目地址: https://gitcode.com/GitHub_Trending/zo/zola
当你的博客文章在搜索结果里只剩一行标题和链接时,问题通常不是内容写得不好,而是搜索引擎“看不懂”它。Zola 是一个单二进制、模板完全由你掌控的静态网站生成器,给它补上 Schema.org 结构化数据(JSON-LD 形态),就是 SEO 里最直接的翻译层:机器读到标记,用户在搜索框里看到富媒体卡片。
一行标题和富卡片之间,差的是机器可读的标记
搜索结果里的“卡片”——摘要、作者头像、发布日期、缩略图——不是搜索引擎凭空生成的,它来自页面里嵌在<script type="application/ld+json">中的一段 JSON。这段 JSON 遵循 Schema.org 的词表,告诉机器:这是 Article,标题是 X,发布日期是 Y,作者是 Z。
💡 没有这段标记时,机器只能靠猜:从一堆 HTML 里推断哪个是标题、哪段是正文。猜对是运气,猜错就没有富媒体结果;有了标记,猜的过程直接跳过。
所以差距清单很具体:页面得声明类型(Article)、给出headline、datePublished、author、image这几个字段。Zola 的页面变量里这些几乎都有现成的,缺的只是把它们写进模板那一步。
可直接复制的最小 Article JSON-LD 模板
能跑通的最短模板
在 templates/ 下新建schema/article.html,把下面的内容放进去。最关键的是date那一行:Zola 内置的 feed 模板就是用%:z输出时区偏移的,datePublished必须长成 ISO 8601 的样子才有效。
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "{{ page.title }}", "image": [ {% for asset in page.assets if asset is matching("\\.(png|jpe?g|webp|avif)$") %} "{{ get_url(path=asset) }}"{% if not loop.last %},{% endif %} {% endfor %} ], "author": { "@type": "Person", "name": "{{ page.extra.author | default(value=config.extra.author) }}" }, "datePublished": "{{ page.date | date(format='%Y-%m-%dT%H:%M:%S%:z') }}", "dateModified": "{{ page.updated | default(value=page.date) | date(format='%Y-%m-%dT%H:%M:%S%:z') }}", "mainEntityOfPage": "{{ current_url }}" } </script>模板里每个字段对应哪个 Zola 变量
page.title、page.date、page.updated、page.assets都是 Zola 页面对象自带的字段;get_url(path=...)负责把静态资源路径换算成带base_url的完整地址,保证image里的链接在任何部署环境下都能访问;current_url是模板内置变量,直接给出当前页完整 URL,供mainEntityOfPage使用。default过滤器则是给可选字段兜底——没写extra.author的文章不会渲染出空的作者名。
⚠️ 唯一要留神的:headline里如果出现英文双引号,JSON 会直接断掉。标题保持简短,或写死不带引号的措辞,这个成本远低于做转义。
让 JSON-LD 只在文章页生效
用主题的话,先查它做没做
如果站点套了主题,打开主题的文档和theme.toml找schema、JSON-LD这类词——不少主题已经内置了结构化数据,重复注入两份标记反而会让验证工具报错。
上面这个 AdiDoks 主题就是例子:它的配置里专门留了[extra.schema]段落来下发站点级 JSON-LD。你在 themes/ 里翻自己的主题时,看的就是这种写法。
条件包含与站点级配置
主题没做,就在page.html的<head>里做定向包含:{% if %}这一行决定了标记只跟着文章页走,首页、分类页不会被误标成 Article。
<head> ... {% if page.section == "posts" %} {% include "schema/article.html" %} {% endif %} </head>站点级信息沉到config.toml里,模板就不必每篇 front matter 都重复写作者:
[extra] author = "你的笔名"产品页与首页也有各自的 Schema 类型
产品页:Product 加 Offer
商品内容别沿用 Article 的类型——机器读到@type: Article却找不到正文结构,验证会直接报警。仿照文章模板建schema/product.html,价格信息放在offers里,extra字段从 front matter 取:
{ "@context": "https://schema.org", "@type": "Product", "name": "{{ page.title }}", "offers": { "@type": "Offer", "price": "{{ page.extra.price }}", "priceCurrency": "{{ page.extra.currency | default(value='CNY') }}" } }包含方式和文章页完全一样,换个 section 名再包一层{% if %}即可。
首页:WebSite
首页是整站的入口,标成WebSite才能让机器理解“这是一个站点,而不是一篇文章”。只保留两个必填字段就够起步:
{ "@context": "https://schema.org", "@type": "WebSite", "name": "{{ config.title }}", "url": "{{ config.base_url }}" }放进index.html的<head>,config.title和config.base_url都是配置对象直接给的,不需要额外设置。
上线前验证:确认标记真的生效
用 zola build 在本地核对产物
标记是构建时生成的,改完模板先跑一次构建,再在产物里搜——出现匹配说明脚本真的进了 HTML:
zola build && grep -rl "ld+json" public | head更直接的办法是zola serve起本地服务,在浏览器开发者工具里搜application/ld+json,肉眼确认字段值都填对了——这一步能拦下九成的低级错误。
标记出错的三个高频位置
headline、datePublished这类必需字段缺失,Article 验证必挂,模板里留空字符串也算缺失。- 日期不是 ISO 8601 格式,比如只写了
%Y-%m-%d或本地化格式,机器无法解析时间。 - 标题或作者名带英文引号把 JSON 结构打断,页面能打开但整段标记被丢弃。
✅ 本地构建的 HTML 过了验证,就把它提交部署,然后做两件事:用 Google 的富媒体结果测试工具粘贴线上 URL 复查一遍,再把站点自带的sitemap.xml提交到搜索引擎的站点管理工具里,观察几天搜索结果卡片的变化。富媒体结果不是构建完立刻出现的——标记就位、提交 sitemap、给索引一点时间,这三件事做完才算闭环。🚀
【免费下载链接】zolaA fast static site generator in a single binary with everything built-in. https://www.getzola.org项目地址: https://gitcode.com/GitHub_Trending/zo/zola
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考