Tin tức

JavaScript SEO Là Gì? Cách Tối Ưu Website React, Vue Lên Top Google (2026)

JavaScript SEO là gì — tối ưu website React, Vue để Google index đúng

Bạn vừa hoàn thành một website React hoặc Vue rất đẹp: chuyển trang mượt như app, hiệu ứng mở rộng nội dung tinh tế, dữ liệu sản phẩm tải về theo thời gian thực. Nhưng sau ba tháng, Google Search Console vẫn báo “Đã thu thập dữ liệu – hiện chưa được lập chỉ mục” cho phần lớn URL, và khi bạn tìm một đoạn văn bản trong bài của mình trên Google thì không ra kết quả nào. Nội dung rõ ràng đang hiển thị trên màn hình, nhưng với Google thì nó gần như không tồn tại.

Đó là vấn đề kinh điển của JavaScript SEO. Googlebot không “nhìn” trang web giống người dùng. Trình duyệt của bạn tải HTML, chạy JavaScript, gọi API, dựng DOM rồi vẽ ra màn hình — tất cả trong vài trăm mili giây và bạn không cảm nhận được độ trễ nào. Googlebot thì tách quá trình đó thành nhiều pha riêng biệt, cách nhau bởi một hàng đợi có thể kéo dài hàng giờ đến hàng tuần, và ở mỗi pha nó đều có quyền bỏ cuộc nếu thấy không đáng đầu tư tài nguyên.

Bài viết này sẽ giải thích chính xác cơ chế đó, chỉ ra 9 lỗi JavaScript SEO phổ biến nhất mà các website Việt Nam hay mắc, đưa cho bạn quy trình 7 bước tự kiểm tra bằng công cụ miễn phí, một checklist tối ưu đầy đủ, lộ trình khắc phục 30 ngày và hướng dẫn riêng cho từng framework (React, Next.js, Vue, Nuxt). Mục tiêu cuối cùng rất cụ thể: nội dung quan trọng của bạn phải nằm sẵn trong HTML mà Googlebot nhận được ở lần request đầu tiên, chứ không phải đợi JavaScript chạy xong mới xuất hiện.

JavaScript SEO là gì?

JavaScript SEO là tập hợp các kỹ thuật giúp công cụ tìm kiếm có thể thu thập dữ liệu (crawl), kết xuất (render) và lập chỉ mục (index) đầy đủ nội dung của một website được xây dựng bằng JavaScript. Nói ngắn gọn: đây là phần SEO kỹ thuật dành riêng cho các website mà nội dung không nằm sẵn trong file HTML ban đầu, mà được JavaScript sinh ra sau khi trang đã tải.

Với một website WordPress truyền thống, máy chủ trả về một file HTML đã chứa sẵn toàn bộ tiêu đề, đoạn văn, hình ảnh và liên kết. Googlebot chỉ cần tải file đó về là đã có đủ mọi thứ cần thiết để hiểu trang. Với một website Single Page Application (SPA) viết bằng React, Vue hay Angular theo kiểu mặc định, file HTML trả về thường chỉ gồm vài dòng: một thẻ <div id="root"></div> rỗng và vài thẻ <script> trỏ tới bundle JavaScript. Toàn bộ nội dung thật chỉ xuất hiện sau khi trình duyệt tải bundle, chạy nó và gọi API lấy dữ liệu.

Khoảng cách giữa hai kịch bản đó chính là toàn bộ nội dung của JavaScript SEO. Nếu Googlebot dừng lại ở bước tải HTML, nó sẽ thấy một trang trống rỗng. Nếu nó đi tiếp tới bước render, nó sẽ thấy nội dung — nhưng muộn hơn, tốn kém hơn, và không phải lúc nào cũng thành công.

Vì sao JavaScript lại gây khó cho công cụ tìm kiếm?

Có bốn lý do kỹ thuật khiến JavaScript trở thành rào cản, và hiểu rõ chúng sẽ giúp bạn chẩn đoán vấn đề nhanh hơn nhiều so với việc đoán mò:

  • Chi phí tài nguyên chênh lệch rất lớn. Tải và phân tích một file HTML tĩnh tốn vài mili giây CPU. Khởi tạo một trình duyệt không giao diện, chạy vài trăm kilobyte JavaScript, chờ API phản hồi rồi dựng lại DOM có thể tốn gấp hàng chục lần. Google phải nhân con số đó với hàng nghìn tỷ URL, nên họ buộc phải xếp hàng và ưu tiên.
  • Render là một pha tách rời, không diễn ra ngay. Googlebot crawl trước, đưa trang vào hàng đợi render, rồi mới quay lại xử lý sau. Khoảng trễ này có thể là vài giây với site lớn uy tín, nhưng cũng có thể là vài ngày đến vài tuần với domain mới hoặc site có crawl budget thấp.
  • Googlebot không hành xử như người dùng thật. Nó không cuộn trang, không di chuột, không bấm nút “Xem thêm”, không đăng nhập, không chấp nhận cookie consent. Mọi nội dung chỉ xuất hiện sau một trong các hành động đó đều vô hình với Google.
  • Mọi lỗi JavaScript đều mang tính “tất cả hoặc không có gì”. Một exception duy nhất chưa bắt được có thể làm dừng toàn bộ chuỗi thực thi, khiến trang kết xuất ra rỗng. Trên trình duyệt của bạn lỗi đó có thể bị che giấu bởi cache hoặc extension, nhưng với Googlebot thì nó là dấu chấm hết.

