Cách thiết lập schema cho trang sản phẩm
Chọn đúng mô hình schema cho trang sản phẩm
Product, Offer, AggregateOffer và ProductGroup khác nhau như thế nào?
Sai lầm phổ biến nhất khi thiết lập schema cho trang sản phẩm là xem toàn bộ dữ liệu thương mại như một khối duy nhất. Trên thực tế, Google và Schema.org phân tách sản phẩm, điều kiện bán hàng và biến thể thành các thực thể khác nhau.
Product mô tả bản thân sản phẩm. Nó trả lời những câu hỏi như:
-
Sản phẩm có tên gì?
-
Thuộc thương hiệu nào?
-
Có mã SKU, GTIN hoặc MPN nào?
-
Hình ảnh đại diện là gì?
-
Sản phẩm có những đặc điểm nào?
-
Đánh giá trung bình bao nhiêu?
Offer mô tả một đề nghị bán cụ thể. Nó trả lời:
-
Sản phẩm đang được bán với giá bao nhiêu?
-
Dùng đơn vị tiền tệ nào?
-
Còn hàng hay hết hàng?
-
Người bán là ai?
-
Sản phẩm mới hay đã qua sử dụng?
-
Người dùng có thể mua tại URL nào?
AggregateOffer dùng khi một sản phẩm có nhiều đề nghị bán được tổng hợp, chẳng hạn cùng một mẫu điện thoại được bán bởi nhiều nhà cung cấp với các mức giá khác nhau.
ProductGroup dùng để nhóm các biến thể thuộc cùng một dòng sản phẩm. Mỗi biến thể có thể khác nhau về màu sắc, kích thước, dung lượng, chất liệu, cấu hình, SKU, giá hoặc tình trạng tồn kho.
Có thể hình dung cấu trúc như sau:
Product
└── Offer
├── price
├── priceCurrency
├── availability
└── seller
Với sản phẩm có biến thể:
ProductGroup
├── Product biến thể 1
│ └── Offer
├── Product biến thể 2
│ └── Offer
└── Product biến thể 3
└── Offer
Việc phân tách đúng giúp Google không nhầm giá của sản phẩm với tên sản phẩm, không lấy tồn kho của biến thể này gắn cho biến thể khác và không hiểu một danh mục sản phẩm là một sản phẩm duy nhất.
Cách chọn cấu trúc schema theo từng loại trang
Có thể áp dụng framework sau:
| Loại trang | Cấu trúc phù hợp |
|---|---|
| Một sản phẩm, một SKU, một giá | Product kết hợp Offer |
| Một sản phẩm, nhiều người bán | Product kết hợp AggregateOffer |
| Một dòng sản phẩm có nhiều màu, size hoặc dung lượng | ProductGroup và các Product biến thể |
| Trang review sản phẩm nhưng không bán trực tiếp | Product kết hợp Review hoặc AggregateRating |
| Trang danh mục chứa nhiều sản phẩm độc lập | Không dùng một Product chung cho cả danh mục |
| Trang thương hiệu hoặc bộ sưu tập | Dùng loại schema phù hợp với nội dung, không biến thành Product giả |
Ví dụ, trang “Điện thoại Samsung” chứa 30 mẫu máy khác nhau không phải là một Product có 30 mức giá. Nếu gắn một Product duy nhất cho toàn bộ danh mục, Google có thể hiểu sai tên, giá và đối tượng chính của trang.
Ngược lại, một trang “Áo thun Basic” có bốn lựa chọn màu và ba lựa chọn kích thước có thể được mô hình hóa bằng ProductGroup, trong đó mỗi tổ hợp màu và size là một Product riêng khi có SKU, giá hoặc tồn kho độc lập.
Product snippet và merchant listing
Trang sản phẩm có thể phục vụ hai nhóm trải nghiệm tìm kiếm chính.
Product snippet thường phù hợp với trang cung cấp thông tin, đánh giá hoặc so sánh sản phẩm. Trang không nhất thiết phải cho phép mua hàng trực tiếp.
Merchant listing phù hợp với trang bán hàng, nơi người dùng có thể xem giá, tình trạng hàng và thực hiện hành động mua. Dữ liệu có thể mở rộng sang vận chuyển, đổi trả, tình trạng sản phẩm và thông tin người bán.
Một trang thương mại điện tử nên ưu tiên mô hình merchant listing nếu sản phẩm thực sự có thể mua. Tuy nhiên, việc thêm schema chỉ giúp trang đủ điều kiện tham gia trải nghiệm kết quả nâng cao. Google không bảo đảm giá, sao đánh giá hoặc trạng thái hàng sẽ luôn xuất hiện với mọi truy vấn.
Chuẩn bị dữ liệu trước khi viết JSON-LD
Lập bảng ánh xạ dữ liệu sản phẩm
Trước khi lập trình, cần xác định mỗi thuộc tính schema được lấy từ trường dữ liệu nào trong hệ thống.
| Dữ liệu trên website | Thuộc tính schema | Quy tắc |
|---|---|---|
| Tên sản phẩm | name |
Dùng đúng tên đang hiển thị |
| URL sản phẩm | url |
Dùng URL tuyệt đối và có thể truy cập |
| Hình ảnh | image |
Dùng ảnh thật, không bị chặn thu thập |
| Mô tả | description |
Mô tả đúng sản phẩm, không nhồi từ khóa |
| SKU | sku |
Mã nội bộ duy nhất |
| GTIN | gtin8, gtin12, gtin13, gtin14 |
Chỉ dùng mã chính xác |
| MPN | mpn |
Mã do nhà sản xuất cung cấp |
| Thương hiệu | brand.name |
Dùng thương hiệu sản phẩm |
| Giá bán | offers.price |
Chỉ chứa giá trị số |
| Tiền tệ | offers.priceCurrency |
Ví dụ VND |
| Tồn kho | offers.availability |
Ánh xạ từ trạng thái thực tế |
| Tình trạng | offers.itemCondition |
Mới, cũ hoặc tân trang |
| Điểm trung bình | aggregateRating.ratingValue |
Tính từ đánh giá thật |
| Số đánh giá | aggregateRating.reviewCount |
Cập nhật tự động |
| Người bán | offers.seller |
Tên đơn vị bán hàng |
| Giá trị đến ngày | priceValidUntil |
Chỉ dùng khi có mốc hợp lệ rõ ràng |
Bảng mapping giúp đội SEO, lập trình viên và vận hành hiểu cùng một quy tắc. Nếu không có tài liệu này, schema thường được tạo bằng dữ liệu nhập tay, trong khi giao diện lại lấy từ cơ sở dữ liệu khác. Kết quả là giá, tồn kho và đánh giá có thể lệch nhau.
Phân biệt SKU, GTIN, MPN và thương hiệu
sku là mã quản lý nội bộ. Doanh nghiệp có thể tự đặt SKU để quản lý kho.
gtin là mã định danh thương mại toàn cầu. Tùy loại mã, website có thể sử dụng gtin8, gtin12, gtin13 hoặc gtin14.
mpn là mã sản phẩm hoặc linh kiện do nhà sản xuất cấp.
Ví dụ:
SKU: PHONE-BLK-256
GTIN-13: 8931234567890
MPN: ABC256VN
Không nên lấy SKU nội bộ điền vào gtin. Không nên tự tạo GTIN chỉ để xóa cảnh báo trong công cụ kiểm tra. Mã sai có thể khiến Google liên kết sản phẩm với một thực thể khác.
Trường brand cũng thường bị dùng sai. Nếu cửa hàng Điện Máy ABC bán tivi Samsung, thương hiệu sản phẩm là Samsung, còn Điện Máy ABC là người bán.
"brand": {
"@type": "Brand",
"name": "Samsung"
}
Tên cửa hàng nên đặt trong seller:
"seller": {
"@type": "Organization",
"name": "Điện Máy ABC"
}
Chuẩn hóa giá và đơn vị tiền tệ
Giá trong schema phải là mức giá người dùng thực sự có thể mua trong điều kiện được mô tả trên trang.
Cách khai báo đúng:
"price": "2490000",
"priceCurrency": "VND"
Không nên dùng:
"price": "2.490.000 VNĐ"
Không dùng:
"price": "Từ 2.490.000 đồng"
Không dùng:
"price": "Liên hệ"
price chỉ nên chứa giá trị số. Ký hiệu tiền tệ được xác định bằng priceCurrency.
Website cũng cần phân biệt giá công khai và giá có điều kiện. Nếu mức 2.490.000 đồng chỉ xuất hiện sau khi đăng nhập tài khoản thành viên, trong khi khách truy cập thông thường nhìn thấy 2.790.000 đồng, không nên mặc định đưa giá thành viên vào schema như giá chung.
Tương tự, giá sau khi nhập mã giảm giá không phải lúc nào cũng là giá nên khai báo. Cần xem người dùng có thể mua ngay với mức đó hay phải đáp ứng điều kiện bổ sung.
Chuẩn hóa tình trạng tồn kho
Một số trạng thái thường dùng:
https://schema.org/InStock
https://schema.org/OutOfStock
https://schema.org/PreOrder
https://schema.org/BackOrder
https://schema.org/Discontinued
Quy tắc ánh xạ nên được định nghĩa từ dữ liệu kho:
Số lượng lớn hơn 0
→ InStock
Số lượng bằng 0 nhưng cho phép đặt trước
→ PreOrder
Sản phẩm chưa có hàng nhưng chấp nhận đơn chờ
→ BackOrder
Không thể mua tại thời điểm hiện tại
→ OutOfStock
Ngừng kinh doanh vĩnh viễn
→ Discontinued
Không nên giữ InStock chỉ vì trang sản phẩm vẫn tồn tại hoặc nút liên hệ vẫn hiển thị. Availability phải phản ánh khả năng mua thực tế.
Chuẩn hóa đánh giá sản phẩm
Chỉ thêm AggregateRating khi website có dữ liệu đánh giá thật.
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "126",
"bestRating": "5",
"worstRating": "1"
}
Không nên:
-
Tạo một đánh giá 5 sao mặc định cho sản phẩm mới.
-
Lấy điểm đánh giá của toàn bộ cửa hàng gắn vào từng sản phẩm.
-
Dùng điểm do biên tập viên chấm như điểm trung bình của khách hàng.
-
Khai báo đánh giá trong JSON-LD nhưng không hiển thị trên trang.
-
Giữ số lượt đánh giá cũ sau khi dữ liệu đã thay đổi.
Điểm trung bình và số lượng đánh giá nên được tính từ cùng nguồn với giao diện. Nếu trang hiển thị 4,6 từ 91 đánh giá nhưng schema vẫn khai báo 4,7 từ 90 đánh giá, hai lớp dữ liệu đã không còn đồng bộ.

