JSON-LD structured data cho site/blog/local business VN | Article, FAQ, Organization
JSON-LD không phải “thêm càng nhiều schema càng rank cao”. Với site/blog VN: ưu tiên Article (ngày, tác giả, publisher), FAQPage chỉ khi trang thật sự trả lời FAQ, Organization (logo + url) cho thương hiệu, LocalBusiness chỉ khi có địa chỉ/giờ mở cửa thật. Markup phải khớp nội dung hiển thị, validate bằng Rich Results Test, cú pháp JSON sạch — dùng JSON Formatter bắt lỗi trước khi deploy.
Developer freelance và team outsource Việt Nam hay nhận ticket: “Thêm schema để lên rich result.” Kết quả thường thấy trên staging: FAQ spam, Organization thiếu logo, LocalBusiness gắn cho landing SaaS không có cửa hàng, hoặc JSON lỗi trailing comma khiến cả block bị bỏ qua.
Bài này tập trung JSON-LD thực chiến cho site / blog / local business tại VN: chọn type đúng, ví dụ copy-paste được, lỗi Google hay bắt, và checklist trước khi promote.
Bài viết này giúp bạn
- Phân biệt JSON-LD với meta title/description/OGP (chúng bổ sung, không thay nhau)
- Chọn Article / FAQPage / Organization / LocalBusiness theo loại trang
- Có ví dụ schema đủ field quan trọng (ngày ISO +07:00, author, logo)
- Tránh spam FAQ và LocalBusiness giả
- Checklist validate: cú pháp → Rich Results → khớp nội dung
Structured data là gì — và không làm gì
Dữ liệu có cấu trúc (structured data) là markup nói với máy tìm kiếm: “đây là bài viết / FAQ / tổ chức / cửa hàng” theo từ vựng schema.org. Google đọc chủ yếu qua JSON-LD trong:
<script type="application/ld+json">
{ ... }
</script>
Làm được: đủ điều kiện ứng viên rich result (ngày bài, FAQ accordion trên SERP, knowledge panel cơ bản…).
Không làm được: thay thế nội dung mỏng, “hack rank” bằng schema giả, hay thay title/description/og:image.
| Lớp | Ví dụ | Ai đọc trước |
|---|---|---|
| HTML meta | title, meta description | Snippet tìm kiếm cơ bản |
| OGP | og:title, og:image | Zalo / Facebook / LinkedIn khi share |
| JSON-LD | Article, FAQPage, Organization | Google / Bing hiểu entity & rich result |
OGP và schema không thay nhau. Card Zalo xấu → sửa OGP (xem thêm OGP Preview). Rich result FAQ không hiện → kiểm FAQ thật + FAQPage, không đổ lỗi cho og:image.
Chọn schema theo loại trang (VN)
| Loại trang | Schema ưu tiên | Khi nào bỏ |
|---|---|---|
| Bài blog / tutorial | Article hoặc BlogPosting | Landing sản phẩm không phải bài viết |
| Trang FAQ / hỗ trợ | FAQPage | Blog nhét 10 câu FAQ ẩn cuối trang |
| Trang About / toàn site | Organization (+ WebSite nếu cần) | Blog cá nhân không có thương hiệu |
| Quán / clinic / shop có địa chỉ | LocalBusiness (hoặc subtype) | App SaaS / portfolio không có cửa |
| Sản phẩm ecommerce | Product + Offer (ngoài phạm vi bài này) | Blog affiliate không có giá/SKU thật |
Quy tắc vàng: một trang có thể có nhiều graph (Article + BreadcrumbList + Organization), nhưng mỗi type phải đúng sự thật. Google xử lý markup gây hiểu nhầm như spam.
Article / BlogPosting — blog tiếng Việt
Field quan trọng nhất cho blog:
headline— khớp (hoặc gần) H1 / titledatePublished/dateModified— ISO 8601, nên có offset+07:00author—Personvớiname(vàurlnếu có trang tác giả)publisher—Organization+logo(URL ảnh tuyệt đối, đủ kích thước)
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "JSON-LD structured data cho blog và local business",
"description": "Hướng dẫn Article, FAQPage, Organization cho website Việt Nam.",
"datePublished": "2026-05-31T09:00:00+07:00",
"dateModified": "2026-07-19T18:00:00+07:00",
"inLanguage": "vi-VN",
"author": {
"@type": "Person",
"name": "Nguyễn An",
"url": "https://example.vn/tac-gia/nguyen-an"
},
"publisher": {
"@type": "Organization",
"name": "Example Studio",
"logo": {
"@type": "ImageObject",
"url": "https://example.vn/logo.png",
"width": 600,
"height": 60
}
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://example.vn/blog/seo-structured-data/"
}
}
Với Astro/Next: generate từ frontmatter (pubDate, updatedDate, title) — một nguồn sự thật. Hardcode ngày trong JSON rồi quên cập nhật khi sửa bài = dateModified sai.
Lỗi Article hay gặp
- Logo thiếu hoặc relative path (
/logo.png) — cần absolutehttps://… - headline dài bất thường / lệch hoàn toàn so với H1
- author chỉ là string thay vì
Person(một số validator cảnh báo) - Staging URL lọt vào
@id/mainEntityOfPagekhi copy config production
FAQPage — chỉ khi trang thật sự là FAQ
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "JSON-LD có bắt buộc cho SEO không?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Không bắt buộc. Schema giúp đủ điều kiện rich result và làm rõ entity; nội dung và trải nghiệm trang vẫn quyết định thứ hạng."
}
},
{
"@type": "Question",
"name": "Có nên gắn FAQ schema cho mọi bài blog không?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Không. Chỉ dùng FAQPage khi câu hỏi và câu trả lời hiển thị rõ trên trang. FAQ ẩn hoặc copy lệch HTML dễ bị coi là markup gây hiểu nhầm."
}
}
]
}
Checklist trước khi bật FAQ schema:
- Mỗi
Question.namexuất hiện trên UI (accordion / heading) -
Answer.textkhông chứa nội dung khác hẳn đoạn người dùng đọc - Không nhồi 20 FAQ mỏng chỉ để “chiếm diện tích SERP”
- Trang chính là FAQ/hỗ trợ — hoặc section FAQ rõ ràng, không phải footer giả
Team agency VN hay bị client ép “thêm FAQ schema mọi landing”. Từ chối lịch sự bằng guideline Google: markup phải reflect visible content.
Organization vs LocalBusiness
Organization — thương hiệu / công ty
Dùng cho logo Knowledge Panel cơ bản, sameAs (Facebook, LinkedIn, GitHub org):
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Kawa Dev Tools",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"sameAs": [
"https://www.facebook.com/example",
"https://github.com/example"
]
}
LocalBusiness — có địa điểm thật
Quán cafe Đà Nẵng, phòng khám Q.3, shop linh kiện có giờ mở cửa:
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Cafe Thí Nghiệm",
"image": "https://cafe-example.vn/storefront.jpg",
"address": {
"@type": "PostalAddress",
"streetAddress": "12 Nguyễn Huệ",
"addressLocality": "Huế",
"addressRegion": "Thừa Thiên Huế",
"postalCode": "49000",
"addressCountry": "VN"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 16.4637,
"longitude": 107.5909
},
"telephone": "+84-234-000-0000",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "07:30",
"closes": "21:00"
}
]
}
Đừng gắn LocalBusiness cho SaaS, landing tool, hay portfolio freelancer nếu không có cửa phục vụ tại chỗ — đó là tín hiệu sai entity.
| Tình huống | Chọn | Lý do |
|---|---|---|
| Agency / studio chỉ online | Organization | Không có địa chỉ phục vụ walk-in |
| Quán ăn, clinic, shop | LocalBusiness (+ subtype) | Cần address, giờ, điện thoại |
| Blog cá nhân | Person (+ publisher Organization nhỏ) | Tránh LocalBusiness giả |
| Chi nhánh nhiều tỉnh | Organization + nhiều LocalBusiness | Mỗi địa điểm một entity |
Case study ngắn
1) Blog tech freelancer — Article đủ, FAQ thừa
Trang tutorial 1800 từ, cuối bài nhét 8 FAQ không hiển thị. Rich Results Test báo FAQ hợp lệ… vài tuần sau không còn FAQ trên SERP / bị cảnh báo. Sửa: bỏ FAQPage; giữ Article + dates + publisher logo. FAQ chỉ thêm khi section accordion thật.
2) Landing quán trà sữa — thiếu LocalBusiness, thừa Article
Team gắn Article vì “mọi trang đều là content”. Google không hiểu giờ mở cửa / địa chỉ. Sửa: LocalBusiness + PostalAddress addressCountry: VN, giờ +07 mental model khớp openingHoursSpecification. Ảnh image là ảnh cửa hàng, không phải banner stock.
3) JSON “đẹp mắt” nhưng invalid
Dev copy schema, thêm comment // todo hoặc trailing comma — JSON-LD bị parse fail, toàn bộ block bị bỏ. Bắt bằng định dạng JSON (local, không upload) trước khi commit; CI có thể JSON.parse file schema snapshot.
Quy trình validate (đừng đảo thứ tự)
- Cú pháp JSON — format + parse thành công (JSON Formatter)
- Schema fields — Schema Markup Validator / Rich Results Test (URL public hoặc code snippet)
- Khớp HTML — headline, FAQ, địa chỉ giống những gì user thấy
- Môi trường — staging
noindex; đừng test rich result production bằng URL preview có auth lệch - Sau deploy — URL Inspection trên Search Console; rich result có thể chậm hơn index thường
Checklist PR cho team 2–3 người
-
@typeđúng loại trang (không copy Article cho mọi route) -
datePublished/dateModifiedcó timezone -
publisher.logoabsolute HTTPS - FAQ chỉ khi UI có Q&A
- LocalBusiness chỉ khi có địa chỉ thật
- Không để hostname staging trong
@id - Rich Results Test: 0 lỗi critical trước merge
JSON-LD và OGP — đừng nhầm ticket
| Triệu chứng | Hướng xử lý |
|---|---|
| Share Zalo/Facebook thiếu ảnh | OGP / cache scraper — OGP Preview + debugger nền tảng |
| SERP không có ngày / FAQ | JSON-LD Article/FAQ + nội dung thật + Rich Results |
| Snippet mô tả kém | meta description + nội dung; schema description chỉ hỗ trợ |
| Staging bị index kèm schema | noindex + robots môi trường (xem bài robots.txt) — schema không thay noindex |
Liên kết liên quan
- Định dạng JSON — validate cú pháp JSON-LD trước khi nhúng
- Xem trước OGP — card mạng xã hội (lớp khác structured data)
- robots.txt ≠ noindex — kiểm soát crawl/index, không nhầm với schema