Điều quan trọng cần nhớ: Google có khả năng render JavaScript, và đã làm được từ nhiều năm nay. Vấn đề không phải “Google không đọc được JavaScript” mà là “Google đọc được nhưng chậm hơn, tốn kém hơn và dễ thất bại hơn”. Trong SEO, chậm hơn và dễ thất bại hơn đã đủ để bạn thua đối thủ dùng HTML tĩnh.

Google xử lý JavaScript như thế nào: quy trình 3 pha

Muốn sửa lỗi JavaScript SEO, bạn phải hình dung đúng đường đi của một URL trong hệ thống của Google. Quy trình này gồm ba pha tách biệt, và nội dung của bạn có thể “rơi” ở bất kỳ pha nào. Nếu bạn chưa nắm vững cách hoạt động của trình thu thập dữ liệu, hãy đọc thêm bài Googlebot là gì để có nền tảng trước khi đi tiếp.

Pha 1 — Crawl: tải HTML thô

Googlebot gửi một HTTP request tới URL và nhận về HTML thô, đúng như những gì bạn thấy khi dùng lệnh curl hoặc bấm “View Source” trong trình duyệt. Ở pha này, JavaScript chưa hề được chạy. Googlebot làm ba việc: đọc mã trạng thái HTTP, trích xuất các liên kết trong thẻ <a href> để thêm vào hàng đợi crawl, và đọc các thẻ meta cơ bản như robots, canonical.

Đây chính là lý do một trang SPA thuần túy gần như không mang lại giá trị gì ở pha 1: HTML rỗng nghĩa là không có liên kết nào để Googlebot đi tiếp, không có nội dung nào để đánh giá sơ bộ. Trang bị đưa vào hàng đợi render với mức ưu tiên thấp vì hệ thống chưa có tín hiệu nào cho thấy nó đáng để đầu tư tài nguyên.

Pha 2 — Render: chạy JavaScript trong hàng đợi

Trang được đưa vào render queue. Khi đến lượt, Web Rendering Service (một phiên bản Chromium không giao diện, luôn cập nhật theo bản Chrome ổn định mới nhất) sẽ tải lại trang, thực thi JavaScript, gọi các API cần thiết và dựng ra DOM cuối cùng. HTML sau render này mới là thứ Google thực sự dùng để đánh giá nội dung.

Hai đặc điểm của pha này gây ra phần lớn rắc rối trong thực tế. Thứ nhất, độ trễ không cố định: có thể vài giây, cũng có thể vài tuần, tuỳ vào uy tín domain, tần suất cập nhật và ngân sách thu thập. Thứ hai, Web Rendering Service có giới hạn kiên nhẫn: nó không chờ vô hạn một API chậm, không thực hiện các hành động tương tác, và sẽ bỏ qua tài nguyên bị chặn trong robots.txt.

Pha 3 — Index: đưa vào chỉ mục

Sau khi có HTML đã render, Google mới phân tích nội dung thật, trích xuất lại lần nữa các liên kết mới phát hiện (đưa chúng ngược về hàng đợi crawl), đánh giá chất lượng và quyết định có index hay không. Đây là lúc bạn thấy kết quả trong báo cáo Lập chỉ mục của Search Console. Nếu bạn đang gặp hàng loạt URL báo lỗi ở bước này, bài khắc phục lỗi trang chưa được lập chỉ mục mô tả chi tiết cách đọc từng loại thông báo.

Một hệ quả ít người để ý: vì liên kết chỉ được phát hiện lại ở pha 3, website SPA cần hai vòng crawl-render-index đầy đủ để Google khám phá được một trang nằm sâu hai cấp. Với site HTML tĩnh, toàn bộ cấu trúc liên kết đã lộ ra ngay từ pha 1. Đây là lý do các site JavaScript thường bị index rất chậm ở những trang danh mục sâu.

Ba pha Googlebot xử lý JavaScript: crawl, render và index

