Bài 9 · Vận dụng · 26 phút
JSON-LD: dữ liệu có cấu trúc
Biên soạn bởi Nguyễn Anh Tuấn
Structured data với JSON-LD: khai báo Product, NewsArticle, FAQPage, Restaurant… theo schema.org để Google hiện rich result (sao, giá, hỏi đáp). Thư viện công thức theo từng loại hình kinh doanh.
Ở bài HTML cho SEO & metadata, mèo con đã gặp structured data (JSON-LD) ở mức "biết nó tồn tại". Bài này ta đi sâu: viết được JSON-LD cho trang của mình.
Semantic HTML giúp Google đoán nội dung: thấy article + time thì đoán đây là bài viết có ngày đăng. JSON-LD thì khai báo thẳng, không cần đoán: "đây là sản phẩm tên X, giá 250.000đ, 4,8 sao, còn hàng". Khi đã chắc chắn như vậy, Google có thể hiện một rich result - kết quả giàu thông tin hơn:
- ▸Structured data = dữ liệu có cấu trúc, khai báo nội dung trang theo bộ từ vựng schema.org.
- ▸JSON-LD là cách viết structured data phổ biến nhất - một khối JSON trong thẻ script.
- ▸Phần thưởng là rich result: sao đánh giá, giá, hỏi đáp, công thức… hiện ngay trên Google.
JSON-LD nằm trong một thẻ <script type="application/ld+json"> và bên trong là một object JSON. Hai khoá đặc biệt luôn có: @context (bộ từ vựng - gần như luôn là https://schema.org) và @type (đây là loại gì). Còn lại là các thuộc tính của loại đó.
course.html · chính meohamhoc.vn dùng kiểu khai báo này cho mỗi khoá (xem src/lib/seo.ts)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Course",
"name": "HTML: cấu trúc & semantic",
"description": "Học HTML từ đầu và viết semantic HTML đúng chuẩn.",
"provider": {
"@type": "Organization",
"name": "Mèo Ham Học",
"url": "https://meohamhoc.vn"
}
}
</script> Đọc từ trên xuống: đây là một Course (khoá học), tên là…, mô tả là…, do một Organization tên "Mèo Ham Học" cung cấp. Thuộc tính có thể lồng nhau: provider lại là một object có @type riêng.
Trung thực
Loại sinh lời rõ nhất cho một web bán hàng là Product. Hai phần đắt giá: offers (một Offer chứa giá và tình trạng còn hàng) và aggregateRating (điểm trung bình + số lượt đánh giá). Đây chính là thứ dựng nên sao và giá ở hình trên.
product.html · gắn vào trang chi tiết sản phẩm (vd trang bạn đã dựng ở dự án trang bán hàng)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Bàn cào cho mèo",
"image": "https://meohamhoc.vn/shop/ban-cao.png",
"description": "Bàn cào gỗ chắc chắn cho mèo con mài móng.",
"brand": { "@type": "Brand", "name": "Mèo Shop" },
"offers": {
"@type": "Offer",
"price": "250000",
"priceCurrency": "VND",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "256"
}
}
</script> - ▸Product cần ít nhất name; muốn hiện giá thì thêm offers (price + priceCurrency).
- ▸availability dùng URL chuẩn schema.org: InStock (còn hàng), OutOfStock (hết hàng).
- ▸aggregateRating chỉ dùng khi có đánh giá THẬT trên trang - đừng bịa sao.
Nối với dự án trang bán hàng
Trang bài báo dùng NewsArticle (hoặc Article cho bài thường). Nó khai báo tựa, ảnh, ngày đăng, tác giả và đơn vị xuất bản - đúng những gì semantic header/time đã gợi, nay nói thẳng cho máy:
article.html · gắn vào trang bài viết (vd dự án trang tin tức)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "NewsArticle",
"headline": "Mèo con học HTML trong một tuần",
"image": "https://meohamhoc.vn/tin/meo-hoc-html.png",
"datePublished": "2026-06-30T08:00:00+07:00",
"author": { "@type": "Person", "name": "Mèo Biên Tập" },
"publisher": {
"@type": "Organization",
"name": "Mèo Ham Học",
"logo": { "@type": "ImageObject", "url": "https://meohamhoc.vn/logo.png" }
}
}
</script> Một loại đi kèm rất hữu ích cho mọi trang con là BreadcrumbList - đường dẫn phân cấp. Nó giúp Google hiện đường dẫn đẹp (Trang chủ › Tin tức › Bài) thay cho URL trần:
breadcrumb.html · đường dẫn phân cấp cho một trang con
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Trang chủ", "item": "https://meohamhoc.vn" },
{ "@type": "ListItem", "position": 2, "name": "Tin tức", "item": "https://meohamhoc.vn/tin" },
{ "@type": "ListItem", "position": 3, "name": "Mèo con học HTML" }
]
}
</script> Nối với dự án trang tin tức
Mỗi loại hình kinh doanh có một @type riêng, mở một kiểu rich result riêng. Hai ví dụ đầy đủ thường gặp - nhà hàng/cửa hàng và trang hỏi đáp:
restaurant.html · quán ăn / cửa hàng địa phương (Restaurant là một dạng LocalBusiness)
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Restaurant",
"name": "Quán Cá Mèo",
"servesCuisine": "Hải sản",
"priceRange": "$$",
"telephone": "+84-28-1234-5678",
"address": {
"@type": "PostalAddress",
"streetAddress": "12 Đường Cá",
"addressLocality": "TP.HCM",
"addressCountry": "VN"
}
}
</script> faq.html · khối hỏi đáp - Google có thể hiện ngay câu hỏi/đáp dưới kết quả
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Giao hàng mất bao lâu?",
"acceptedAnswer": { "@type": "Answer", "text": "Thường 2-3 ngày trong nội thành." }
},
{
"@type": "Question",
"name": "Có đổi trả không?",
"acceptedAnswer": { "@type": "Answer", "text": "Đổi trả trong 7 ngày nếu còn nguyên hộp." }
}
]
}
</script> Cùng một khuôn, chỉ đổi @type và thuộc tính. Vài loại phổ biến khác:
- ▸LocalBusiness: cửa hàng/dịch vụ địa phương - address, telephone, openingHours → hiện địa chỉ, giờ mở cửa.
- ▸JobPosting: tin tuyển dụng - title, hiringOrganization, baseSalary, jobLocation → lên Google Jobs.
- ▸Recipe: công thức nấu ăn - recipeIngredient, recipeInstructions, cookTime → thẻ công thức có ảnh, thời gian.
- ▸Event: sự kiện - name, startDate, location → hiện ngày giờ, địa điểm trong kết quả.
Mẹo chọn @type
Một khối JSON-LD sai một dấu phẩy là hỏng cả khối. Đừng tin nó đúng vì "trông có vẻ đúng" - hãy kiểm bằng công cụ. Google có Rich Results Test (search.google.com/test/rich-results): dán URL hoặc dán thẳng đoạn HTML, nó báo loại nào hợp lệ, thiếu thuộc tính gì, sai ở đâu.
- ▸Rich Results Test: kiểm trang có đủ điều kiện rich result chưa, báo lỗi cụ thể.
- ▸Schema Markup Validator (validator.schema.org): kiểm cú pháp schema.org tổng quát.
- ▸Lỗi hay gặp: thiếu thuộc tính bắt buộc, sai định dạng ngày, dữ liệu không khớp nội dung trang.
Trung thực
Đồ nghề mang về
Bước tiếp theo
Câu hỏi thường gặp
meta description là một câu mô tả cho NGƯỜI đọc trên kết quả tìm kiếm. JSON-LD là dữ liệu cho MÁY đọc: nó khai báo rõ "đây là sản phẩm giá 250.000đ, 4,8 sao" để Google có thể hiện thêm sao, giá, tình trạng còn hàng (rich result). Một cái là lời mô tả, một cái là dữ liệu có cấu trúc.
Không. Google TỰ QUYẾT có hiện rich result hay không. JSON-LD đúng cú pháp là điều kiện cần, nhưng dữ liệu phải KHỚP với nội dung hiện trên trang, trang phải đủ chất lượng, và đúng loại được Google hỗ trợ. Khai man (sao ảo, giá sai) có thể bị phạt.
Trong một thẻ <script type="application/ld+json">. Đặt trong head hay cuối body đều được; một trang có thể có nhiều khối (vd Product + BreadcrumbList + FAQPage). Vì là JSON nên nó không phụ thuộc vị trí như thẻ hiển thị.
Không. Nó nằm trong thẻ script, người dùng không thấy gì khác trên trang. Chính vì ẩn nên nó phải KHỚP nội dung thật: giá trong JSON-LD phải đúng giá trên trang, sao phải là đánh giá có thật. Đây là dữ liệu cho máy, không phải chỗ để nói khác đi.
Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.
Trả lời vài câu để chắc rằng em đã nắm bài.
Structured data (JSON-LD) trong trang chủ yếu để làm gì?
- 1
Product cho trang shop
Viết khối JSON-LD Product cho một sản phẩm của mèo con (vd món đã dựng ở dự án trang bán hàng): có name, image, description và offers (price, priceCurrency "VND", availability).
✅ Hoàn thành khi: Có <script type="application/ld+json"> với "@type":"Product" và một Offer đủ price + priceCurrency + availability.
- 2
Thêm sao đánh giá
Bổ sung aggregateRating vào Product ở trên: ratingValue và reviewCount.
✅ Hoàn thành khi: Product có thuộc tính aggregateRating với "@type":"AggregateRating", ratingValue và reviewCount.
- 3
NewsArticle cho bài viết
Viết JSON-LD NewsArticle cho một bài (vd trang tin tức đã dựng): headline, image, datePublished, author và publisher.
✅ Hoàn thành khi: Có "@type":"NewsArticle" với headline, datePublished (định dạng ISO), author và publisher.
- 4
FAQPage cho trang shop
Viết JSON-LD FAQPage với 2 câu hỏi - đáp thường gặp (vd giao hàng, đổi trả).
✅ Hoàn thành khi: Có "@type":"FAQPage" với mainEntity gồm 2 Question, mỗi Question có acceptedAnswer.
- 5
BreadcrumbList 3 cấp
Viết JSON-LD BreadcrumbList cho đường dẫn Trang chủ › Danh mục › Trang hiện tại.
✅ Hoàn thành khi: Có "@type":"BreadcrumbList" với 3 ListItem, mỗi cái có position và name (item cho 2 cấp đầu).
- 6
Kiểm chứng bằng công cụ
Dán một khối JSON-LD ở trên vào Google Rich Results Test (search.google.com/test/rich-results), sửa cho tới khi không còn lỗi. Viết 1-2 câu mèo con học được gì từ báo lỗi.
✅ Hoàn thành khi: Công cụ báo khối JSON-LD hợp lệ (0 lỗi), kèm 1-2 câu ghi lại điều rút ra.