Le Duy Khuong

Chuỗi: seo-json-ld · Phần 4

Năng suất & công cụ dev

Debugging & Extending Structured Data

Validation tools, extending schemas

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:

  1. F12 → Elements
  2. Ctrl+F → search ld+json
  3. Expand <script> tag → đọc JSON
  4. Copy JSON → format bằng python3 -m json.tool hoặ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 "---"; done

Common 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.png

Error: "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 Test

Bướ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:

  1. 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.

  2. Content không match type — Thêm FAQPage schema cho page không có Q&A format → Google có thể coi là spam → giảm trust.

  3. 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).

  4. 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 -rn

Câ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 Person schema 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.

LDK

Le Duy Khuong

AI Transformation & Digital Strategy. Writing about agentic systems, engineering leadership, and building in public.