Bảng dưới đây tóm tắt điểm khác biệt giữa một trang HTML tĩnh và một trang SPA đi qua cùng một quy trình:

Giai đoạn Trang HTML tĩnh (WordPress, SSR) Trang SPA (React/Vue mặc định)
Sau pha Crawl Đã có đủ tiêu đề, nội dung, toàn bộ liên kết nội bộ HTML rỗng, không nội dung, không liên kết
Cần pha Render? Không bắt buộc Bắt buộc, nếu không thì không có gì để index
Độ trễ trung bình tới khi index Vài giờ đến vài ngày Vài ngày đến vài tuần
Số vòng xử lý để phát hiện trang sâu 1 vòng 2 vòng trở lên
Rủi ro mất toàn bộ nội dung Rất thấp Cao — chỉ cần 1 lỗi JS là trang rỗng
Chi phí crawl budget mỗi URL Thấp Cao gấp nhiều lần

Bốn kiểu render và cách chọn đúng cho dự án của bạn

Đây là quyết định kiến trúc quan trọng nhất trong JavaScript SEO. Chọn sai ở bước này thì mọi tối ưu phía sau chỉ là vá víu. Có bốn phương án chính, và chúng không loại trừ lẫn nhau — một dự án tốt thường kết hợp nhiều kiểu cho các loại trang khác nhau.

1. CSR — Client-Side Rendering

Máy chủ trả về HTML rỗng, toàn bộ việc dựng giao diện do JavaScript phía trình duyệt đảm nhiệm. Đây là chế độ mặc định của Create React App, Vite + React, Vue CLI. Ưu điểm là hạ tầng đơn giản, chi phí máy chủ gần như bằng không, trải nghiệm chuyển trang rất mượt sau lần tải đầu. Nhược điểm với SEO thì nghiêm trọng: phụ thuộc hoàn toàn vào pha render của Google, chỉ số LCP kém, và các công cụ chia sẻ mạng xã hội (Facebook, Zalo) không đọc được thẻ Open Graph vì chúng không chạy JavaScript.

Nên dùng khi: dashboard nội bộ, khu vực sau đăng nhập, ứng dụng công cụ — tức là những trang bạn không cần lên top Google.

2. SSR — Server-Side Rendering

Máy chủ chạy JavaScript trước, dựng sẵn HTML hoàn chỉnh rồi mới trả về cho trình duyệt. Sau đó JavaScript “hydrate” để trang trở nên tương tác. Đây là chế độ mặc định của Next.js App Router, Nuxt 3, Remix, SvelteKit. Googlebot nhận được nội dung đầy đủ ngay ở pha 1, không cần chờ render queue.

Nên dùng khi: nội dung thay đổi thường xuyên theo người dùng hoặc theo thời gian thực — trang chi tiết sản phẩm có tồn kho và giá biến động, kết quả tìm kiếm nội bộ, trang cá nhân hóa.

3. SSG — Static Site Generation

HTML được dựng sẵn một lần ở thời điểm build, sau đó phục vụ như file tĩnh qua CDN. Tốc độ nhanh nhất có thể, chi phí rẻ nhất, an toàn nhất cho SEO. Next.js gọi là Static Generation, Nuxt gọi là Prerender, ngoài ra còn Astro, Hugo, Gatsby.

Nên dùng khi: blog, trang giới thiệu, tài liệu, landing page — nội dung ít thay đổi. Với các dự án có hàng nghìn trang, hãy kết hợp ISR (Incremental Static Regeneration) để build lại từng trang theo chu kỳ thay vì build lại toàn bộ site.

4. Dynamic Rendering

Máy chủ phát hiện user-agent: nếu là Googlebot thì trả HTML đã prerender, nếu là người dùng thật thì trả bản JavaScript bình thường. Google từng khuyến nghị giải pháp này như một cách chữa cháy, nhưng hiện nay chính thức xem nó là workaround tạm thời, không phải giải pháp dài hạn — vì phải duy trì hai đường dẫn nội dung song song, rất dễ lệch nhau và tiệm cận ranh giới cloaking.

Nên dùng khi: bạn đang mắc kẹt với một codebase legacy không thể chuyển sang SSR trong ngắn hạn, và cần cầm cự vài tháng.

Bảng so sánh CSR, SSR và SSG về mức độ an toàn SEO
Tiêu chí CSR SSR SSG Dynamic Rendering
Nội dung có trong HTML đầu tiên Không Có Có Có (chỉ với bot)
Mức độ an toàn SEO Thấp Cao Rất cao Trung bình
Tốc độ LCP Chậm Khá Nhanh nhất Khá
Chi phí hạ tầng Rất thấp Cao Rất thấp Trung bình
Độ phức tạp vận hành Thấp Trung bình Thấp Cao
Phù hợp nội dung động Có Rất tốt Kém (cần ISR) Có
Open Graph khi chia sẻ Hỏng Hoạt động Hoạt động Hoạt động