Cách tạo Product schema bằng JSON-LD
Quy trình triển khai chuẩn
Một quy trình an toàn gồm tám bước:
-
Kiểm tra schema đang có trên trang.
-
Xác định nguồn đang tạo Product schema.
-
Chọn một nguồn dữ liệu chính.
-
Lập bảng mapping thuộc tính.
-
Xác định quy tắc cho dữ liệu rỗng.
-
Tạo JSON-LD.
-
Đối chiếu với nội dung hiển thị.
-
Kiểm thử trên nhiều trạng thái sản phẩm.
Bước đầu tiên rất quan trọng vì nhiều website đã có schema từ theme, plugin SEO, ứng dụng review hoặc nền tảng thương mại điện tử. Nếu tiếp tục chèn thêm một Product mới, trang có thể xuất hiện nhiều thực thể mâu thuẫn.
Ví dụ:
Theme:
Product A – 2.990.000 đồng – InStock
Plugin SEO:
Product A – 3.490.000 đồng – OutOfStock
Plugin review:
Product A – 4,8 sao – 235 đánh giá
Có nhiều đoạn JSON-LD không phải lỗi tự thân. Vấn đề là chúng có cùng mô tả một sản phẩm nhưng không liên kết bằng @id, hoặc chứa dữ liệu khác nhau.
Mẫu JSON-LD cho sản phẩm đơn
Giải thích các thành phần quan trọng
@context xác định từ vựng Schema.org.
@type cho biết thực thể đang được mô tả là Product.
@id tạo định danh ổn định cho thực thể. Đây không nhất thiết là một URL người dùng truy cập, nhưng nên dựa trên URL chính của sản phẩm để các đoạn schema khác có thể tham chiếu.
url là URL trang sản phẩm.
name, description và image phải phản ánh đúng nội dung người dùng nhìn thấy.
sku, gtin13 và brand giúp nhận diện sản phẩm rõ hơn.
aggregateRating chỉ được xuất khi có dữ liệu đánh giá thật.
offers chứa toàn bộ thông tin giao dịch, bao gồm giá, tiền tệ, tình trạng hàng, người bán và tình trạng sản phẩm.
Quy tắc xử lý dữ liệu rỗng
Không nên xuất:
"gtin13": "",
"mpn": null,
"ratingValue": "0"
Nên sử dụng logic:
Có GTIN hợp lệ
→ Xuất gtin
Không có GTIN
→ Bỏ thuộc tính gtin
Có ít nhất một đánh giá thật
→ Xuất aggregateRating
Chưa có đánh giá
→ Không xuất aggregateRating
Trang bán sản phẩm
→ Xuất Offer
Trang chỉ review
→ Không tạo Offer giả
Schema không cần chứa mọi thuộc tính có thể dùng. Nó cần chứa dữ liệu chính xác, có thật và có thể duy trì.
Xử lý các tình huống sản phẩm thực tế
Sản phẩm đang giảm giá
Giả sử giá niêm yết là 3.490.000 đồng, giá bán hiện tại là 2.990.000 đồng.
Không nên khai báo:
"price": "3490000 - 2990000"
price phải là giá hiện tại mà người dùng có thể thanh toán:
"offers": {
"@type": "Offer",
"priceCurrency": "VND",
"price": "2990000",
"availability": "https://schema.org/InStock"
}
Giá cũ có thể hiển thị trên giao diện để người dùng so sánh. Không nên nhét hai mức giá vào cùng trường price.
Nếu giá giảm chỉ áp dụng trong một thời gian xác định, có thể sử dụng priceValidUntil, nhưng ngày phải phản ánh đúng chương trình thực tế. Không nên đặt một ngày xa tùy ý chỉ để tránh cảnh báo.
Giá thành viên, giá theo mã và giá trả góp
Cần xác định giá nào là giá bán có thể tiếp cận trực tiếp.
| Tình huống | Cách xử lý |
|---|---|
| Giá giảm công khai cho mọi khách | Dùng giá sau giảm |
| Giá chỉ dành cho thành viên | Chỉ dùng khi điều kiện được thể hiện rõ |
| Giá sau khi nhập mã | Không mặc định dùng nếu mã chưa được áp dụng |
| Giá trả góp mỗi tháng | Không dùng thay cho tổng giá sản phẩm |
| Giá chưa bao gồm lựa chọn bắt buộc | Không dùng như giá hoàn chỉnh |
| Giá theo số lượng | Cần mô tả đúng điều kiện áp dụng |
Nếu trang quảng cáo “chỉ từ 199.000 đồng” nhưng người dùng phải mua gói dịch vụ hoặc phụ kiện bắt buộc mới có mức đó, schema không nên mô tả 199.000 đồng như giá sản phẩm độc lập.
Sản phẩm hết hàng hoặc ngừng kinh doanh
Sản phẩm hết hàng không bắt buộc phải xóa Product schema. Trang vẫn có thể tiếp tục mô tả sản phẩm, nhưng Offer phải chuyển sang OutOfStock.
"availability": "https://schema.org/OutOfStock"
Nếu cho phép đặt trước:
"availability": "https://schema.org/PreOrder"
Nếu sản phẩm ngừng kinh doanh vĩnh viễn:
"availability": "https://schema.org/Discontinued"
Ngoài schema, website cần có chiến lược URL phù hợp:
-
Giữ trang nếu vẫn có nhu cầu tìm kiếm và nội dung hữu ích.
-
Gợi ý sản phẩm thay thế.
-
Chuyển hướng khi có sản phẩm kế nhiệm tương đương.
-
Không chuyển mọi sản phẩm hết hàng về trang chủ.
-
Không để
InStockkhi nút mua đã bị vô hiệu hóa.
Sản phẩm không có GTIN hoặc chưa có đánh giá
Không có GTIN không đồng nghĩa với schema không hợp lệ. Một số sản phẩm thủ công, sản phẩm đặt riêng hoặc hàng không có mã thương mại toàn cầu có thể chỉ sử dụng SKU, MPN và thương hiệu.
Không nên tự tạo GTIN.
Tương tự, sản phẩm mới chưa có đánh giá không cần AggregateRating. Bỏ thuộc tính này tốt hơn việc tạo dữ liệu giả.
Schema chất lượng không được đánh giá bằng số lượng trường, mà bằng độ chính xác của từng trường.
Sản phẩm có nhiều người bán
Nếu một sản phẩm được bán bởi nhiều nhà cung cấp, có thể dùng AggregateOffer.
"offers": {
"@type": "AggregateOffer",
"priceCurrency": "VND",
"lowPrice": "2990000",
"highPrice": "3490000",
"offerCount": "5"
}
lowPrice là giá thấp nhất trong các offer thực tế. highPrice là giá cao nhất. offerCount là số đề nghị bán.
Không nên dùng AggregateOffer để thể hiện giá cũ và giá mới của một người bán. Hai mức đó không phải hai offer độc lập.
Sản phẩm có nhiều biến thể
Giả sử một mẫu áo có hai màu và ba kích thước:
Áo thun Basic
├── Đen – M
├── Đen – L
├── Đen – XL
├── Trắng – M
├── Trắng – L
└── Trắng – XL
Nếu mỗi tổ hợp có SKU hoặc tồn kho riêng, nên mô tả bằng ProductGroup và các Product biến thể.
Không nên lấy giá rẻ nhất làm giá đại diện nếu biến thể đó đã hết hàng.
Ví dụ:
| Biến thể | Giá | Tồn kho |
|---|---|---|
| 64 GB | 8.990.000 đồng | Hết hàng |
| 128 GB | 10.990.000 đồng | Còn hàng |
| 256 GB | 13.990.000 đồng | Còn hàng |
Nếu schema khai báo giá 8.990.000 đồng và InStock, người dùng sẽ không thể mua sản phẩm còn hàng ở mức giá được hiển thị. Cách tốt hơn là mô tả từng biến thể với Offer tương ứng.
Thiết lập schema trên từng nền tảng
WordPress và WooCommerce
WooCommerce, theme, plugin SEO và plugin review đều có thể tạo structured data.
Quy trình kiểm tra:
-
Mở một trang sản phẩm đại diện.
-
Chạy Rich Results Test.
-
Xem có bao nhiêu Product được phát hiện.
-
Kiểm tra mã nguồn để xác định nguồn tạo.
-
Chọn một nguồn schema chính.
-
Bổ sung dữ liệu thiếu tại nguồn đó.
-
Tắt hoặc lọc schema trùng.
-
Kiểm tra lại sản phẩm đơn và sản phẩm biến thể.
Không nên cài thêm plugin chỉ vì thiếu brand hoặc gtin. Plugin mới có thể tạo thêm một Product thay vì bổ sung vào thực thể hiện tại.
Một hướng tốt hơn là dùng hook hoặc filter để bổ sung thuộc tính vào schema WooCommerce đang có.
add_filter('woocommerce_structured_data_product', function ($markup, $product) {
$brand = get_post_meta($product->get_id(), '_brand_name', true);
if (!empty($brand)) {
$markup['brand'] = [
'@type' => 'Brand',
'name' => sanitize_text_field($brand),
];
}
return $markup;
}, 10, 2);
Đoạn mã chỉ mang tính minh họa. Cần kiểm tra phiên bản WooCommerce, theme và plugin trước khi triển khai thực tế.
Shopify
Shopify thường tạo JSON-LD bằng Liquid trong theme. Các ứng dụng SEO hoặc review có thể chèn thêm schema.
Cần kiểm tra:
-
Tên sản phẩm có lấy từ
product.titlekhông. -
Biến thể hiện tại có lấy từ
selected_or_first_available_variantkhông. -
SKU và barcode có thuộc đúng biến thể không.
-
Giá có bị chia hoặc nhân sai đơn vị không.
-
Trạng thái
availablecó ánh xạ đúng không. -
Ứng dụng review có gắn đánh giá vào đúng Product không.
-
Theme và ứng dụng có tạo hai Product xung đột không.
Ví dụ Liquid:
{% assign current_variant = product.selected_or_first_available_variant %}
{
"@type": "Product",
"name": {{ product.title | json }},
"sku": {{ current_variant.sku | json }},
"offers": {
"@type": "Offer",
"price": {{ current_variant.price | divided_by: 100.0 | json }},
"priceCurrency": {{ cart.currency.iso_code | json }},
"availability": "https://schema.org/{% if current_variant.available %}InStock{% else %}OutOfStock{% endif %}"
}
}
Cần hiểu đơn vị lưu giá của hệ thống. Nếu dữ liệu gốc được lưu theo đơn vị nhỏ nhất nhưng không được chuyển đổi đúng, giá trong schema có thể sai hàng trăm lần.
Website tự lập trình
Website tự lập trình nên xây dựng một lớp chuyển đổi dữ liệu riêng:
Dữ liệu Product
↓
Schema mapper
↓
Kiểm tra điều kiện
↓
JSON encoder
↓
Xuất vào HTML
Ví dụ:
function buildProductSchema(product) {
const schema = {
"@context": "https://schema.org",
"@type": "Product",
"@id": `${product.url}#product`,
"url": product.url,
"name": product.name,
"image": product.images,
"description": product.description,
"sku": product.sku,
"offers": {
"@type": "Offer",
"url": product.url,
"priceCurrency": product.currency,
"price": String(product.currentPrice),
"availability": mapAvailability(product.stockStatus)
}
};
if (product.brand) {
schema.brand = {
"@type": "Brand",
"name": product.brand
};
}
if (product.gtin13) {
schema.gtin13 = product.gtin13;
}
if (product.reviewCount > 0) {
schema.aggregateRating = {
"@type": "AggregateRating",
"ratingValue": String(product.ratingValue),
"reviewCount": String(product.reviewCount)
};
}
return schema;
}
Lớp mapper giúp:
-
Không nối chuỗi JSON thủ công.
-
Không xuất trường rỗng.
-
Dùng cùng logic cho toàn website.
-
Viết unit test cho từng trạng thái.
-
Giảm lỗi khi thay đổi template.
-
Đảm bảo HTML và JSON-LD lấy từ cùng nguồn.
Có nên chèn schema bằng Google Tag Manager?
Có thể chèn JSON-LD bằng Google Tag Manager, nhưng đây không nên là lựa chọn mặc định.
Rủi ro gồm:
-
Schema chỉ xuất hiện sau khi JavaScript chạy.
-
Tag không chạy do lỗi hoặc điều kiện kích hoạt.
-
Dữ liệu lấy từ DOM bị sai khi giao diện thay đổi.
-
Giá của biến thể chưa được cập nhật.
-
Consent mode hoặc trình chặn script ảnh hưởng việc tải.
-
Khó kiểm thử trên toàn bộ trạng thái sản phẩm.
Nếu có quyền chỉnh hệ thống, nên sinh schema từ phía máy chủ hoặc cùng lớp dữ liệu đang render nội dung sản phẩm.
Kiểm tra và sửa lỗi schema
Dùng đúng công cụ cho từng mục tiêu
Schema Markup Validator dùng để kiểm tra cấu trúc Schema.org:
-
Loại thực thể có tồn tại không.
-
Thuộc tính có phù hợp với loại không.
-
Giá trị có đúng kiểu dữ liệu không.
-
Quan hệ giữa các thực thể có hợp lý không.
Rich Results Test dùng để kiểm tra:
-
Google nhận diện loại kết quả nâng cao nào.
-
Có thiếu thuộc tính bắt buộc không.
-
Có lỗi nghiêm trọng không.
-
Có cảnh báo về trường khuyến nghị không.
-
Google đang đọc giá trị nào.
URL Inspection dùng để xác minh:
-
URL có được lập chỉ mục không.
-
Googlebot có truy cập được không.
-
HTML đã render có chứa schema không.
-
URL có bị
noindexkhông. -
Canonical có trỏ sang trang khác không.
-
JavaScript có tạo được JSON-LD không.
Google Search Console dùng để theo dõi diện rộng:
-
Số URL hợp lệ.
-
Số URL có cảnh báo.
-
Số URL lỗi.
-
Loại lỗi tăng đột biến.
-
Mẫu URL bị ảnh hưởng.
-
Thời điểm lỗi bắt đầu.
Một đoạn schema vượt qua công cụ kiểm tra chưa chắc phản ánh đúng dữ liệu kinh doanh. Công cụ có thể xác nhận "price": "2490000" hợp lệ về cú pháp, nhưng không biết giao diện đang bán với giá 2.990.000 đồng. Vì vậy, luôn phải đối chiếu công cụ với trang thực tế.
Ma trận kiểm thử bắt buộc
Không nên chỉ kiểm tra một sản phẩm đang hoạt động bình thường.
Bộ URL kiểm thử nên có:
-
Sản phẩm còn hàng.
-
Sản phẩm hết hàng.
-
Sản phẩm đặt trước.
-
Sản phẩm đang giảm giá.
-
Sản phẩm chưa có đánh giá.
-
Sản phẩm có nhiều đánh giá.
-
Sản phẩm không có GTIN.
-
Sản phẩm có một biến thể.
-
Sản phẩm có nhiều biến thể.
-
Biến thể rẻ nhất hết hàng.
-
Sản phẩm ngừng kinh doanh.
-
Sản phẩm có giá thành viên.
-
Sản phẩm có nhiều người bán.
-
Trang review không bán trực tiếp.
-
URL được render bằng JavaScript.
Mục tiêu là kiểm tra template trong mọi nhánh dữ liệu, không chỉ URL thuận lợi nhất.
Thứ tự ưu tiên sửa lỗi
Nên ưu tiên theo mức độ ảnh hưởng:
-
JSON không thể phân tích.
-
Thiếu thuộc tính bắt buộc.
-
Giá sai.
-
Đơn vị tiền tệ sai.
-
Tồn kho sai.
-
URL hoặc ảnh không truy cập được.
-
Nhiều Product xung đột.
-
Đánh giá không có thật.
-
SKU hoặc GTIN sai.
-
Thương hiệu sai.
-
Dữ liệu biến thể không khớp.
-
Thiếu trường khuyến nghị.
Một cảnh báo thiếu thuộc tính tùy chọn thường ít nghiêm trọng hơn việc khai báo sản phẩm còn hàng trong khi người dùng không thể mua.
Theo dõi sau khi triển khai
Nên triển khai theo từng đợt:
Môi trường thử nghiệm
↓
5–10 URL đại diện
↓
Kiểm tra schema
↓
Yêu cầu lập chỉ mục
↓
Theo dõi Search Console
↓
Mở rộng toàn bộ
Sau triển khai, cần theo dõi:
-
Số URL Product hợp lệ.
-
Lỗi merchant listing.
-
Lỗi product snippet.
-
Thay đổi trong Search appearance.
-
CTR của nhóm trang đã triển khai.
-
Tỷ lệ chuyển đổi organic.
-
Doanh thu từ trang đích organic.
-
Mức chênh lệch giữa website và Merchant Center.
Không nên kết luận schema giúp tăng CTR chỉ từ một vài ngày dữ liệu. CTR còn phụ thuộc vị trí, giá, thương hiệu, mùa vụ, đối thủ, tiêu đề và loại truy vấn.
Có thể chia trang thành hai nhóm tương đồng:
Nhóm A: Đã hoàn thiện schema
Nhóm B: Chưa thay đổi
Sau đó so sánh trong cùng khoảng thời gian để giảm nhiễu.
Checklist triển khai schema cho trang sản phẩm
Trước khi xuất bản
-
Chỉ có một Product chính hoặc các Product được liên kết rõ ràng.
-
Product mô tả đúng sản phẩm trung tâm của trang.
-
Offer mô tả đúng điều kiện bán hàng.
-
Tên sản phẩm khớp giao diện.
-
URL là URL tuyệt đối.
-
Hình ảnh truy cập được.
-
Giá chỉ chứa giá trị số.
-
Tiền tệ sử dụng mã như
VND. -
Tồn kho phản ánh khả năng mua.
-
SKU thuộc đúng sản phẩm hoặc biến thể.
-
GTIN và MPN không bị tự tạo.
-
Brand là thương hiệu sản phẩm.
-
Seller là đơn vị bán hàng.
-
Đánh giá có thật và hiển thị trên trang.
-
Số lượt đánh giá được cập nhật tự động.
-
Trường rỗng không được xuất.
-
Biến thể có giá và tồn kho riêng.
-
Không có schema trùng từ theme và plugin.
-
JSON-LD không lỗi cú pháp.
-
Rich Results Test không còn lỗi nghiêm trọng.
Sau khi xuất bản
-
Kiểm tra URL bằng URL Inspection.
-
Xác nhận Google nhìn thấy schema đã render.
-
Theo dõi báo cáo Product snippets.
-
Theo dõi báo cáo Merchant listings.
-
Kiểm tra URL lỗi theo từng template.
-
Đối chiếu giá và tồn kho định kỳ.
-
Kiểm tra lại sau khi cập nhật theme hoặc plugin.
-
Kiểm tra lại sau khi thay đổi hệ thống đánh giá.
-
Kiểm tra lại khi thêm biến thể mới.
-
So sánh dữ liệu website với Merchant Center.
-
Ghi nhận thời điểm triển khai để đo lường.
-
Không thay đổi đồng thời quá nhiều yếu tố nếu cần đánh giá tác động.
Kết luận
Thiết lập schema markup cho trang sản phẩm không phải là sao chép một đoạn JSON-LD rồi thay tên và giá. Muốn triển khai đúng, website phải xác định rõ Product, Offer, AggregateOffer và ProductGroup; xây dựng bảng ánh xạ dữ liệu; đồng bộ schema với giao diện; xử lý chính xác giá, tồn kho, đánh giá và biến thể; đồng thời loại bỏ các thực thể trùng lặp do theme hoặc plugin tạo ra.
Điểm quan trọng nhất là dữ liệu có cấu trúc phải lấy từ cùng nguồn đang vận hành trang sản phẩm. Khi giá thay đổi, schema phải thay đổi. Khi sản phẩm hết hàng, availability phải cập nhật. Khi có thêm đánh giá, điểm trung bình và số lượt đánh giá phải được tính lại. Khi người dùng chọn một biến thể khác, SKU, giá và tồn kho tương ứng phải được mô tả chính xác.
Một hệ thống schema tốt không chỉ vượt qua Rich Results Test ở một URL. Nó phải hoạt động ổn định trên toàn bộ danh mục, bao gồm sản phẩm mới, sản phẩm hết hàng, sản phẩm giảm giá, sản phẩm không có GTIN và sản phẩm có nhiều biến thể. Khi được xây dựng theo hướng đó, schema trở thành một lớp dữ liệu thương mại đáng tin cậy, giúp Google hiểu sản phẩm rõ hơn và tạo nền tảng tốt hơn cho khả năng hiển thị trên tìm kiếm.
Hỏi đáp về schema markup cho trang sản phẩm
Product schema có trực tiếp giúp tăng thứ hạng không?
Product schema không phải cam kết tăng thứ hạng. Vai trò chính của nó là giúp công cụ tìm kiếm hiểu rõ sản phẩm và làm trang đủ điều kiện tham gia các kết quả nâng cao. Hiệu quả SEO thực tế còn phụ thuộc nội dung, chất lượng trang, liên kết, giá bán, trải nghiệm người dùng và mức độ phù hợp với truy vấn.
Sản phẩm hết hàng có nên xóa schema không?
Không nhất thiết. Có thể giữ Product schema và chuyển availability sang OutOfStock. Nếu sản phẩm ngừng kinh doanh vĩnh viễn, dùng trạng thái phù hợp và xây dựng chiến lược URL riêng. Không nên giữ InStock khi người dùng không thể mua.
Nên dùng Offer hay AggregateOffer?
Dùng Offer khi có một đề nghị bán cụ thể. Dùng AggregateOffer khi một sản phẩm có nhiều đề nghị bán thực sự, chẳng hạn nhiều người bán. Không dùng AggregateOffer để mô tả giá cũ và giá mới của cùng một cửa hàng.
Sản phẩm nhiều biến thể nên dùng Product hay ProductGroup?
Nếu các lựa chọn màu, size hoặc dung lượng có SKU, giá hay tồn kho riêng, nên cân nhắc ProductGroup và các Product biến thể. Nếu biến thể chỉ mang tính hiển thị và không tạo khác biệt thương mại, có thể không cần mô hình hóa quá chi tiết.
Vì sao Rich Results Test hợp lệ nhưng Google không hiển thị giá?
Công cụ chỉ xác nhận khả năng đáp ứng yêu cầu kỹ thuật. Google vẫn có thể không hiển thị rich result do chưa thu thập lại trang, dữ liệu không khớp nội dung, trang chưa đủ tín hiệu hoặc kết quả nâng cao không phù hợp với truy vấn cụ thể.
