2026-03-206 phút đọcVI
Debugging & Extending Structured Data
Mở đầu
Structured data hoạt động "ẩn" — user không thấy nó trên page, Google không phản hồi ngay lập tức. Vậy làm sao biết JSON-LD đã đúng? Làm sao biết Google đã đọc? Và khi cần thêm schema type mới cho một page, quy trình như thế nào?
Bài này chia làm hai phần: debugging (validate và troubleshoot JSON-LD hiện tại) và extending (quy trình thêm schema mới cho leduykhuong.com).
Mục tiêu: Thành thạo validation tools, hiểu error messages, và biết cách thêm schema type mới theo pattern đã có.
Debugging Tools
1. Rich Results Test (Google)
URL: search.google.com/test/rich-results
Đây là tool chính thức của Google. Nhập URL hoặc paste HTML code:
Output gồm 3 phần:
- Detected items — Các schema types tìm được (BlogPosting, BreadcrumbList...)
- Errors — Fields required bị thiếu → rich results KHÔNG hiển thị
- Warnings — Fields recommended bị thiếu → rich results vẫn có thể hiển thị nhưng kém chất lượng
Ví dụ kết quả:
Detected items:
✅ Article (BlogPosting) — 0 errors, 1 warning
⚠ Missing field "dateModified" (recommended)
✅ Breadcrumb — 0 errors, 0 warnings
Lưu ý: Rich Results Test chỉ validate theo Google's interpretation — không phải toàn bộ Schema.org spec. Google support một subset nhỏ của Schema.org types cho rich results.
2. Schema Markup Validator
URL: validator.schema.org
Validate đầy đủ theo Schema.org specification (không chỉ Google). Tool này kiểm tra:
- Type có tồn tại trong Schema.org
- Properties thuộc về type đúng
- Nested types hợp lệ
- URL formats correct
Dùng tool này khi cần verify schema structure ngoài Google rich results scope.
3. Chrome DevTools — Direct Inspection
Cách nhanh nhất để check JSON-LD on a live page:
- F12 → Elements
- Ctrl+F → search
ld+json - Expand
<script>tag → đọc JSON - Copy JSON → format bằng
python3 -m json.toolhoặc online formatter
4. Build Output Grep
Cho leduykhuong.com (static export), check trực tiếp trong build output:
cd ACE-component/ACE-leduykhuong-site && npm run build
# List all JSON-LD blocks across all pages
find out -name "*.html" -exec grep -l 'ld+json' {} \;
# Count schemas per page
for f in out/vi/blog/*.html; do
count=$(grep -c 'ld+json' "$f" 2>/dev/null)
echo "$count schemas: $(basename $f)"
done | sort -rn | head -10
# Pretty-print specific page's schemas
grep -oP '(?<=ld\+json">)[^<]+' out/vi/blog/learning-in-public.html | \
while read json; do echo "$json" | python3 -m json.tool; echo "---"; doneCommon Errors và Fixes
Error: "Missing field image"
Nguyên nhân: Post không có ogImage trong frontmatter VÀ fallback /og-default.png không resolve.
Fix: Verify file public/og-default.png tồn tại:
ls -la public/og-default.pngError: "Invalid URL in field url"
Nguyên nhân: URL relative thay vì absolute. Ví dụ: /blog/slug thay vì https://leduykhuong.com/blog/slug.
Fix: Đảm bảo getCanonicalUrl() luôn return full URL:
export function getCanonicalUrl(path: string): string {
return `${SITE_CONFIG.baseUrl}${clean || "/"}`;
// ✅ Returns: https://leduykhuong.com/blog/slug
// ❌ NOT: /blog/slug
}Warning: "Missing field dateModified"
Nguyên nhân: dateModified = datePublished — Google muốn biết bài có được cập nhật hay không.
Fix (tương lai): Thêm lastModified field vào MDX frontmatter:
---
date: "2026-03-01"
lastModified: "2026-03-20"
---Rồi update getBlogPostJsonLd():
dateModified: post.lastModified || post.date,Error: "Value in field author is not valid"
Nguyên nhân: author phải là object với @type, không phải string.
// ❌ Sai
"author": "Le Duy Khuong"
// ✅ Đúng
"author": { "@type": "Person", "name": "Le Duy Khuong" }leduykhuong.com đã implement đúng — nhưng nếu tự viết schema, đây là lỗi rất phổ biến.
Extending — Thêm Schema Mới
Quy trình 5 bước, theo pattern leduykhuong.com đã dùng:
Bước 1: Xác định page type và schema type
Ví dụ: Muốn thêm schema cho Topic page (/topics/agentic-ai).
Tra Schema.org → CollectionPage phù hợp cho page liệt kê items theo category.
Bước 2: Viết helper function trong lib/seo.ts
// lib/seo.ts — new function
export function getCollectionPageJsonLd(
name: string,
description: string,
url: string,
itemCount: number
) {
return {
"@context": "https://schema.org",
"@type": "CollectionPage",
name,
description,
url,
mainEntity: {
"@type": "ItemList",
numberOfItems: itemCount,
},
};
}Convention: Function name = get{Type}JsonLd(). Return plain object. Không reference React components.
Bước 3: Inject trong page component
// app/[locale]/topics/[slug]/page.tsx
import { JsonLd } from "@/components/seo/JsonLd";
import { getCollectionPageJsonLd, getBreadcrumbJsonLd } from "@/lib/seo";
export default function TopicPage({ params }) {
const posts = getPostsByTopic(slug);
return (
<>
<JsonLd data={getCollectionPageJsonLd(
`Posts tagged: ${topicName}`,
`All articles about ${topicName}`,
`${SITE_CONFIG.baseUrl}/topics/${slug}`,
posts.length
)} />
<JsonLd data={getBreadcrumbJsonLd([
{ name: "Home", url: SITE_CONFIG.baseUrl },
{ name: "Topics", url: `${SITE_CONFIG.baseUrl}/topics` },
{ name: topicName, url: `${SITE_CONFIG.baseUrl}/topics/${slug}` },
])} />
{/* page content */}
</>
);
}Bước 4: Build và validate
npm run build
grep 'ld+json' out/vi/topics/agentic-ai.html
# → Verify CollectionPage + BreadcrumbList present
# Paste URL vào Rich Results TestBước 5: Deploy và monitor
Deploy → chờ 1-3 ngày → check GSC URL Inspection → verify Google đã đọc structured data.
Khi nào KHÔNG nên thêm schema
Không phải mọi page đều cần structured data. Skip khi:
-
Page không có rich results eligible — Google chỉ support subset nhỏ types cho rich results. Thêm schema cho unsupported type = effort thừa.
-
Content không match type — Thêm
FAQPageschema cho page không có Q&A format → Google có thể coi là spam → giảm trust. -
Duplicate information — Nếu OG tags và metadata đã đủ thông tin, JSON-LD không cần lặp lại nội dung tương tự (trừ khi muốn rich results).
-
Low-value pages — 404 page, redirect page, utility pages không cần schema.
Rule of thumb: Thêm schema khi (a) Google support rich results cho type đó, VÀ (b) page content genuinely match type definition.
Monitoring — Sau khi deploy
GSC → Enhancements
Sau khi Google crawl pages có structured data, GSC tạo reports:
- "Breadcrumb" — Hiển thị valid/invalid breadcrumb schemas
- "Articles" — Hiển thị valid/invalid article schemas
- "Sitelinks Searchbox" — Nếu WebSite+SearchAction valid
Reports cập nhật hàng tuần. Check weekly.
Search Results — Manual check
Search site:leduykhuong.com trên Google → kiểm tra:
- Blog posts có hiển thị date trong snippet?
- Breadcrumbs xuất hiện thay vì full URL?
- Sitelinks Searchbox xuất hiện cho brand query?
Thực hành
Bài tập 1: Validate full site
cd ACE-component/ACE-leduykhuong-site && npm run build
# Extract all unique schema types across the site
grep -rohP '"@type":"[^"]+' out/**/*.html | sort | uniq -c | sort -rnCâu hỏi: Site có bao nhiêu unique schema types? Type nào xuất hiện nhiều nhất?
Bài tập 2: Rich Results Test
Chọn 1 blog post URL → nhập vào Rich Results Test:
- Có bao nhiêu detected items?
- Có errors hay warnings không?
- BlogPosting eligible cho rich result type nào?
Bài tập 3: Sketch schema mới
Thiết kế JSON-LD cho About page nếu muốn thêm ProfilePage schema:
- Cần những fields nào?
- Relationship với
Personschema hiện tại? - Viết helper function skeleton
Tóm tắt
- Rich Results Test — Tool chính thức Google, validate theo Google's rules (không phải full Schema.org)
- Schema Markup Validator — Full Schema.org spec validation
- Build output grep — Fastest check cho static export sites
- Common errors: missing image, relative URLs, author as string, missing dateModified
- Extending pattern: helper function →
<JsonLd>component → build → validate → deploy - Don't over-schema — Chỉ thêm khi Google support rich results VÀ content match type
Bài tiếp theo
Kết thúc series JSON-LD & Structured Data. Series tiếp theo: Google Analytics 4 — Bài 9 sẽ giới thiệu GA4 architecture, sự khác biệt với Universal Analytics, và data model event-based.