Gợi ý thực dụng: với đa số website thương mại Việt Nam, cấu hình tối ưu là SSG cho blog và trang tĩnh, SSR cho trang danh mục và chi tiết sản phẩm, CSR chỉ dành cho khu vực tài khoản sau đăng nhập. Đây là mô hình “hybrid” mà Next.js và Nuxt đều hỗ trợ sẵn ở mức cấu hình từng route, không cần viết lại toàn bộ dự án.

9 lỗi JavaScript SEO thường gặp nhất

Danh sách dưới đây sắp xếp theo mức độ thiệt hại thực tế, từ nghiêm trọng nhất trở xuống. Nếu website của bạn đang mất traffic không rõ nguyên nhân, hãy kiểm tra lần lượt từ trên xuống.

Lỗi 1 — Chặn file JavaScript và CSS trong robots.txt

Đây là lỗi gây thiệt hại lớn nhất và cũng dễ sửa nhất. Nhiều lập trình viên thêm dòng Disallow: /static/ hoặc Disallow: /_next/ vào robots.txt để “tiết kiệm băng thông”. Hậu quả: Web Rendering Service không tải được bundle JavaScript, render ra trang rỗng, và Google index một trang trắng. Quy tắc bất biến: không bao giờ chặn file JS/CSS cần thiết để render nội dung chính.

Lỗi 2 — Liên kết nội bộ không dùng thẻ <a href>

Các đoạn code kiểu <div onClick={() => router.push('/san-pham')}> hay <span> gắn sự kiện click hoạt động hoàn hảo với người dùng nhưng hoàn toàn vô hình với Googlebot. Không có thẻ <a> với thuộc tính href thì không có liên kết, không có liên kết thì không có đường cho crawler đi tiếp và không có dòng sức mạnh liên kết truyền đi. Mọi liên kết điều hướng phải là <a href="/duong-dan-that"> — kể cả khi bạn dùng router phía client để chặn hành vi mặc định.

Lỗi 3 — Nội dung chỉ xuất hiện sau tương tác người dùng

Tab sản phẩm, accordion mô tả, nút “Xem thêm”, infinite scroll: nếu nội dung chỉ được nạp vào DOM sau khi người dùng bấm hoặc cuộn, Googlebot sẽ không bao giờ thấy nó. Cách xử lý đúng là đưa toàn bộ nội dung vào DOM ngay từ đầu rồi dùng CSS để ẩn/hiện, thay vì chỉ nạp khi có sự kiện. Với infinite scroll, bắt buộc phải có phiên bản phân trang song song với URL thật (?page=2) và liên kết bằng thẻ <a>.

Lỗi 4 — Thẻ title và meta description được sinh bằng JavaScript

Khi bạn đặt thẻ tiêu đề bằng document.title = ... hoặc qua thư viện chỉ chạy phía client, thẻ đó chỉ tồn tại sau pha render. Google có thể vẫn bắt được, nhưng các crawler khác thì không: Facebook, Zalo, Twitter, LinkedIn đều không chạy JavaScript, nên khi chia sẻ bài bạn sẽ thấy tiêu đề sai hoặc ảnh preview trống. Thẻ meta phải nằm trong HTML gốc từ máy chủ — Next.js có Metadata API, Nuxt có useHead.

Lỗi 5 — Dùng URL fragment thay vì đường dẫn thật

Các URL dạng example.com/#/san-pham/123 (hash routing) không được Google xem là URL riêng biệt — mọi thứ sau dấu # đều bị bỏ qua. Kết quả là toàn bộ website của bạn chỉ có đúng một URL trong mắt Google. Bắt buộc dùng History API để tạo đường dẫn thật dạng example.com/san-pham/123. Cách đặt đường dẫn hợp lý được trình bày kỹ trong bài về tối ưu SEO onpage.

Lỗi 6 — Soft 404: trang lỗi trả mã 200

Với SPA, khi người dùng vào một URL không tồn tại, máy chủ vẫn trả mã 200 kèm HTML rỗng, rồi JavaScript mới hiển thị thông báo “Không tìm thấy trang”. Google thấy mã 200 và có thể index hàng loạt trang rác, hoặc tự phân loại là soft 404 và bỏ qua cả những trang hợp lệ gần đó. Hãy đảm bảo máy chủ trả đúng mã 404 cho URL không tồn tại và mã 301 cho URL đã chuyển.

Lỗi 7 — Phụ thuộc API chậm hoặc lỗi không có phương án dự phòng

