Le Duy Khuong

Chuỗi: seo-nextjs-metadata · Phần 4

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

Debugging SEO Issues

Lighthouse audit, GSC, DevTools

2026-03-207 phút đọcVI

Debugging SEO Issues — Lighthouse, GSC & DevTools

Mở đầu

Anh đã biết cách khai báo metadata, Open Graph, sitemap. Nhưng khai báo đúng trong code không đảm bảo kết quả đúng trên production. Title có thể bị Google rewrite, canonical URL có thể conflict, OG image có thể 404. Debugging SEO là kỹ năng tìm và fix những lỗi này.

Trong bối cảnh leduykhuong.com — static export deploy trên Cloudflare Pages — debugging có thêm một layer: anh không có server logs. Mọi thứ phải verify từ HTML output hoặc external tools.

Mục tiêu: Thành thạo 3 công cụ debug SEO chính: Lighthouse (audit tự động), Google Search Console (dữ liệu thực từ Google), và Chrome DevTools (inspect trực tiếp).


Lighthouse SEO Audit

Lighthouse là tool audit tích hợp trong Chrome DevTools. SEO audit kiểm tra ~15 tiêu chí:

Cách chạy

  1. Mở Chrome → Navigate tới page cần kiểm tra
  2. F12 (DevTools) → Tab "Lighthouse"
  3. Chọn "SEO" category → "Analyze page load"
  4. Đọc report — mỗi tiêu chí Pass/Fail + explanation

Các tiêu chí quan trọng

Tiêu chíKiểm tra gìLỗi phổ biến
Document has a <title>Trang có title tagTitle rỗng hoặc thiếu
Document has a meta descriptionCó meta descriptionDescription thiếu hoặc quá dài
Page has successful HTTP statusStatus 200404, redirect loops
Links have descriptive textAnchor text có ý nghĩa"Click here", "Read more"
Document uses legible font sizesFont ≥ 12px trên mobileFont nhỏ trên mobile viewport
Tap targets are sized appropriatelyTouch targets ≥ 48×48pxButtons quá nhỏ trên mobile
Page isn't blocked from indexingKhông có noindexrobots meta hoặc robots.txt block
Image elements have alt attributesẢnh có alt textẢnh trang trí thiếu alt
Document has valid hreflanghreflang tags hợp lệSai format locale, thiếu x-default
Document has valid canonicalCanonical URL accessible404, redirect, hoặc self-referencing sai

Chạy từ CLI (headless)

# Install Lighthouse CLI
npm install -g lighthouse
 
# Audit một URL
lighthouse https://leduykhuong.com/vi/blog/learning-in-public \
  --only-categories=seo \
  --output=json \
  --output-path=./seo-report.json
 
# Hoặc audit HTML file local (sau build)
npx serve out -p 3001
lighthouse http://localhost:3001/vi/blog/learning-in-public \
  --only-categories=seo --output=html

Lưu ý: Lighthouse audit local HTML khác production vì thiếu HTTPS, headers, và CDN behavior. Nhưng metadata checks (title, description, canonical) hoạt động bình thường.


Google Search Console (GSC) — Dữ liệu thực

Lighthouse là audit lý thuyết. GSC cho thấy Google thực sự thấy gì khi crawl site anh.

Coverage Report — Trang nào được index?

GSC → "Pages" (hoặc "Coverage" ở phiên bản cũ):

StatusÝ nghĩaAction
Valid (indexed)Google đã indexTốt — không cần làm gì
Valid with warningsIndex nhưng có issuesXem chi tiết, fix nếu cần
ExcludedGoogle biết nhưng KHÔNG indexKiểm tra lý do
ErrorGoogle không crawl đượcFix ngay

Excluded reasons phổ biến:

  • "Crawled - currently not indexed" — Google crawl rồi nhưng cho rằng content không đủ giá trị. Cải thiện content hoặc tăng backlinks.
  • "Duplicate without user-selected canonical" — Google tìm thấy 2+ URLs cùng content và tự chọn canonical. Check alternates.canonical trong metadata.
  • "Excluded by robots.txt" — robots.txt chặn URL này. Kiểm tra disallow rules.
  • "Alternate page with proper canonical tag" — Trang multilingual alternate, canonical trỏ đúng sang phiên bản chính. Đây là behavior mong muốn.

Performance Report — Từ khóa nào mang traffic?

GSC → "Performance":

  • Queries — Từ khóa nào người dùng search để tìm thấy site
  • Impressions — Bao nhiêu lần site xuất hiện trên kết quả tìm kiếm
  • Clicks — Bao nhiêu lần người dùng click vào
  • CTR — Click-through rate (clicks / impressions)
  • Position — Vị trí trung bình trên kết quả tìm kiếm

Actionable insight: Nếu một query có nhiều impressions nhưng CTR thấp → title và description không hấp dẫn đủ → cải thiện seoTitleseoDescription trong MDX frontmatter.

URL Inspection — Debug từng trang

GSC → nhập URL vào thanh Inspection:

  1. "URL is on Google" — Đã index ✅
  2. "Crawled - not indexed" — Google từ chối index ❌
  3. "Request Indexing" — Yêu cầu Google re-crawl (chỉ dùng sau khi fix issues)
  4. "View crawled page" — Xem HTML mà Google thực sự nhận được (quan trọng cho debugging)

Use case thực tế: Sau khi fix metadata cho một blog post, dùng "Request Indexing" để Google fetch phiên bản mới. Thường mất 1-3 ngày để reflect.


Chrome DevTools — Inspect trực tiếp

Elements tab — Xem rendered <head>

F12 → Elements → tìm <head>:

▼ <head>
    <title>Learning in Public | Le Duy Khuong</title>
    <meta name="description" content="Tại sao viết..." />
    <meta property="og:title" content="Learning in Public | Le Duy Khuong" />
    <meta property="og:image" content="https://leduykhuong.com/og-default.png" />
    <meta name="twitter:card" content="summary_large_image" />
    <link rel="canonical" href="https://leduykhuong.com/vi/blog/learning-in-public" />
    <!-- ...more meta tags... -->
  </head>

Kiểm tra:

  • Title format đúng template %s | Le Duy Khuong?
  • Description không quá 155 ký tự?
  • OG image URL absolute (bắt đầu https://)?
  • Canonical URL đúng?
  • hreflang tags đủ (vi, en, x-default)?

Network tab — Verify image loads

  1. F12 → Network → filter "Img"
  2. Tìm OG image URL
  3. Check: Status 200? Content-Type đúng (image/png, image/webp)?
  4. Nếu 404 → image path sai hoặc file chưa được deploy

Console — Structured Data errors

Google's Rich Results Test report cũng xuất hiện trong console:

# Hoặc dùng grep trên build output
grep -n 'application/ld+json' out/vi/blog/learning-in-public.html

Lỗi SEO phổ biến và cách fix

1. Title bị Google rewrite

Triệu chứng: GSC hiển thị title khác với <title> tag anh khai báo.

Nguyên nhân: Google tự rewrite title nếu thấy title quá dài (>60 ký tự), không phản ánh nội dung, hoặc trùng với title page khác.

Fix: Giữ title dưới 60 ký tự, phản ánh đúng nội dung page. Dùng seoTitle trong MDX frontmatter nếu cần title khác title.

2. Canonical URL conflict

Triệu chứng: GSC báo "Duplicate without user-selected canonical."

Nguyên nhân trên leduykhuong.com: /vi/blog/slug/en/blog/slug cùng nội dung nhưng canonical không rõ ràng.

Fix: Đảm bảo alternates.canonical khác nhau cho mỗi locale version. Code hiện tại đã xử lý:

alternates: {
  canonical: `${BASE_URL}/${locale}/blog/${slug}`, // locale-specific
  languages: {
    vi: `${BASE_URL}/vi/blog/${slug}`,
    en: `${BASE_URL}/en/blog/${slug}`,
    "x-default": `${BASE_URL}/vi/blog/${slug}`,
  },
},

3. OG image 404

Triệu chứng: Social preview không có ảnh.

Debug:

# Check image file exists in build output
ls -la out/og-default.png
 
# Check URL trong meta tag
grep 'og:image' out/vi/blog/learning-in-public.html
 
# Verify URL accessible
curl -I https://leduykhuong.com/og-default.png

Fix thường gặp: Image ở thư mục public/ nhưng path trong code thiếu / prefix, hoặc image chưa được commit.

4. Mobile usability issues

Triệu chứng: Lighthouse báo font size hoặc tap targets quá nhỏ.

Fix: Đảm bảo viewport meta tag tồn tại (Next.js tự thêm), font-size ≥ 16px cho body text, buttons ≥ 48×48px.


Workflow Debug SEO cho leduykhuong.com

Quy trình kiểm tra SEO sau mỗi deployment:

1. Build locally: npm run build
   └── Check build output: grep '<title>' out/vi/blog/*.html | head

2. Lighthouse audit (local):
   └── npx serve out -p 3001
   └── Lighthouse → SEO category

3. Deploy to Cloudflare Pages

4. Social debuggers:
   └── Facebook Debugger → Scrape Again
   └── LinkedIn Post Inspector

5. GSC (sau 1-3 ngày):
   └── URL Inspection → check indexing
   └── Coverage → check excluded pages

Thực hành

Bài tập 1: Chạy Lighthouse SEO audit

cd ACE-component/ACE-leduykhuong-site && npm run build
npx serve out -p 3001
# Mở Chrome → http://localhost:3001/vi/blog/learning-in-public
# F12 → Lighthouse → SEO → Analyze

Câu hỏi: Score bao nhiêu? Tiêu chí nào fail (nếu có)?

Bài tập 2: Inspect <head> tags

Mở DevTools → Elements → <head>:

  • Đếm số lượng <meta property="og:*"> tags
  • Tìm <link rel="canonical"> — URL có đúng không?
  • Tìm <link rel="alternate" hreflang="*"> — có đủ vi, en, x-default?

Bài tập 3: Grep build output

# All meta tags cho 1 blog post
grep -E '<meta|<title>|<link rel' out/vi/blog/learning-in-public.html | head -20
 
# So sánh 2 locale versions
diff <(grep '<title>' out/vi/blog/learning-in-public.html) \
     <(grep '<title>' out/en/blog/learning-in-public.html)

Tóm tắt

  • Lighthouse — Audit tự động 15 tiêu chí SEO, chạy từ DevTools hoặc CLI
  • Google Search Console — Dữ liệu thực: pages indexed, queries, clicks, crawl errors
  • Chrome DevTools — Inspect <head> trực tiếp, verify image loads, check structured data
  • Title rewrite — Google có thể thay đổi title; giữ ≤60 ký tự và phản ánh đúng nội dung
  • Canonical conflict — Multilingual sites cần canonical per-locale + hreflang tags
  • OG image 404 — Luôn dùng absolute URL, verify file tồn tại sau deploy

Bài tiếp theo

Kết thúc series Next.js Metadata. Series tiếp theo: JSON-LD & Structured Data — Bài 5 sẽ giới thiệu Schema.org vocabulary, cách JSON-LD hoạt động, và tại sao structured data giúp Google hiểu content tốt hơn.

LDK

Le Duy Khuong

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