Zola 网站补全 JSON-LD 结构化数据:让搜索结果多出一行信息
【免费下载链接】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(结构化数据的标准写法),搜索结果里就能多出作者、发布日期,甚至缩略图。本文只动模板文件,5 分钟跑通最小可用版本,适合任何有博客或栏目结构的 Zola 站点。
为什么需要 Schema.org 结构化数据
搜索引擎读的是 HTML 文本,它并不天然知道哪段文字是作者、哪段是日期。JSON-LD 把一份机器可读的键值描述嵌进页面,引擎解析后就能在富结果位展示这些信息,Schema.org 是各搜索引擎共用的词汇标准。
读完本文你能:
- 在文章模板里输出 Article 结构化数据
- 为产品页输出 Product 标记
- 给首页加上 WebSite 全局标记
- 把不同标记封装成可复用的模板片段
5 分钟跑通最小可用版 Zola JSON-LD
第 1 步:确认站点配置里的公共字段。打开站点根目录的zola.toml,确保有下面这几行(没有就补上):
title = "我的博客" description = "关于静态站点生成的笔记" base_url = "https://example.com" author = "你的笔名"这几个字段后面会被 JSON-LD 反复引用,author是文章没写作者时的兜底值。
第 2 步:新建templates/schema/article.html,写入完整的脚本块。
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "headline": "{{ page.title }}", "description": "{{ page.description | default(value=config.description) }}", "author": { "@type": "Person", "name": "{{ page.extra.author | default(value=config.author) }}" }, "datePublished": "{{ page.date | date(format='%Y-%m-%dT%H:%M:%SZ') }}", "dateModified": "{{ page.updated | default(value=page.date) | date(format='%Y-%m-%dT%H:%M:%SZ') }}", "mainEntityOfPage": { "@type": "WebPage", "@id": "{{ current_url }}" } } </script>这一段把 front matter 里的元数据翻译成一篇 Article 描述。date过滤器把日期格式化成 ISO 8601,两处default保证字段缺失时不会渲染出空值。
第 3 步:在templates/page.html的开头引用它。
{% extends "index.html" %} {% block content %} {% include "schema/article.html" %} {{ page.title | safe }} {{ page.content | safe }} {% endblock %}JSON-LD 放在<head>或正文里都有效,所以直接放在内容区顶部即可,不依赖主题模板的 head 结构。这样每篇文章构建后都会带上自己的结构化数据。
第 4 步:构建并检查输出。
zola serve启动后打开任意一篇文章,右键"查看页面源代码",找到<script type="application/ld+json">,里面应该是变量全部替换完毕的纯 JSON。需要部署到线上再实际验证时,先跑一次zola build检查产物。
拆开看:Tera 如何把页面变量渲染成 JSON-LD
Zola 是静态站点生成器,构建时 Tera 模板引擎会遍历每个模板,把{{ }}占位符替换成渲染上下文里的真实值。上下文来自三处:页面 front matter(page.title、page.date)、zola.toml(config.*),以及引擎注入的current_url这类内置变量。整个过程就像乐高底板——模板是底板,变量是拼上去的积木块,构建完成的 HTML 里已经是最终成品,不再有占位符。爬虫抓到的就是这份成品,它按脚本类型找到 JSON-LD、解析其中的 JSON,再决定搜索结果展示什么。如果对某个变量存疑,可以在模板里临时写{{ __tera_context }},把整个上下文明明白白打印出来看。
覆盖更多页面类型
文章页:补上图片和关键词
第 2 步的最小版本只保留了必填字段,文章页可以再补两个可选字段。把article.html中mainEntityOfPage那行的结尾逗号去掉,改成:
"mainEntityOfPage": { "@type": "WebPage", "@id": "{{ current_url }}" } {% if page.taxonomies.tags %}, "keywords": "{{ page.taxonomies.tags | join(sep=', ') }}"{% endif %} {% if page.extra.image %}, "image": "{{ get_url(path=page.extra.image) }}"{% endif %}get_url会按 static 目录优先的顺序查找文件,所以封面图放在static/images/下、front matter 写image = "images/cover.png"就能用。把条件字段放在 JSON 末尾,是为了避免{% if %}破坏逗号结构。
产品页(Product)
新建templates/schema/product.html:
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "{{ page.title }}", "description": "{{ page.description }}", "sku": "{{ page.extra.sku }}", "offers": { "@type": "Offer", "price": "{{ page.extra.price }}", "priceCurrency": "{{ page.extra.currency }}", "availability": "https://schema.org/InStock", "url": "{{ current_url }}" } } </script>+++ title = "无线鼠标" description = "静音按键,长续航" sku = "WM-01" price = 299 currency = "CNY" +++与 Article 块的差别在于:headline换成name,价格信息收进offers子对象,字段全部来自 front matter,模板里不写死任何商品数据。
站点全局(WebSite / Organization)
在templates/index.html顶部加一段,只在首页输出一次:
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "WebSite", "name": "{{ config.title }}", "url": "{{ config.base_url }}", "description": "{{ config.description }}", "potentialAction": { "@type": "SearchAction", "target": "{{ config.base_url }}/search?q={search_term_string}", "query-input": "required name=search_term_string" } } </script>这段引用的全是config而不是page,因为它描述的是整个站点。SearchAction声明站内搜索入口,路径请改成你站点实际的搜索页地址。
三种类型都稳定后,建议保持templates/schema/目录结构不动,在page.html里按 front matter 条件引用:
{% if page.extra.schema == "article" %} {% include "schema/article.html" %} {% elif page.extra.schema == "product" %} {% include "schema/product.html" %} {% endif %}以后新增类型时,只要多建一个文件、在 front matter 里加一行schema = "product"即可。
JSON-LD 常见踩坑与排查
症状:源码里有脚本标签,验证工具却显示"未找到结构化数据"原因:include 写在了
section.html这类模板里,而该页面实际由page.html渲染,脚本块根本没被输出修法:确认引用写在该页面类型真正使用的模板中;拿不准上下文时临时输出{{ __tera_context }}核对症状:JSON-LD 里日期字段是空字符串原因:文章 front matter 没有
updated字段,page.updated未定义修法:给所有可能缺失的字段加| default(value=...)兜底,写法见第 2 步代码症状:验证工具提示"图片 URL 必须是绝对地址"原因:部署时
base_url没配置为正式域名,get_url只输出了相对路径修法:在正式环境配置里把base_url设为真实站点地址,且末尾不带斜杠症状:解析报 JSON 无效,缺逗号或多出空白原因:用
{% if %}条件输出字段时,JSON 的逗号结构被破坏修法:每种类型的 JSON-LD 放进独立的templates/schema/*.html文件,被条件包裹的字段一律放在 JSON 末尾
一张清单收尾
- 脚本块位于 head 或 body 内,JSON 合法
- 日期为 ISO 8601,缺失字段有 default 兜底
- base_url 为线上地址,输出的是绝对 URL
- 不同页面类型引用对应的 schema 片段
- 上线后用搜索引擎官方富结果工具验证一次
结构化数据就位后,搜索结果会替你的内容说话。
相关参考:模板与页面变量说明、站点配置说明
【免费下载链接】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),仅供参考