Nếu nội dung chính của trang chỉ xuất hiện sau khi một API bên thứ ba phản hồi, thì mỗi lần API đó chậm hoặc timeout là một lần Googlebot thấy trang rỗng. Hãy đặt giới hạn thời gian chờ, luôn có dữ liệu dự phòng render phía máy chủ, và không để nội dung quan trọng phụ thuộc vào API ngoài tầm kiểm soát của bạn.

Lỗi 8 — Bundle JavaScript quá nặng làm hỏng Core Web Vitals

Một bundle 2MB không chỉ làm người dùng chờ lâu mà còn kéo LCP và INP xuống vùng đỏ, đồng thời tăng chi phí render cho Googlebot — dẫn tới việc Google giảm tần suất thu thập site của bạn. Hãy chia nhỏ bundle theo route, tải lười các thành phần không quan trọng và loại bỏ thư viện không dùng. Bộ chỉ số cần theo dõi được giải thích trong bài Core Web Vitals.

Lỗi 9 — Thẻ canonical hoặc noindex sinh sai phía client

Một lỗi tinh vi nhưng rất tốn kém: HTML gốc có <meta name="robots" content="noindex"> làm mặc định, và JavaScript sẽ gỡ nó ra sau khi xác định trang hợp lệ. Nếu Google crawl mà chưa render, nó thấy noindex và loại trang khỏi chỉ mục ngay lập tức — sau đó có thể rất lâu mới quay lại. Tương tự với thẻ canonical trỏ sai. Nguyên tắc: các chỉ thị dành cho robot luôn phải đúng ngay trong HTML gốc, không bao giờ sửa bằng JavaScript. Cách dùng đúng được mô tả chi tiết trong bài thẻ canonical.

Quy trình 7 bước kiểm tra website JavaScript

Bạn không cần công cụ trả phí để chẩn đoán phần lớn vấn đề. Bảy bước dưới đây dùng toàn công cụ miễn phí và có thể hoàn thành trong khoảng một giờ cho một website cỡ vừa.

  1. So sánh HTML gốc với HTML sau render. Mở trang, bấm chuột phải chọn “View Page Source” để xem HTML gốc, sau đó mở DevTools tab Elements để xem DOM sau render. Tìm một đoạn văn bản đặc trưng trong nội dung chính: nếu nó có trong Elements nhưng không có trong Page Source, bạn đang phụ thuộc hoàn toàn vào pha render của Google.
  2. Tìm kiếm nội dung trên Google. Copy một câu dài, độc nhất trong bài rồi tìm trên Google với dấu ngoặc kép. Nếu không ra kết quả nào dù trang đã được index, nghĩa là Google chưa render được nội dung đó.
  3. Dùng URL Inspection trong Search Console. Nhập URL, bấm “Kiểm tra URL trực tiếp”, rồi mở phần “HTML đã kết xuất”. Đây là thứ Google thực sự nhìn thấy. Kiểm tra kỹ phần “Ảnh chụp màn hình” và danh sách “Tài nguyên trang” để phát hiện file nào bị chặn hoặc lỗi tải.
  4. Tắt JavaScript rồi tải lại trang. Trong DevTools, mở Command Menu rồi chọn “Disable JavaScript”, tải lại trang. Những gì còn nhìn thấy chính là phần nội dung an toàn tuyệt đối về mặt SEO. Nếu màn hình trắng, bạn biết mình đang đặt cược toàn bộ traffic vào pha render.
  5. Crawl bằng Screaming Frog ở hai chế độ. Chạy lần một với chế độ Text Only, lần hai bật JavaScript Rendering, rồi so sánh số trang tìm được, số liên kết nội bộ và độ dài nội dung. Chênh lệch lớn giữa hai lần chính là phần nội dung phụ thuộc JavaScript. Cách cấu hình công cụ này có trong bài hướng dẫn Screaming Frog.
  6. Kiểm tra bằng Mobile-Friendly Test và Rich Results Test. Cả hai công cụ này đều hiển thị HTML sau render và liệt kê lỗi JavaScript phát sinh trong quá trình kết xuất. Phần “Chi tiết trang” thường chỉ thẳng ra dòng script gây lỗi.
  7. Đọc lại báo cáo Lập chỉ mục trong Search Console. Lọc theo lý do “Đã thu thập dữ liệu – hiện chưa được lập chỉ mục” và “Đã phát hiện – hiện chưa được lập chỉ mục”. Hai nhóm này tăng nhanh trên site JavaScript gần như luôn đồng nghĩa với vấn đề render hoặc ngân sách thu thập.

Ghi lại kết quả từng bước thành một bảng đối chiếu. Rất nhiều đội ngũ bỏ qua khâu này rồi tranh cãi vòng vo về nguyên nhân, trong khi dữ liệu thực tế đã chỉ thẳng vào một lỗi cụ thể.

