# 结构化数据

> 为 Shoplazza 主题添加 JSON-LD 结构化数据与 Open Graph 标签，让搜索引擎展示富媒体结果、社交平台生成链接预览卡。

结构化数据和社媒标签帮助搜索引擎与社交平台理解你的页面。它们驱动富媒体结果（如搜索结果中展示商品价格和库存）以及社交媒体上的链接预览。本指南介绍如何在 theme 中添加 JSON-LD 结构化数据和 Open Graph 标签。

两者都写在页面 HTML 里、供机器读取，顾客看不到：

- **结构化数据**告诉搜索引擎这个页面是什么——对商品而言，就是它的价格、库存和评分——这样搜索结果就能直接展示这些信息（即**富媒体结果**），而不只是一个标题加链接。标准格式是 **JSON-LD**：写在 `<script type="application/ld+json">` 标签里的一段 JSON，也是 Google 推荐的方式。
- **社媒标签**告诉社交平台：当有人分享你的链接时，该展示什么图片、标题和描述（即**链接预览**卡片）。标准格式是 **Open Graph**——`og:` 开头的 `<meta>` 标签，最早由 Facebook 提出，如今大多数平台都支持。

关于页面标题、描述和规范 URL，见[元数据](/zh-CN/docs/theme/theme-features/seo/metadata)。

:::warning
结构化数据必须与页面可见内容一致。如果标记里的价格、货币或库存与顾客看到的不同，搜索引擎可能会忽略它或标记该页面。
:::

## 添加网站结构化数据

