2026-03-204 phút đọcVI
Sitemap Strategy cho Static Sites
Mở đầu
Bài 3 trong series Metadata đã cover cách leduykhuong.com generate sitemap. Bài này đi sâu hơn vào strategy: khi nào cần multiple sitemaps, cách tối ưu lastmod cho re-crawl, multilingual sitemap patterns, và sitemap index cho sites lớn.
Mục tiêu: Hiểu sitemap strategy beyond implementation — khi nào dùng sitemap index, hreflang trong sitemap, và monitoring sitemap health.
Sitemap Limits
| Limit | Giá trị | leduykhuong.com |
|---|---|---|
| Max URLs per sitemap | 50,000 | ~400 (2 locales × ~200 pages) |
| Max file size | 50MB (uncompressed) | ~30KB |
| Max sitemaps in index | 50,000 | 1 (chưa cần index) |
leduykhuong.com: Far below limits. 1 sitemap file đủ. Sitemap index cần khi > 50,000 URLs (ví dụ: e-commerce với millions of products).
lastmod Strategy — Trigger Re-crawl
lastmod là signal quan trọng nhất trong sitemap (Google actually dùng, unlike priority):
// Hiện tại — dùng post date
const postPages = posts.flatMap((p) => {
const date = p.date ? new Date(p.date) : new Date();
return withLocales(`/blog/${p.slug}`, {
lastModified: date,
changeFrequency: "monthly",
priority: 0.7,
});
});Vấn đề: lastmod = publish date, KHÔNG PHẢI last modified date. Nếu anh update bài (fix typo, add section), lastmod vẫn là ngày publish cũ → Google không biết content đã thay đổi.
Cải thiện:
# MDX frontmatter
---
date: "2026-01-15"
lastModified: "2026-03-20"
---// sitemap.ts — improved
const lastModified = p.lastModified
? new Date(p.lastModified)
: p.date
? new Date(p.date)
: new Date();Rule: Update lastmod CHỈ khi content thực sự thay đổi. Fake updates (update lastmod mà không đổi content) → Google phát hiện → giảm trust → ignore lastmod hoàn toàn.
Multilingual Sitemap — hreflang
leduykhuong.com có 2 locales. Sitemap hiện tại tạo separate URLs:
<url>
<loc>https://leduykhuong.com/vi/blog/learning-in-public</loc>
</url>
<url>
<loc>https://leduykhuong.com/en/blog/learning-in-public</loc>
</url>Advanced pattern: Thêm xhtml:link để khai báo relationship giữa locales:
<url>
<loc>https://leduykhuong.com/vi/blog/learning-in-public</loc>
<xhtml:link rel="alternate" hreflang="vi"
href="https://leduykhuong.com/vi/blog/learning-in-public"/>
<xhtml:link rel="alternate" hreflang="en"
href="https://leduykhuong.com/en/blog/learning-in-public"/>
<xhtml:link rel="alternate" hreflang="x-default"
href="https://leduykhuong.com/vi/blog/learning-in-public"/>
</url>Tại sao quan trọng: Google dùng hreflang để:
- Hiển thị đúng locale version cho user (Vietnamese user → vi version)
- Consolidate ranking signals (links tới en version cũng benefit vi version)
- Avoid duplicate content issues
Lưu ý: Next.js Metadata API KHÔNG tự thêm hreflang vào sitemap. Anh đã khai báo hreflang trong generateMetadata() → HTML <link rel="alternate"> tags. Sitemap hreflang là bổ sung, không bắt buộc nếu HTML tags đã có.
Static Sites — Sitemap Update Workflow
Với static export, sitemap chỉ update khi build lại:
1. Write new MDX post
2. npm run build → sitemap.xml regenerated
3. Deploy to Cloudflare Pages
4. Googlebot eventually re-fetches sitemap.xml
5. Discovers new URL → crawls → indexes
Timing: Google re-fetches sitemap theo schedule riêng (days to weeks). Muốn faster:
- GSC → Sitemaps → Resubmit sitemap.xml sau mỗi deploy
- GSC → URL Inspection → "Request Indexing" cho bài mới cụ thể
Automation Idea
# Post-deploy script
#!/bin/bash
# After Cloudflare Pages deploy
echo "Pinging Google with updated sitemap..."
curl -s "https://www.google.com/ping?sitemap=https://leduykhuong.com/sitemap.xml"Lưu ý: Google ping endpoint (/ping?sitemap=) đã bị deprecated (2023). GSC manual resubmit hoặc URL Inspection là cách chính thức còn lại.
Sitemap Health Monitoring
GSC Sitemaps Report
GSC → Sitemaps → xem status:
Sitemap URL Status URLs discovered
────────────────────────────────────────────────────────────
/sitemap.xml Success 380
Last read: 2026-03-18
Check:
- Status = "Success"? Nếu "Error" → parse issue
- URLs discovered ≈ expected? Nếu thấp → URLs bị filtered
- Last read gần đây? Nếu > 30 ngày → Google ít quan tâm sitemap
Common Issues
| Issue | Triệu chứng | Fix |
|---|---|---|
| 404 on sitemap.xml | GSC error "Couldn't fetch" | Check deployment, file tồn tại |
| Invalid XML | GSC error "Parsing error" | Validate XML, check encoding |
| URLs 404 | GSC warning "Submitted URL not found" | Remove deleted pages from sitemap |
| Too many redirects | GSC warning "Redirect" | Update URLs in sitemap to final destinations |
Khi nào cần Sitemap Index?
Sitemap index = sitemap of sitemaps:
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://leduykhuong.com/sitemap-posts.xml</loc>
<lastmod>2026-03-20</lastmod>
</sitemap>
<sitemap>
<loc>https://leduykhuong.com/sitemap-pages.xml</loc>
<lastmod>2026-03-15</lastmod>
</sitemap>
</sitemapindex>Khi nào cần:
-
50,000 URLs (limit per file)
- Muốn segment sitemaps (posts vs pages vs products)
- Different update frequencies (posts update weekly, pages monthly)
leduykhuong.com: KHÔNG cần. 400 URLs fit comfortably trong 1 file.
Thực hành
Bài tập 1: Validate sitemap
cd ACE-component/ACE-leduykhuong-site && npm run build
# Count URLs
grep -c '<loc>' out/sitemap.xml
# Check for invalid dates
grep '<lastmod>' out/sitemap.xml | grep -v '20[0-9][0-9]-'Bài tập 2: Check GSC sitemap status
GSC → Sitemaps:
- Status = Success?
- URLs discovered = expected?
- Last read date?
Bài tập 3: Compare sitemap vs indexed pages
GSC → Pages → Valid (indexed):
- Số pages indexed so với sitemap URLs?
- Pages nào trong sitemap nhưng KHÔNG indexed? Tại sao?
Tóm tắt
lastmodlà signal Google actually dùng — update chỉ khi content thực sự thay đổi- hreflang trong sitemap bổ sung cho HTML hreflang tags — helpful cho multilingual
- Static sites regenerate sitemap mỗi build — resubmit GSC sau deploy
- Sitemap index chỉ cần cho > 50,000 URLs
- Monitor sitemap health qua GSC Sitemaps report
Bài tiếp theo
Bài 19: Canonical URLs & Duplicate Content — Hiểu sâu vấn đề duplicate content cho multilingual sites, canonical URL strategy, và cách Google xử lý locale variants.