Checklist tối ưu JavaScript SEO

Dùng danh sách này như tiêu chuẩn nghiệm thu trước mỗi lần triển khai lên môi trường thật. Mỗi mục đều là một câu hỏi có/không, không có vùng xám.

  • Nội dung chính nằm trong HTML gốc. Tiêu đề H1, đoạn mở đầu, thông tin sản phẩm cốt lõi phải xem được khi tắt JavaScript.
  • Mọi liên kết điều hướng dùng thẻ <a href> với đường dẫn thật. Không dùng onClick, không dùng hash routing.
  • robots.txt không chặn bất kỳ file JS/CSS nào phục vụ render. Kiểm tra lại cả các thư mục build như /_next/, /assets/, /static/.
  • Thẻ title, meta description, canonical, meta robots, Open Graph đều được máy chủ render sẵn. Không sinh bằng JavaScript phía client.
  • Mã trạng thái HTTP chính xác. 404 cho trang không tồn tại, 301 cho trang đã chuyển, 200 chỉ dành cho trang hợp lệ.
  • Sitemap XML liệt kê đúng các URL cần index và được cập nhật tự động khi thêm nội dung mới. Xem thêm cách cấu hình trong bài về sitemap XML.
  • Bundle JavaScript được chia nhỏ theo route và tải lười các thành phần không nằm trong màn hình đầu tiên.
  • Hình ảnh dùng lazy loading gốc của trình duyệt (loading="lazy") thay vì thư viện JavaScript tuỳ biến — thuộc tính gốc được Googlebot hiểu đúng.
  • Không có nội dung quan trọng nào nằm sau tương tác người dùng. Tab, accordion, “xem thêm” đều phải có sẵn trong DOM.
  • Có cơ chế theo dõi lỗi JavaScript trên môi trường thật để phát hiện sớm exception làm hỏng render.
Checklist 6 điều kiện bắt buộc khi tối ưu JavaScript SEO

Lộ trình 30 ngày khắc phục JavaScript SEO

Nếu website của bạn đang gặp vấn đề, đừng viết lại toàn bộ dự án. Thứ tự dưới đây được sắp xếp theo tỷ lệ “hiệu quả trên công sức bỏ ra”, giúp bạn thấy kết quả sớm nhất có thể trong khi vẫn đi đúng hướng dài hạn.

Giai đoạn Việc cần làm Kết quả kỳ vọng
Ngày 1–3
Chẩn đoán
Chạy đủ 7 bước kiểm tra ở trên, lập bảng liệt kê lỗi theo từng URL mẫu đại diện cho mỗi loại template Danh sách lỗi cụ thể thay vì phỏng đoán
Ngày 4–7
Sửa lỗi chặn
Gỡ chặn JS/CSS trong robots.txt, sửa mã trạng thái HTTP, gỡ noindex sinh sai phía client Số trang render thành công tăng rõ trong URL Inspection
Ngày 8–14
Sửa liên kết
Thay toàn bộ onClick điều hướng bằng thẻ a href, bỏ hash routing, thêm phân trang thật cho infinite scroll Screaming Frog chế độ Text Only bắt được gần đủ số URL
Ngày 15–21
Chuyển render
Chuyển các template quan trọng nhất (trang chủ, danh mục, chi tiết, bài viết) sang SSR hoặc SSG Nội dung chính xuất hiện trong View Source
Ngày 22–26
Tối ưu tốc độ
Chia nhỏ bundle, tải lười thành phần phụ, tối ưu ảnh, kiểm tra lại Core Web Vitals LCP và INP vào vùng xanh trên dữ liệu thực tế
Ngày 27–30
Thúc đẩy index
Cập nhật sitemap, bổ sung liên kết nội bộ từ các trang đã index về trang mới sửa, theo dõi báo cáo Lập chỉ mục Số URL đã index tăng đều trong 2–4 tuần tiếp theo

Một lưu ý về kỳ vọng thời gian: sau khi sửa xong, Google không index lại ngay lập tức. Trang phải được crawl lại, render lại rồi mới đánh giá lại — tổng thời gian thường là 2 đến 6 tuần với domain trẻ. Nếu bạn muốn rút ngắn giai đoạn này, các kỹ thuật trong bài cách index bài viết nhanh trên Google sẽ giúp đẩy nhanh vòng crawl đầu tiên.

Hướng dẫn theo từng framework

React thuần (Create React App, Vite)

Đây là trường hợp rủi ro nhất vì mặc định là CSR hoàn toàn. Nếu website cần SEO, phương án đúng là chuyển sang Next.js hoặc Remix — cả hai đều hỗ trợ giữ lại phần lớn code component hiện có. Nếu chưa thể chuyển ngay, giải pháp cầm cự là prerender các route quan trọng ở bước build bằng công cụ như react-snap, hoặc dựng một lớp prerender phía máy chủ. Đừng đầu tư quá nhiều vào phương án cầm cự — chi phí bảo trì nó thường vượt chi phí chuyển đổi.

