Product 與 Offer 標記:電商商品的價格、庫存與評價
Product 是電商網站最有價值的 結構化資料 型別。它讓搜尋結果直接顯示 價格、庫存狀態與星等,使用者在點進來之前就看得到這些資訊。
本頁的範例只寫在程式碼區塊裡
這一頁不是商品頁,所以 檔頭沒有真的注入 Product 標記。標記一個不存在的商品正是要避免的事,理由見下方的 政策紅線 。
最小可用的標記
{
"@context": "https://schema.org",
"@type": "Product",
"name": "無線滑鼠 M100",
"image": ["https://example.com/mouse-1200.webp"],
"description": "2.4GHz 無線連線,續航 12 個月。",
"sku": "M100-BK",
"brand": {
"@type": "Brand",
"name": "某某品牌"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/products/mouse-m100",
"price": "790",
"priceCurrency": "TWD",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}欄位與它們換來什麼
| 欄位 | 必要性 | 換來什麼 |
|---|---|---|
name | 必填 | 商品名稱 |
offers | 建議 | 搜尋結果顯示價格 |
aggregateRating 或 review | 建議 | 搜尋結果顯示星等 |
image | 建議 | 搜尋結果的縮圖 |
brand | 建議 | 品牌識別 |
sku、gtin、mpn | 建議 | 商品識別碼,跨平台比對 |
description | 選填 | 商品描述 |
只有 name 是絕對必填
但只填 name 拿不到任何複合式呈現。價格靠 offers,星等靠 aggregateRating,這兩個才是真正有回報的欄位。
Offer:價格與庫存
"offers": {
"@type": "Offer",
"url": "https://example.com/products/mouse-m100",
"price": "790",
"priceCurrency": "TWD",
"availability": "https://schema.org/InStock",
"priceValidUntil": "2026-12-31",
"itemCondition": "https://schema.org/NewCondition",
"shippingDetails": {
"@type": "OfferShippingDetails",
"shippingRate": {
"@type": "MonetaryAmount",
"value": "60",
"currency": "TWD"
}
}
}price 的寫法
價格必須是純數字字串
// 錯誤:加了貨幣符號
"price": "NT$790"
// 錯誤:加了千分位逗號
"price": "1,290"
// 錯誤:用了數字型別以外的格式
"price": "790 元"
// 正確
"price": "790"
"price": "1290"幣別另外用 priceCurrency 表示,台幣是 TWD。
availability 的值
必須是完整的 Schema.org 網址,不是純文字:
| 值 | 意義 |
|---|---|
https://schema.org/InStock | 有庫存 |
https://schema.org/OutOfStock | 缺貨 |
https://schema.org/PreOrder | 預購 |
https://schema.org/BackOrder | 缺貨但可下訂 |
https://schema.org/Discontinued | 已停產 |
https://schema.org/SoldOut | 售完 |
// 錯誤
"availability": "InStock"
"availability": "有庫存"
// 正確
"availability": "https://schema.org/InStock"itemCondition
| 值 | 意義 |
|---|---|
https://schema.org/NewCondition | 全新 |
https://schema.org/UsedCondition | 二手 |
https://schema.org/RefurbishedCondition | 整新品 |
https://schema.org/DamagedCondition | 有瑕疵 |
評價:AggregateRating 與 Review
兩者可以只有一個,也可以並存。
AggregateRating(彙總評分)
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.3",
"reviewCount": "128",
"bestRating": "5",
"worstRating": "1"
}| 欄位 | 說明 |
|---|---|
ratingValue | 平均分數 |
reviewCount | 評論數量 |
ratingCount | 評分數量(可與評論數不同) |
bestRating | 滿分,預設 5 |
worstRating | 最低分,預設 1 |
reviewCount 或 ratingCount 至少要有一個
只填平均分數而沒有數量,標記會被判定不完整。兩者的差別是:ratingCount 是打分數的人數,reviewCount 是寫文字評論的人數。
Review(個別評論)
"review": [
{
"@type": "Review",
"author": { "@type": "Person", "name": "王小明" },
"datePublished": "2026-08-15",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5",
"bestRating": "5"
},
"reviewBody": "手感很好,續航也符合說明。"
}
]政策紅線:自我評價與假資料
這是唯一會招致人工處罰的部分
| 違規行為 | 說明 |
|---|---|
| 自我評價 | 網站自己產生的星等,不是真實使用者給的 |
| 假評論 | 虛構的評論者與評論內容 |
| 頁面上看不到的評價 | 標記有星等,但頁面上沒有評價區 |
| 價格不一致 | 標記寫 790,頁面顯示 890 |
| 標記缺貨商品為有庫存 | 庫存狀態與實際不符 |
後果是複合式結果被取消,嚴重時會收到人工處罰通知。
三個必須成立的條件
- 評價來自真實使用者:不是網站自己給的。
- 評價在頁面上看得到:使用者找得到那個評價區。
- 數字完全一致:標記的平均分與評論數,與頁面顯示的相同。
價格必須即時同步
標記的價格與頁面不一致就是違規
價格會變、庫存會變。手工維護標記一定會不同步。
正確做法是 從同一份商品資料同時產生頁面與標記:
// 同一個 product 物件同時餵給模板與標記,不可能不同步
function buildProductSchema(product, domain) {
return {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
image: product.images.map((path) => `${domain}${path}`),
description: product.description,
sku: product.sku,
brand: { '@type': 'Brand', name: product.brandName },
offers: {
'@type': 'Offer',
url: `${domain}/products/${product.slug}`,
price: String(product.price), // 純數字字串
priceCurrency: 'TWD',
availability: product.stock > 0
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
itemCondition: 'https://schema.org/NewCondition',
},
// 只有真的有評價時才輸出這個欄位
...(product.reviewCount > 0 && {
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: String(product.averageRating),
reviewCount: String(product.reviewCount),
},
}),
};
}沒有評價就不要輸出那個欄位
上面用條件展開處理,評論數為 0 時整個 aggregateRating 不會出現,而不是輸出一個 "reviewCount": "0"。
多規格商品
同一款商品有多種顏色或尺寸時,有兩種做法。
用 AggregateOffer 表示價格區間
簡單,但搜尋結果只會顯示「790 起」這類區間。
"offers": {
"@type": "AggregateOffer",
"lowPrice": "790",
"highPrice": "1290",
"priceCurrency": "TWD",
"offerCount": "4"
}用 ProductGroup 列出變體
較複雜,但每個規格各有自己的價格、庫存與識別碼。
{
"@context": "https://schema.org",
"@type": "ProductGroup",
"name": "無線滑鼠 M100",
"productGroupID": "M100",
"variesBy": ["https://schema.org/color"],
"hasVariant": [
{
"@type": "Product",
"name": "無線滑鼠 M100 黑色",
"sku": "M100-BK",
"color": "黑色",
"offers": {
"@type": "Offer",
"price": "790",
"priceCurrency": "TWD",
"availability": "https://schema.org/InStock"
}
},
{
"@type": "Product",
"name": "無線滑鼠 M100 白色",
"sku": "M100-WH",
"color": "白色",
"offers": {
"@type": "Offer",
"price": "790",
"priceCurrency": "TWD",
"availability": "https://schema.org/OutOfStock"
}
}
]
}商品識別碼
| 欄位 | 說明 |
|---|---|
sku | 自家的商品編號 |
gtin、gtin8、gtin13、gtin14 | 全球貿易品項編號(條碼) |
mpn | 製造商零件編號 |
有條碼就填 gtin
它讓搜尋引擎能把不同賣家的同一款商品對應起來。gtin13 對應 EAN-13(一般商品條碼),gtin12 對應 UPC。
商品頁的其他 SEO 要點
Product 標記只是商品頁 SEO 的一部分:
| 項目 | 見 |
|---|---|
| 商品分類的路徑 | 麵包屑標記 |
| 商品同時掛多個分類 | 網址正規化 |
| 商品列表的分頁 | 分頁與無限滾動 |
| 缺貨商品要不要下架 | 轉址與狀態碼 |
| 商品圖片的最佳化 | 圖片 SEO |
缺貨商品不要直接 404
永久停產才回傳 410 或轉址。只是暫時缺貨的話,保留頁面並把 availability 標成 OutOfStock,那些頁面累積的排名很有價值,補貨後立刻能用。
檢查清單
| 項目 | 標準 |
|---|---|
有 name | 必備 |
price 是純數字字串(無符號無逗號) | 必備 |
priceCurrency 為三字母代碼 | 必備 |
availability 是完整的 Schema.org 網址 | 必備 |
| 標記的價格與頁面一致 | 必備 |
| 庫存狀態與實際一致 | 必備 |
| 評價來自真實使用者 | 必備 |
| 評價在頁面上看得到 | 必備 |
| 沒有評價時不輸出評價欄位 | 必備 |
| 從商品資料自動產生標記 | 建議 |
有 sku 或 gtin | 建議 |
| 通過 複合式搜尋結果測試 | 建議 |
常見問題
Product 標記的必填欄位有哪些?
只有名稱是絕對必填。但要取得帶價格的搜尋結果呈現,還需要 offers 物件並在裡面填上價格與幣別。要取得星等呈現則需要 aggregateRating 或 review 其中之一。
價格要怎麼寫才正確?
價格用純數字字串,不要加貨幣符號、不要加千分位逗號,幣別另外用三個字母的代碼欄位表示。台幣是 TWD。寫成帶符號的字串會讓那個欄位被判定無效。
可以標記自己給自己的評價嗎?
絕對不行。評價必須來自真實使用者,而且必須在頁面上看得到。網站自己產生的星等屬於明確的違規行為,可能導致複合式結果被取消甚至收到人工處罰通知。
價格變動了標記要跟著改嗎?
要,而且必須即時。標記的價格與頁面顯示的價格不一致,屬於標記與內容不符。正確做法是從同一份商品資料同時產生頁面與標記,這樣就不可能不同步。
同一款商品有多種規格怎麼標?
有兩種做法:用 AggregateOffer 表示最低到最高價,或用 ProductGroup 把各規格當成變體列出。前者簡單,後者能讓每個規格各有自己的價格、庫存與識別碼。
延伸閱讀
參考資料:Google 搜尋中心:商品結構化資料