Tấn Phát Digital — Bài viết được biên dịch, phân tích và Việt hóa từ tài liệu chính thức "Developer's guide to Search" của Google Search Central. Đây là cẩm nang bắt buộc cho mọi lập trình viên web, full-stack developer, frontend engineer muốn xây dựng website Google-friendly từ những dòng code đầu tiên.
Tại sao Developer cần hiểu SEO?
Có một sự thật phũ phàng mà nhiều agency Việt Nam phải đối mặt:
Sau khi nhận bàn giao website từ developer, đội SEO phát hiện 70% lỗi không thể sửa được nếu không refactor code.
Tại sao? Vì SEO không phải là một tầng "thêm vào" sau khi website xong — SEO phải được tích hợp ngay từ bước architect. Một website React SPA không có Server-Side Rendering, một trang sản phẩm load nội dung qua JavaScript fetch, một URL /page?id=12345... — tất cả đều là quyết định kỹ thuật ảnh hưởng trực tiếp đến khả năng SEO.
Google hiểu điều này, nên họ có riêng một Developer's Guide dành cho lập trình viên. Bài viết này sẽ phân tích chi tiết từng phần, kèm code thực tế và ví dụ áp dụng cho stack hiện đại (React, Next.js, Vue, Nuxt, v.v.).
Bài viết này dành cho:
Frontend Developer / Full-stack Developer
Tech Lead / Solution Architect
Product Owner cần hiểu rõ yêu cầu kỹ thuật SEO
Agency Web Development muốn deliver sản phẩm chất lượng cao
Marketing Team cần "nói chuyện" với Dev Team về SEO
Phần 1: Tư duy nền tảng — Website "Search-friendly" là gì?
Google mở đầu hướng dẫn bằng một thông điệp đơn giản nhưng quan trọng:
"Làm cho nội dung của bạn thân thiện với tìm kiếm rất quan trọng, vì đó là cách bạn có được nhiều người dùng phù hợp xem nội dung. Đây gọi là SEO — và nếu Google Search gặp khó khăn trong việc hiểu trang của bạn, có khả năng bạn đang bỏ lỡ một nguồn traffic quan trọng."
4 trụ cột của website hiện đại theo Google
Ngoài các yêu cầu SEO cụ thể, Google yêu cầu website phải đáp ứng 4 yêu cầu nền tảng:
Trụ cột | Ý nghĩa | Tham chiếu |
|---|---|---|
Secure | An toàn (HTTPS, không vulnerabilities) | web.dev/secure |
Fast | Tốc độ tốt (Core Web Vitals) | web.dev/fast |
Accessible | Truy cập được cho mọi người (WCAG) | web.dev/accessible |
Mobile-first | Hoạt động tốt trên mọi thiết bị | Google docs |
Đây không phải là "nice-to-have" — đây là yêu cầu cơ bản. Một website thiếu một trong 4 trụ cột này sẽ gặp khó khăn lớn về SEO, bất kể nội dung tốt đến đâu.
Phần 2: Phát hiện Google "nhìn" website của bạn như thế nào
Đây là bước đầu tiên và quan trọng nhất — vì Google không phải lúc nào cũng thấy những gì bạn thấy trong browser.
2.1. Câu chuyện kinh điển: "User view" vs "Google view"
Google đưa ra một ví dụ minh họa rất rõ ràng:
User view: Một trang về mèo (Cute cat content chronicles) — user thấy 6 hình ảnh mèo dễ thương.
Google view: Cùng trang đó, nhưng Google chỉ thấy icon loading — không thấy hình ảnh nào.
Nguyên nhân: Trang dùng một feature JavaScript không được Google support.
2.2. Đây là vấn đề phổ biến đến mức nào?
Tấn Phát Digital ước tính: 80% website Việt Nam dùng JavaScript framework hiện đại đều có lỗi tương tự ở mức độ nào đó. Lý do:
Single Page Application (SPA) không có SSR
Nội dung load lazy bằng
fetch()sau khi trang loadRouting client-side không tạo URL thật
Dùng third-party widgets không SEO-friendly
2.3. Công cụ kiểm tra: URL Inspection Tool
Bước 1: Vào Google Search Console
Bước 2: Verify website của bạn (nếu chưa)
Bước 3: Paste URL cần kiểm tra vào ô URL Inspection ở đầu trang
Bước 4: Click "Test live URL" (Kiểm tra URL trực tiếp)
Bước 5: Sau khi xong, click "View tested page" → tab "Screenshot"
→ Đây chính là cách Google "nhìn" trang của bạn. So sánh với những gì user thấy.
2.4. Công cụ thay thế: Rich Results Test
Nếu muốn nhanh hơn (không cần verify Search Console), dùng Rich Results Test:
Nhập URL
Xem screenshot Googlebot rendered
Kiểm tra HTML đã render
Phát hiện structured data
Mẹo từ Tấn Phát Digital: Sau MỖI lần deploy major change, hãy chạy URL Inspection cho các trang quan trọng. Nhiều lỗi chỉ phát hiện ra ở đây.
Phần 3: Kiểm tra Links — Đường dẫn cho Googlebot
Google nhấn mạnh:
"Googlebot điều hướng từ URL này sang URL khác bằng cách fetch và parse các link, sitemap, và redirect. Googlebot xem mỗi URL như là URL đầu tiên và duy nhất mà nó từng thấy từ website của bạn."
Điều này có nghĩa: Mọi trang quan trọng đều PHẢI có một con đường (link) dẫn đến nó.
3.1. Dùng thẻ <a> mà Google có thể crawl
Đây là yêu cầu CƠ BẢN nhưng nhiều developer Việt vẫn vi phạm.
✅ Đúng — Crawlable:
<!-- Link tiêu chuẩn -->
<a href="/san-pham/ao-thun">Áo thun</a>
<!-- Link với URL đầy đủ -->
<a href="https://shop.com/san-pham/ao-thun">Áo thun</a>
<!-- Link tương đối -->
<a href="../danh-muc/ao">Quay lại danh mục</a>
❌ Sai — KHÔNG crawlable:
<!-- onclick navigation -->
<span onclick="window.location='/san-pham'">Sản phẩm</span>
<!-- Button có sự kiện JS -->
<button onclick="navigate('/san-pham')">Xem</button>
<!-- a tag không có href -->
<a onclick="goToProduct()">Sản phẩm</a>
<!-- href javascript: -->
<a href="javascript:void(0)" onclick="loadPage()">Sản phẩm</a>
<!-- Div làm link -->
<div class="link" data-href="/san-pham">Sản phẩm</div>
3.2. Quy tắc với React Router / Vue Router
Đây là vấn đề cực kỳ phổ biến trong các dự án SPA.
❌ Sai (mặc dù JS-routing hoạt động):
// React - KHÔNG có href thật
<div onClick={() => navigate('/about')}>About</div>
✅ Đúng:
// React Router
<Link to="/about">About</Link>
// → Render thành: <a href="/about">About</a>
// Next.js
import Link from 'next/link';
<Link href="/about">About</Link>
// Vue Router
<router-link to="/about">About</router-link>
// → Render thành: <a href="/about">About</a>
Quy tắc vàng: Luôn dùng component Link chính thức của framework — nó render ra thẻ <a href> đúng chuẩn.
3.3. Mọi trang phải có path đến nó
Google yêu cầu rõ ràng:
"Đảm bảo mọi trang trên site có thể được tiếp cận bằng một link từ một trang findable khác."
Điều này nghĩa là:
Không có "orphan pages" (trang mồ côi — không có link nội bộ trỏ đến)
Mọi sản phẩm phải link được từ danh mục
Mọi bài blog phải link được từ trang chủ blog
Mọi landing page phải có ít nhất 1 link nội bộ
3.4. Anchor text phải có ý nghĩa
<!-- Tốt -->
<a href="/seo-co-ban">Hướng dẫn SEO cơ bản</a>
<!-- Tốt cho hình ảnh -->
<a href="/san-pham/ao-thun">
<img src="ao-thun.jpg" alt="Áo thun nam cotton 100%">
</a>
<!-- Xấu -->
<a href="/seo-co-ban">Click here</a>
<a href="/seo-co-ban">Đọc thêm</a>
<a href="/san-pham/ao-thun">
<img src="ao-thun.jpg" alt=""> <!-- alt rỗng -->
</a>
3.5. Sitemap — Bản đồ cho Googlebot
Google khuyến nghị build và submit sitemap vì:
Giúp Googlebot crawl thông minh hơn
Cung cấp metadata (lastmod, priority)
Khai báo mối quan hệ giữa các trang
Khai báo video, image, news content
Cấu trúc XML sitemap cơ bản:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<lastmod>2026-05-15</lastmod>
</url>
<url>
<loc>https://example.com/san-pham</loc>
<lastmod>2026-05-10</lastmod>
</url>
</urlset>
Cho Next.js: Dùng package next-sitemap Cho Nuxt: Dùng module @nuxtjs/sitemap Cho WordPress: Plugin Yoast SEO / Rank Math tự tạo
3.6. SPA với một HTML page — Đặc biệt chú ý
Nếu app của bạn là Single Page Application với chỉ một file HTML, Google yêu cầu rõ:
"Đảm bảo mỗi màn hình hoặc mỗi mảnh nội dung cá nhân có một URL."
Điều này nghĩa là:
❌ Không được: https://app.com/#/products (hash-based routing chỉ)
❌ Không được: Toàn bộ app chỉ là https://app.com/ với nội dung load động
✅ Phải có: URL thật cho mỗi state:
https://app.com/productshttps://app.com/products/1https://app.com/about
→ Dùng History API của browser (pushState) hoặc framework router.
Phần 4: JavaScript — "Con dao hai lưỡi" của SEO hiện đại
Đây là phần phức tạp nhất nhưng quan trọng nhất với developer hiện đại.
4.1. Sự thật về Google và JavaScript
Tin tốt: Google CÓ THỂ run JavaScript khi crawl.
Tin không tốt: Google không xử lý JS như browser thông thường, có nhiều giới hạn và khác biệt cần lưu ý:
Crawl 2 giai đoạn: Initial crawl (HTML) → Rendering queue → Final index
Có thể bị delay đến vài ngày giữa crawl HTML và render JS
Không support tất cả Web APIs (ví dụ: WebSocket, WebGL, một số API mới)
Không tương tác (không click, không scroll, không hover)
Timeout nếu render quá lâu
Không state persistence giữa các page load
4.2. 4 chiến lược render cho SPA — So sánh
Tùy theo dự án, chọn chiến lược phù hợp:
Chiến lược | Mô tả | SEO | Performance | Use case |
|---|---|---|---|---|
CSR (Client-Side Rendering) | Browser render hoàn toàn | ⚠️ Rủi ro | ❌ Slow first load | Web app nội bộ, không cần SEO |
SSR (Server-Side Rendering) | Server render mỗi request | ✅ Tốt | ⚠️ Phụ thuộc server | Site có content động, cần SEO |
SSG (Static Site Generation) | Build time render | ✅ Tốt nhất | ✅ Cực nhanh | Blog, marketing site, docs |
ISR (Incremental Static Regeneration) | SSG + revalidate | ✅ Tốt | ✅ Nhanh | E-commerce vừa và lớn |
Khuyến nghị từ Tấn Phát Digital:
Blog, website giới thiệu: SSG với Next.js / Nuxt / Astro / Hugo
E-commerce: SSR hoặc ISR với Next.js / Nuxt
Web app phức tạp: SSR cho các trang public, CSR cho dashboard
Tin tức: SSR với cache aggressive
4.3. Code-splitting và Lazy loading — Cẩn thận
❌ Không nên lazy load các nội dung quan trọng (above-the-fold):
// Title trang lazy load? KHÔNG được!
const PageTitle = lazy(() => import('./PageTitle'));
✅ Nên lazy load các nội dung không quan trọng (below-the-fold):
// Comments section, related posts...
const Comments = lazy(() => import('./Comments'));
4.4. Hydration mismatch — Lỗi phổ biến
Nếu dùng SSR và nội dung server-render khác với client-render, sẽ bị hydration mismatch:
// ❌ Sai - render khác giữa server và client
function Component() {
const isClient = typeof window !== 'undefined';
return <div>{isClient ? 'Client' : 'Server'}</div>;
}
// ✅ Đúng - dùng useEffect
function Component() {
const [isClient, setIsClient] = useState(false);
useEffect(() => setIsClient(true), []);
return <div>{isClient ? 'Client' : 'Server'}</div>;
}
Phần 5: Thông báo cho Google khi nội dung thay đổi
Google đưa ra 2 cách chính:
5.1. Submit Sitemap
Cách hiệu quả nhất cho website có nhiều trang thay đổi:
Bước 1: Tự động generate sitemap khi có thay đổi nội dung
Bước 2: Cập nhật <lastmod> chính xác (KHÔNG gian lận — Google biết)
Bước 3: Submit qua Search Console hoặc ping endpoint
Bước 4: Khai báo trong robots.txt:
Sitemap: https://example.com/sitemap.xml
5.2. Yêu cầu Google recrawl URL
Cho từng URL quan trọng vừa cập nhật:
Bước 1: Vào Search Console → URL Inspection
Bước 2: Nhập URL cần recrawl
Bước 3: Click "Request indexing"
Lưu ý: Có giới hạn số request/ngày. Chỉ dùng cho URL thực sự quan trọng vừa update.
5.3. Khi vẫn không index được — Kiểm tra server logs
Google đưa ra lời khuyên:
"Nếu bạn vẫn gặp khó khăn trong việc index trang, hãy kiểm tra server logs để tìm lỗi."
Cách kiểm tra:
# Apache
grep "Googlebot" /var/log/apache2/access.log | tail -100
# Nginx
grep "Googlebot" /var/log/nginx/access.log | tail -100
# Tìm lỗi 5xx khi Googlebot crawl
grep "Googlebot" /var/log/nginx/access.log | grep " 5[0-9][0-9] "
# Đếm crawl theo status code
grep "Googlebot" /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c
Các lỗi thường gặp:
5xx errors: Server quá tải, code crash
Timeout: Response quá chậm
403 Forbidden: Vô tình block Googlebot
Redirect loop: Vòng lặp redirect
Phần 6: Đừng quên — Text trên trang vẫn là vua
Đây là phần Google đặc biệt nhấn mạnh, và nhiều developer hiện đại bỏ quên.
6.1. Google chỉ "thấy" được text
Google nói rất rõ:
"Googlebot chỉ có thể tìm thấy nội dung hiển thị dưới dạng văn bản. Ví dụ: text trong video là vô hình với Googlebot."
Điều này nghĩa là:
❌ Google KHÔNG thấy:
Text trong video (chưa caption)
Text trong hình ảnh (chưa OCR đầy đủ)
Text trong canvas
Text load qua plugin
Text chỉ render khi tương tác (hover, click)
✅ Google THẤY:
Text trong DOM (HTML)
Alt text của hình ảnh
Caption/subtitle của video
Text trong PDF
6.2. Visual content phải có text version
Ví dụ Google đưa ra:
❌ Suboptimal: Trang danh mục sản phẩm có danh sách hình ảnh áo nhưng KHÔNG có text mô tả từng hình.
✅ Tốt: Trang danh mục có hình ảnh kèm theo text mô tả (tên sản phẩm, giá, mô tả ngắn).
Code minh họa:
<!-- Xấu -->
<div class="products">
<img src="ao1.jpg">
<img src="ao2.jpg">
<img src="ao3.jpg">
</div>
<!-- Tốt -->
<div class="products">
<article>
<a href="/ao-1">
<img src="ao1.jpg" alt="Áo thun nam cotton trắng">
<h3>Áo thun nam cotton trắng</h3>
<p>Chất liệu cotton 100%, form regular</p>
<span class="price">299.000đ</span>
</a>
</article>
<!-- ... -->
</div>
6.3. Mọi trang phải có Title và Meta Description độc đáo
Google yêu cầu:
"Đảm bảo mọi trang có một title mô tả và meta description. Title và meta description độc đáo giúp Google hiển thị các trang của bạn liên quan đến user như thế nào, từ đó có thể tăng traffic."
Cho Next.js:
// app/products/[id]/page.tsx
export async function generateMetadata({ params }) {
const product = await getProduct(params.id);
return {
title: `${product.name} - Mua online giá tốt | Shop XYZ`,
description: product.shortDescription.slice(0, 155),
};
}
Cho Nuxt 3:
<script setup>
const route = useRoute();
const { data: product } = await useFetch(`/api/products/${route.params.id}`);
useSeoMeta({
title: `${product.value.name} - Mua online giá tốt | Shop XYZ`,
description: product.value.shortDescription.slice(0, 155),
});
</script>
Quy tắc title và description:
Yếu tố | Độ dài tối ưu | Lưu ý |
|---|---|---|
Title | 50-60 ký tự | Độc đáo, có từ khóa chính, mô tả nội dung |
Description | 150-160 ký tự | Tóm tắt nội dung, có CTA, dùng để tăng CTR |
6.4. Dùng Semantic HTML
Google nhấn mạnh:
"Google index HTML, PDF content, hình ảnh và video, nhưng không index nội dung yêu cầu plugin (như Java hay Silverlight) hoặc nội dung được render trong canvas."
Semantic HTML đúng chuẩn:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>Tên trang</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="/">Trang chủ</a></li>
<li><a href="/about">Giới thiệu</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Tiêu đề chính</h1>
<p>Nội dung mở đầu...</p>
<section>
<h2>Phần 1</h2>
<p>Nội dung phần 1...</p>
</section>
<section>
<h2>Phần 2</h2>
<p>Nội dung phần 2...</p>
</section>
</article>
<aside>
<h3>Bài viết liên quan</h3>
<ul>
<li><a href="/post-1">Bài 1</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2026 Tấn Phát Digital</p>
</footer>
</body>
</html>
Các thẻ semantic quan trọng:
<header>,<nav>,<main>,<article>,<section>,<aside>,<footer><h1>(chỉ 1 cái mỗi trang),<h2>,<h3>, ...<p>cho đoạn văn<ul>,<ol>,<li>cho danh sách<figure>,<figcaption>cho hình ảnh + chú thích<time>cho ngày tháng<address>cho thông tin liên hệ
6.5. Text content phải có trong DOM
Google đưa ra cảnh báo cực kỳ quan trọng:
"Nội dung được thêm qua CSS
contentproperty không phải là một phần của DOM và Google Search hiện tại bỏ qua nó."
❌ Google KHÔNG index nội dung này:
/* Text trong CSS - Google không thấy */
.warning::before {
content: "Cảnh báo: Sản phẩm có chứa gluten";
}
<div class="warning"></div>
✅ Đúng — text trong DOM:
<div class="warning">
<span class="icon" aria-hidden="true"></span>
Cảnh báo: Sản phẩm có chứa gluten
</div>
Quy tắc: CSS content chỉ dùng cho nội dung trang trí (icon, dấu hiệu visual), KHÔNG dùng cho text có ý nghĩa SEO.
Phần 7: Quản lý nhiều phiên bản nội dung
Google không tự động biết bạn có nhiều phiên bản của site:
Mobile và desktop
Phiên bản quốc tế (tiếng Anh, tiếng Việt, tiếng Nhật...)
Phiên bản AMP
Print version
7.1. Consolidate Duplicate URLs
Khi có nhiều URL trỏ đến cùng nội dung, dùng canonical:
<!-- Trên trang https://example.com/san-pham/ao?color=red -->
<link rel="canonical" href="https://example.com/san-pham/ao">
Ưu tiên canonical:
URL chính của sản phẩm/bài viết
Phiên bản HTTPS (không HTTP)
Phiên bản www (hoặc non-www) — chọn 1, áp dụng nhất quán
URL ngắn gọn, sạch (không tracking parameter)
7.2. Localized Versions — Hreflang
Cho website đa ngôn ngữ:
<!-- Trong <head> -->
<link rel="alternate" hreflang="vi" href="https://example.com/vi/">
<link rel="alternate" hreflang="en" href="https://example.com/en/">
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="x-default" href="https://example.com/">
Lưu ý:
Phải có return tag (mỗi trang đều khai báo về các trang khác và cả chính nó)
Mã ngôn ngữ theo chuẩn ISO 639-1 (vi, en, ja, ko...)
Có thể thêm region:
en-US,en-GB,zh-TWx-defaultcho phiên bản mặc định khi không match locale nào
7.3. AMP Pages — Liên kết với phiên bản chính
Nếu bạn có AMP version:
<!-- Trên trang chính: https://example.com/article -->
<link rel="amphtml" href="https://example.com/amp/article">
<!-- Trên trang AMP: https://example.com/amp/article -->
<link rel="canonical" href="https://example.com/article">
Phần 8: Kiểm soát Google "thấy" gì — Block content đúng cách
Google liệt kê 3 cách chính để block, mỗi cách có công dụng khác nhau:
8.1. Block hoàn toàn — Yêu cầu login / password
Khi nào dùng: Nội dung thực sự nhạy cảm, dữ liệu cá nhân, nội dung trả phí
Cách thực hiện:
# Nginx - Basic Auth
location /admin {
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Hoặc trong app: middleware xác thực, return 401/403 nếu chưa đăng nhập.
8.2. Block crawling — robots.txt
Khi nào dùng: Không muốn Google tốn budget crawl các trang không cần thiết
# robots.txt
User-agent: *
Disallow: /admin/
Disallow: /api/
Disallow: /search?q=
Disallow: /cart/
Disallow: /checkout/
# Cho phép Googlebot crawl Google Ads tracking
User-agent: Mediapartners-Google
Allow: /
Sitemap: https://example.com/sitemap.xml
⚠️ CẢNH BÁO QUAN TRỌNG từ Google:
"robots.txt KHÔNG phải là cơ chế để giữ một trang web ra khỏi Google. Để giữ trang ra khỏi Google, hãy dùng
noindexrobots rules hoặc password-protect trang của bạn."
Đây là sai lầm phổ biến nhất! Trang bị block bởi robots.txt VẪN có thể xuất hiện trong Google (chỉ là Google không biết nội dung gì bên trong).
8.3. Block indexing — Cho phép crawl nhưng không index
Khi nào dùng: Để Google đọc trang (vì có link bên trong), nhưng không hiển thị trang đó trong kết quả
Meta tag noindex:
<!-- Trong <head> -->
<meta name="robots" content="noindex">
<!-- Hoặc cụ thể cho Google -->
<meta name="googlebot" content="noindex">
HTTP header X-Robots-Tag (cho file không phải HTML):
X-Robots-Tag: noindex
8.4. KẾT HỢP các rule — Cẩn thận!
Google cảnh báo:
"Việc kết hợp nhiều crawling và indexing rules có thể khiến một số rule triệt tiêu các rule khác."
Ví dụ sai lầm phổ biến:
# robots.txt
Disallow: /private-page
<!-- /private-page -->
<meta name="robots" content="noindex">
Vấn đề: Vì robots.txt chặn crawl, Google KHÔNG ĐỌC được <meta noindex>. Kết quả: trang có thể vẫn xuất hiện trong Google.
Đúng: Nếu muốn noindex, hãy CHO PHÉP crawl (xóa khỏi robots.txt), Google sẽ đọc meta tag và áp dụng noindex.
8.5. Debug khi nội dung không index
Nếu nội dung không hiển thị trên Google:
Bước 1: Kiểm tra Googlebot có thể access không (URL Inspection Tool)
Bước 2: Test robots.txt — đảm bảo không vô tình chặn
# Test bằng Google's robots.txt tester (trong Search Console)
# Hoặc dùng curl với user-agent Googlebot
curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://example.com/page
Bước 3: Kiểm tra HTML cho noindex rules (trong meta tags hoặc HTTP headers)
Bước 4: Kiểm tra canonical tags có trỏ đúng không
Bước 5: Kiểm tra server logs xem Googlebot có đến không
Phần 9: Enable Rich Results — Bật "kết quả phong phú"
Google nói:
"Rich result có thể bao gồm styling, hình ảnh, hoặc các tính năng tương tác giúp site của bạn nổi bật hơn trong kết quả tìm kiếm."
9.1. Rich Results là gì?
Đây là kết quả tìm kiếm "đẹp" hơn — có ngôi sao đánh giá, hình ảnh, giá, FAQ, breadcrumb...
Ví dụ rich result phổ biến:
⭐⭐⭐⭐⭐ Đánh giá sản phẩm
🍽️ Công thức nấu ăn (hình + thời gian + calories)
❓ FAQ accordion ngay trong kết quả
📅 Sự kiện (ngày, địa điểm)
💼 Tin tuyển dụng
🎬 Video với timestamp
🛒 Sản phẩm (giá, có sẵn, đánh giá)
9.2. Triển khai bằng Structured Data
Format khuyến nghị: JSON-LD (dễ implement, ít lỗi nhất)
Ví dụ — Product structured data:
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Product",
"name": "Áo thun nam cotton trắng",
"image": "https://shop.com/ao-trang.jpg",
"description": "Áo thun nam cotton 100%, form regular",
"brand": {
"@type": "Brand",
"name": "Shop XYZ"
},
"offers": {
"@type": "Offer",
"url": "https://shop.com/ao-trang",
"priceCurrency": "VND",
"price": "299000",
"availability": "https://schema.org/InStock"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "127"
}
}
</script>
Ví dụ — Article structured data:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Hướng dẫn SEO cho Developer",
"image": "https://example.com/article.jpg",
"datePublished": "2026-05-19T08:00:00+07:00",
"dateModified": "2026-05-19T08:00:00+07:00",
"author": {
"@type": "Person",
"name": "Tấn Phát Digital"
},
"publisher": {
"@type": "Organization",
"name": "Tấn Phát Digital",
"logo": {
"@type": "ImageObject",
"url": "https://tanphatdigital.com/logo.png"
}
}
}
</script>
9.3. Các loại Structured Data hữu ích cho doanh nghiệp Việt
Loại | Use case | Lợi ích |
|---|---|---|
| Blog, tin tức | Hiển thị ngày, tác giả, hình ảnh |
| E-commerce | Giá, đánh giá, tình trạng hàng |
| Cửa hàng, dịch vụ địa phương | Hiện trong Local Pack |
| Website nấu ăn | Hiện calories, thời gian, hình |
| Trang FAQ | FAQ accordion trong kết quả |
| Tổ chức sự kiện | Hiện ngày, địa điểm, giá vé |
| Đánh giá sản phẩm | Ngôi sao đánh giá |
| Trang công ty | Knowledge panel |
| Mọi site | Breadcrumb trong URL |
| Site có video | Thumbnail, thời gian |
9.4. Validate Structured Data
LUÔN LUÔN test trước khi deploy:
Rich Results Test — Google's official tool
Schema Markup Validator — Schema.org's validator
9.5. Helper libraries
Cho React:
npm install react-schemaorg
import { JsonLd } from 'react-schemaorg';
<JsonLd
item={{
"@context": "https://schema.org",
"@type": "Product",
name: "Áo thun",
// ...
}}
/>
Cho Next.js 14+: Có thể đặt JSON-LD trực tiếp trong component:
export default function ProductPage({ product }) {
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
// ...
};
return (
<section>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* Page content */}
</section>
);
}
Phần 10: Checklist cho Developer — Triển khai SEO ngay khi build
Tấn Phát Digital tổng hợp checklist toàn diện cho mỗi giai đoạn dự án:
Giai đoạn Architecture & Planning
[ ] Quyết định render strategy (CSR/SSR/SSG/ISR)
[ ] Lên cấu trúc URL có ý nghĩa
[ ] Plan đa ngôn ngữ (nếu có) — URL structure, hreflang
[ ] Plan canonical strategy
[ ] Plan robots.txt và sitemap
[ ] Plan structured data cần dùng
Giai đoạn Development
[ ] Setup framework với SSR/SSG (Next.js, Nuxt, Astro, v.v.)
[ ] Dùng semantic HTML (header, main, article, section...)
[ ] Implement Link component đúng cách (không onclick nav)
[ ] Mọi page có unique title + meta description
[ ] Implement canonical tags
[ ] Implement structured data
[ ] Hình ảnh có alt text mô tả
[ ] Mobile-responsive
[ ] HTTPS với certificate hợp lệ
[ ] Optimize Core Web Vitals (LCP < 2.5s, INP < 200ms, CLS < 0.1)
Giai đoạn Pre-Launch
[ ] Generate XML sitemap (tự động)
[ ] Tạo robots.txt
[ ] Setup Google Search Console
[ ] Setup Google Analytics 4
[ ] Test URL Inspection cho các trang quan trọng
[ ] Validate structured data
[ ] Test mobile-friendly
[ ] Test page speed (PageSpeed Insights)
[ ] Test với 3G/4G connection
[ ] Test accessibility (Lighthouse)
Giai đoạn Post-Launch
[ ] Submit sitemap qua Search Console
[ ] Request indexing cho các trang quan trọng
[ ] Monitor server logs (Googlebot crawl)
[ ] Monitor Search Console (errors, coverage)
[ ] Setup uptime monitoring
[ ] Setup error tracking (Sentry, v.v.)
Phần 11: Anti-patterns thường gặp ở Developer Việt Nam
Đây là những "tử huyệt" mà nhiều dự án mắc phải:
❌ Anti-pattern 1: SPA không SSR cho website public
Vấn đề: Build website giới thiệu bằng Create React App, deploy lên Netlify, hết. Google không thấy nội dung.
Giải pháp: Migrate sang Next.js / Astro với SSG.
❌ Anti-pattern 2: URL không có ý nghĩa
❌ https://shop.com/p?id=12345&cat=7
✅ https://shop.com/ao-thun-nam-cotton-trang
❌ Anti-pattern 3: Nội dung load qua AJAX sau khi trang ready
Vấn đề: Trang load skeleton, sau đó fetch API lấy nội dung thật.
Giải pháp: SSR/SSG nội dung quan trọng. Chỉ AJAX cho phần phụ.
❌ Anti-pattern 4: Lazy load hình ảnh main banner
Vấn đề: Hero image lazy load → LCP rất tệ → SEO score giảm.
Giải pháp: Hình above-the-fold dùng loading="eager" và fetchpriority="high".
❌ Anti-pattern 5: Title và meta description giống nhau
Vấn đề: Hardcode title "Shop XYZ" cho mọi trang.
Giải pháp: Template động dựa trên nội dung trang.
❌ Anti-pattern 6: Quên hreflang khi build multi-language
Vấn đề: Có /vi và /en nhưng không khai báo hreflang → Google không biết đó là cùng nội dung khác ngôn ngữ.
Giải pháp: Implement hreflang đầy đủ với return tags.
❌ Anti-pattern 7: Block toàn bộ JavaScript/CSS trong robots.txt
# SAI - Google cần JS/CSS để render
User-agent: *
Disallow: /js/
Disallow: /css/
Giải pháp: Cho phép Google crawl JS/CSS để render đúng.
❌ Anti-pattern 8: Infinite scroll không có paginated fallback
Vấn đề: Trang blog dùng infinite scroll. Google chỉ thấy 10 bài đầu, các bài còn lại "vô hình".
Giải pháp: Có cả URL phân trang (/blog?page=2, /blog?page=3) để Google crawl.
Developer Tốt = SEO Tốt = Business Tốt
Đầu tư vào SEO ngay từ giai đoạn development không phải là chi phí phụ — đó là đầu tư có ROI cực cao. Một website được build đúng từ đầu sẽ:
Tiết kiệm hàng trăm giờ refactor sau này
Có cơ hội ranking cao hơn ngay từ ngày launch
Cung cấp trải nghiệm tốt cho user (mà SEO chỉ là hệ quả)
Dễ maintain và mở rộng
3 nguyên tắc cuối cùng cho Developer
1. SEO là kỹ thuật, không phải ma thuật. Mọi yêu cầu SEO đều có lý do kỹ thuật rõ ràng. Hiểu lý do → biết cách triển khai đúng.
2. Google không phải user thông minh nhất. Hãy giả định Googlebot là một browser cũ, chậm, không tương tác. Nếu trang của bạn vẫn hoạt động trong điều kiện đó, SEO sẽ tốt.
3. Test, test, và test. URL Inspection Tool, Rich Results Test, Lighthouse, PageSpeed Insights — đây là những công cụ MIỄN PHÍ. Dùng chúng thường xuyên.
Lời nhắn cho team Development
Nếu bạn là Tech Lead hoặc Solution Architect, hãy đưa SEO requirements vào tài liệu kỹ thuật ngay từ đầu dự án. Đừng để đến phase QA mới phát hiện ra vấn đề.
Nếu bạn là Developer cá nhân, đọc tài liệu chính thức của Google (đừng tin các "thủ thuật SEO" trên YouTube/Facebook). Tài liệu Google thay đổi liên tục — luôn cập nhật.
Tài liệu tham khảo chính thức
Developer's guide to Search — Tài liệu nguồn
Công cụ thiết yếu cho Developer
Google Search Console — URL Inspection, Coverage, Performance
Rich Results Test — Test structured data + render
Schema Markup Validator — Validate schema theo schema.org
PageSpeed Insights — Core Web Vitals
Lighthouse — Trong Chrome DevTools
Framework khuyến nghị cho SEO tốt
Next.js — React + SSR/SSG/ISR
Nuxt — Vue + SSR/SSG
Astro — Multi-framework + SSG (cực nhanh)
Remix — React + SSR
SvelteKit — Svelte + SSR/SSG
Hugo / Jekyll — Static site generators
Về Tấn Phát Digital
Tấn Phát Digital không chỉ là agency SEO — chúng tôi là đối tác Technical Partner cho doanh nghiệp Việt Nam. Khác biệt của chúng tôi:
Đội ngũ kết hợp giữa SEO Specialist và Senior Developer
Tư vấn từ giai đoạn architect — không phải đợi đến khi website xong
Code review SEO cho team developer in-house của khách hàng
Migration không mất traffic — chuyên thực hiện site migration phức tạp
Dịch vụ Technical SEO cho Developer
SEO Code Audit — Review code và đề xuất cải thiện
Pre-launch SEO Check — Đảm bảo website launch không có lỗi SEO
Schema Implementation — Triển khai structured data đầy đủ
Core Web Vitals Optimization — Tối ưu hiệu suất đạt chuẩn Google
JavaScript SEO Consulting — Đặc biệt cho SPA, PWA, headless commerce
Đào tạo SEO cho Developer Team — Workshop in-house
Bạn là developer hoặc Tech Lead? Liên hệ Tấn Phát Digital để được tư vấn về kiến trúc SEO-friendly cho dự án sắp tới của bạn.
Bài viết được biên soạn và phân tích từ tài liệu chính thức của Google Search Central, cập nhật ngày 10/12/2025. Bản quyền nội dung gốc thuộc về Google (CC BY 4.0). Phần phân tích, code examples, anti-patterns và checklist thuộc về Tấn Phát Digital.
SEO hiện đại không còn là việc riêng của marketer — mà là sự kết hợp giữa content, kỹ thuật và trải nghiệm người dùng.
Nếu bạn cần xây dựng website chuẩn SEO ngay từ kiến trúc kỹ thuật, hãy liên hệ Tấn Phát Digital để được tư vấn.