Next.js

Next.js xử lý gần như toàn bộ vấn đề JavaScript SEO nếu bạn dùng đúng. Với App Router, mặc định mọi component là Server Component và được render phía máy chủ — hãy cẩn thận khi thêm 'use client' vào đầu file, vì nó đẩy cả cây component con sang phía client. Dùng Metadata API để khai báo thẻ tiêu đề và mô tả, dùng generateStaticParams để dựng tĩnh các trang chi tiết, và bật ISR với khoảng thời gian revalidate phù hợp cho nội dung thay đổi thường xuyên. Luôn kiểm tra lại bằng View Source sau khi deploy, vì một lần thêm nhầm 'use client' có thể làm rỗng cả một template.

Vue thuần

Tình trạng tương tự React thuần. Vue CLI và Vite mặc định tạo ra SPA client-side. Hướng xử lý là chuyển sang Nuxt, hoặc dùng plugin prerender cho các route tĩnh. Với website thương mại điện tử, chuyển sang Nuxt gần như là lựa chọn bắt buộc nếu bạn nghiêm túc về organic traffic.

Nuxt

Nuxt 3 mặc định chạy chế độ universal (SSR), đây là cấu hình tốt cho SEO. Dùng useHead hoặc useSeoMeta để quản lý thẻ meta, dùng nuxt generate cho các phần nội dung tĩnh và cấu hình routeRules để chọn kiểu render cho từng nhóm route. Cạm bẫy thường gặp là vô tình đặt ssr: false trong file cấu hình khi gỡ lỗi rồi quên bật lại trước khi lên môi trường thật.

Angular

Dùng Angular Universal để bật server-side rendering. Angular có bundle khá nặng nên phần tối ưu kích thước và chia nhỏ theo route quan trọng hơn so với các framework khác. Kiểm tra kỹ phần hydration để tránh lỗi nội dung nhấp nháy sau khi trang tải.

Những sai lầm thường gặp khi xử lý JavaScript SEO

Ngoài các lỗi kỹ thuật ở trên, đây là những sai lầm về cách tiếp cận khiến nhiều dự án tốn hàng tháng mà không cải thiện được gì:

  • Tin rằng “Google render được JavaScript nên không cần lo”. Đúng về mặt kỹ thuật nhưng sai về mặt chiến lược. Google có thể render, nhưng điều đó không có nghĩa nó sẽ render kịp thời và mọi lần. Với website tin tức hay thương mại điện tử có hàng nghìn URL, độ trễ vài tuần là mất doanh thu thật.
  • Chỉ kiểm tra trên trình duyệt của mình. Trình duyệt của bạn có cache, có extension, có kết nối nhanh và có cookie đã đăng nhập. Googlebot không có gì trong số đó. Luôn kiểm tra bằng chế độ ẩn danh cộng với URL Inspection.
  • Sửa lỗi rồi kết luận ngay sau hai ngày là “không hiệu quả”. Chu kỳ crawl – render – index cần thời gian. Hãy đặt mốc đánh giá ở tuần thứ tư, không phải ngày thứ hai.
  • Chuyển toàn bộ site sang SSR một lượt. Chi phí máy chủ tăng vọt và rủi ro hỏng vận hành rất cao. Hãy chuyển từng template theo thứ tự ưu tiên traffic.
  • Dùng Dynamic Rendering như giải pháp vĩnh viễn. Hai đường dẫn nội dung song song sẽ lệch nhau sau vài tháng bảo trì, và khi đó bạn có nguy cơ bị xem là cloaking.
  • Bỏ qua liên kết nội bộ sau khi đã sửa xong phần render. Trang có nội dung nhưng không có trang nào đã index trỏ về vẫn sẽ nằm mãi ở trạng thái “Đã phát hiện – hiện chưa được lập chỉ mục”.

Câu hỏi thường gặp về JavaScript SEO

Google có thực sự đọc được JavaScript không?

Có. Web Rendering Service của Google dùng phiên bản Chromium cập nhật liên tục, hỗ trợ đầy đủ các tính năng JavaScript hiện đại. Nhưng việc render diễn ra ở một pha riêng, sau pha crawl, và phải xếp hàng chờ tài nguyên. Nói cách khác, khả năng render không phải là vấn đề — độ trễ, chi phí và tỷ lệ thất bại mới là vấn đề. Đó là lý do đưa nội dung vào HTML gốc vẫn luôn là lựa chọn an toàn hơn.