在任意页面，你都可以用 [WebSite](https://schema.org/WebSite) 结构化数据描述店铺本身：

```liquid
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "WebSite",
  "name": {{ shop.name | json }},
  "url": {{ shop.url | json }}
}
</script>
```

## 添加商品结构化数据

在 `<script type="application/ld+json">` 标签内以 JSON-LD 形式输出 [Product](https://schema.org/Product) 结构化数据。把它放在一个 snippet 里，从布局的 `<head>` 中引入，在商品页渲染。

先选定要描述的 variant，再用 [product](/zh-CN/docs/theme/references/liquid/objects/product)、[variant](/zh-CN/docs/theme/references/liquid/objects/variant)、[cart](/zh-CN/docs/theme/references/liquid/objects/cart)、[shop](/zh-CN/docs/theme/references/liquid/objects/shop) 对象构建 JSON：

```liquid
{% assign variant = product.selected_or_first_available_variant %}
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": {{ product.title | json }},
  "url": {{ canonical_url | json }},
  "image": {{ product.image.src | prepend: 'https:' | json }},
  {% if product.description != blank %}"description": {{ product.description | strip_html | json }},{% endif %}
  {% if product.vendor != blank %}"brand": { "@type": "Brand", "name": {{ product.vendor | json }} },{% endif %}
  {% if variant.sku != blank %}"sku": {{ variant.sku | json }},{% endif %}
  {% if variant.barcode != blank %}"gtin": {{ variant.barcode | json }},{% endif %}
  "offers": {
    "@type": "Offer",
    "url": {{ canonical_url | json }},
    "priceCurrency": {{ cart.currency | json }},
    "price": {{ variant.price | times: 1 | json }},
    "itemCondition": "https://schema.org/NewCondition",
    "availability": "https://schema.org/{% if variant.available %}InStock{% else %}OutOfStock{% endif %}",
    "seller": { "@type": "Organization", "name": {{ shop.name | json }} }
  }
}
</script>
```

各部分的含义，以及保证输出有效且准确的细节：

* `product.selected_or_first_available_variant` 选出顾客选中的 variant，没有则取第一个有货的；后续 `variant.*` 字段都描述它。
* `@context` 和 `@type` 声明使用 schema.org 词汇表、类型为 `Product`；`offers` 承载可购买的价格、商品状态、库存状态和卖家。
* 可选字段（`description`、`brand`、`sku`、`gtin`）都包在 `{% if %}` 守卫里，仅当有值时才输出——空字段会让 JSON 失效。
* `image.src` 返回协议相对 URL（`//…`），需 prepend `https:` 得到绝对 URL。
* `json` 过滤器会对每个值转义并加引号，因此不要再自己加引号。
* `price` 经 `times: 1` 处理，输出为数字（`33`）而非字符串（`"33"`）。
* `priceCurrency` 用 [`cart.currency`](/zh-CN/docs/theme/references/liquid/objects/cart)，而不是 `shop.currency`。店铺支持多货币时，`cart.currency` 反映顾客当前查看的货币，使标记与显示价格一致。
* `url` 用 [canonical_url](/zh-CN/docs/theme/references/liquid/objects/canonical_url) 对象，即当前商品页的绝对 URL。
* 仅当 variant 的 `barcode` 是有效 GTIN（UPC、EAN 或 ISBN）时才输出 `gtin`。

### 变价商品

当商品的多个 variant 价格构成区间时，用 [AggregateOffer](https://schema.org/AggregateOffer) 代替单个 `Offer`，以 `price_min` 和 `price_max` 描述：

```liquid
"offers": {
  "@type": "AggregateOffer",
  "priceCurrency": {{ cart.currency | json }},
  "lowPrice": {{ product.price_min | times: 1 | json }},
  "highPrice": {{ product.price_max | times: 1 | json }},
  "offerCount": {{ product.variants.size }}
}
```

## 添加 Open Graph 和 Twitter 标签

Open Graph（`og:`）和 Twitter Card 元标签控制页面被分享到社交平台时的展示效果。把它们加到 `<head>` 中。

最常用的 Open Graph 属性：

| 属性 | 说明 |
| --- | --- |
| `og:title` | 预览中显示的标题 |
| `og:type` | 对象类型——`website`、`article`、`product` 等 |
| `og:image` | 预览卡片中显示的图片 |
| `og:url` | 页面的规范 URL |
| `og:description` | 一到两句话的摘要 |
| `og:site_name` | 店铺整体名称 |
| `og:locale` | 区域，如 `en_US` |

前四个（`og:title`、`og:type`、`og:image`、`og:url`）是协议要求的必填项，其余为可选。完整的属性与对象类型列表，见 [Open Graph 协议官网](https://ogp.me/)。

比如，取当前页面对象的值，并回退到店铺级别的值：

```liquid
<meta property="og:type" content="{% if template.name == 'product' %}product{% else %}website{% endif %}">
<meta property="og:title" content="{{ page_title | default: shop.name | escape }}">
<meta property="og:description" content="{{ page_description | default: shop.description | strip_html | escape }}">
<meta property="og:url" content="{{ canonical_url | default: shop.url }}">
{% if product.image %}
  <meta property="og:image" content="https:{{ product.image.src | img_url: '1200x' }}">
  <meta property="og:image:secure_url" content="https:{{ product.image.src | img_url: '1200x' }}">
  <meta property="og:image:width" content="{{ product.image.width }}">
  <meta property="og:image:height" content="{{ product.image.height }}">
  <meta property="og:image:alt" content="{{ product.image.alt | escape }}">
{% endif %}

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ page_title | default: shop.name | escape }}">
<meta name="twitter:description" content="{{ page_description | default: shop.description | strip_html | escape }}">
```

这些标签如何取值：

* `og:type` 在商品页为 `product`，其他页面为 `website`，由 `template.name` 决定。
* `default` 过滤器在页面自身没有值时，回退到店铺级别的值（`shop.name`、`shop.description`、`shop.url`）。
* `og:image` 的宽、高和 alt 文本帮助平台渲染预览卡片；`twitter:card` 设为 `summary_large_image` 表示请求大图预览。

在商品页，添加价格和库存的商品专属标签。它们用 `product:` 命名空间——这是 Facebook 在 `og:type` 为 `product` 时生效的扩展，而非 `og:` 前缀。货币用 `cart.currency`，使其与显示价格一致：

```liquid
{% if template.name == 'product' %}
  {% assign variant = product.selected_or_first_available_variant %}
  <meta property="product:price:amount" content="{{ variant.price }}">
  <meta property="product:price:currency" content="{{ cart.currency }}">
  <meta property="product:availability" content="{% if variant.available %}in stock{% else %}out of stock{% endif %}">
{% endif %}
```

## 验证输出

添加结构化数据后，用 [Google 富媒体结果测试](https://search.google.com/test/rich-results)测试一个线上商品页，确认标记有效、有资格获得富媒体结果。