Website React của tôi vẫn có traffic, vậy có cần đổi sang SSR không?

Hãy so sánh chứ đừng nhìn con số tuyệt đối. Kiểm tra tỷ lệ URL đã index trên tổng số URL trong sitemap, và độ trễ trung bình từ lúc xuất bản đến lúc được index. Nếu tỷ lệ index dưới 70% hoặc độ trễ vượt hai tuần, bạn đang mất traffic đáng kể mà không nhìn thấy, vì phần bị mất không bao giờ xuất hiện trong báo cáo. Ngược lại, nếu tỷ lệ index cao và thứ hạng ổn định, bạn có thể ưu tiên việc khác trước.

Mất bao lâu để thấy kết quả sau khi sửa lỗi JavaScript SEO?

Với các lỗi chặn như robots.txt hoặc noindex sai, kết quả có thể thấy sau 3–7 ngày vì Google sẽ crawl lại khá nhanh. Với việc chuyển kiểu render, thời gian thường là 3–6 tuần cho toàn bộ site được crawl lại và đánh giá lại. Domain càng trẻ và càng ít backlink thì chu kỳ càng dài. Hãy theo dõi số URL đã index theo tuần thay vì theo dõi thứ hạng theo ngày.

Infinite scroll có hại cho SEO không?

Bản thân infinite scroll không bị phạt, nhưng nếu đó là cách duy nhất để truy cập nội dung thì Google sẽ chỉ thấy phần nội dung đầu tiên. Giải pháp chuẩn là duy trì song song một hệ thống phân trang có URL thật và liên kết bằng thẻ <a>, trong khi người dùng vẫn được trải nghiệm cuộn liên tục. Đây là mô hình mà hầu hết các sàn thương mại điện tử lớn đang áp dụng.

Dùng dịch vụ prerender bên thứ ba có an toàn không?

An toàn nếu nội dung bản prerender giống hệt nội dung người dùng thật nhìn thấy. Rủi ro nằm ở khâu vận hành: bản prerender bị cache quá lâu dẫn tới nội dung lỗi thời, hoặc dịch vụ gặp sự cố khiến Googlebot nhận trang rỗng mà bạn không hay biết. Nếu dùng, hãy thiết lập cảnh báo tự động cho tình huống dịch vụ trả về nội dung bất thường, và xem đây là giải pháp tạm thời trong lúc chuyển sang SSR.

Tôi nên ưu tiên sửa lỗi nào trước nếu nguồn lực có hạn?

Theo đúng thứ tự: gỡ chặn JS/CSS trong robots.txt, sửa thẻ noindex và canonical sinh sai phía client, thay liên kết onClick bằng thẻ <a href>, rồi mới tới chuyển kiểu render. Ba việc đầu thường chỉ tốn vài ngày công nhưng gỡ được phần lớn thiệt hại, trong khi việc thứ tư tốn hàng tuần.

Kết luận và bước tiếp theo

JavaScript SEO không phải cuộc chiến giữa “dùng JavaScript” và “không dùng JavaScript”. Bạn hoàn toàn có thể xây dựng một website hiện đại, mượt mà bằng React hay Vue mà vẫn lên top Google — điều kiện duy nhất là nội dung quan trọng phải có mặt trong HTML mà máy chủ trả về, còn JavaScript chỉ đảm nhiệm phần tương tác nâng cao phía trên.

Nếu bạn chỉ có thời gian làm một việc sau khi đọc xong bài này, hãy làm việc sau: mở website của bạn, tắt JavaScript trong DevTools rồi tải lại trang chủ và một trang chi tiết bất kỳ. Những gì còn hiển thị chính là phần nội dung mà Google chắc chắn thấy được ngay lập tức, không cần chờ hàng đợi render. Nếu màn hình gần như trắng, bạn đã biết chính xác việc cần ưu tiên trong tháng tới.

Sau đó, hãy đi theo đúng lộ trình 30 ngày ở trên: chẩn đoán trước, gỡ các lỗi chặn trước, sửa liên kết, rồi mới chuyển kiểu render. Và đừng quên bước cuối cùng mà rất nhiều đội kỹ thuật bỏ sót — sau khi trang đã render đúng, nó vẫn cần được liên kết từ những trang đã index thì Googlebot mới có lý do quay lại. Kỹ thuật tốt và tín hiệu thu thập tốt phải đi cùng nhau thì traffic organic mới thực sự tăng.

Cần tăng traffic user thật cho website? Traffic Thật cung cấp traffic từ người dùng thật 100% — an toàn cho SEO, đối soát qua Google Analytics, chỉ trừ tiền lượt hợp lệ.
Xem bảng giá

Minh Anh

Cần tư vấn SEO & traffic? Chat với em nhé!