Bỏ qua tới nội dung

Site dựng bằng JavaScript: Google đọc được gì và khi nào cần dựng sẵn phía máy chủ

Google chạy được JavaScript, nhưng chỉ thấy nội dung hiện ra không cần bấm hay cuộn, đi theo thẻ a có href và cần mỗi trang có URL riêng. Bot xem trước của Facebook, Zalo và nhiều bot AI không chạy JavaScript, nên trang nhận lượt tìm kiếm nên trả HTML đủ nội dung ngay từ máy chủ.

Ban biên tập SEO Gốc · · 6 phút đọc

Google đọc được trang dựng bằng JavaScript: Googlebot chạy một bản Chrome luôn cập nhật để dựng trang trước khi lập chỉ mục. Nhưng "đọc được" có điều kiện. Nội dung phải hiện ra mà không cần bấm, cuộn hay đăng nhập, mỗi trang phải có URL riêng thật sự, liên kết phải là thẻ <a href>, và những tín hiệu quan trọng như noindex, canonical, title nên có sẵn trong HTML máy chủ trả về. Ngoài Google, phần lớn những máy khác đọc site của bạn, như bot xem trước liên kết của Facebook, Zalo và nhiều bot AI, không chạy JavaScript. Với chúng, một trang chỉ có khung rỗng và tệp app.js là trang trắng.

Google xử lý trang JavaScript qua mấy bước

  1. Thu thập: Googlebot tải HTML thô. Ở bước này nó đã đọc được robots.txt, thẻ meta robots, canonical và các liên kết có sẵn trong HTML.
  2. Xếp hàng dựng: trang được đưa vào hàng đợi để dựng bằng Chrome. Thường nhanh, nhưng không có cam kết thời gian; site lớn có hàng nghìn trang mới thì độ trễ cộng dồn.
  3. Dựng: chạy JavaScript, chờ các yêu cầu dữ liệu, lấy DOM cuối cùng. Googlebot không bấm nút, không gõ vào ô tìm kiếm, không cuộn như người dùng; nó dùng khung nhìn cao để nội dung lười tải trong vùng nhìn thấy vẫn hiện.
  4. Lập chỉ mục: dùng HTML đã dựng, phát hiện thêm liên kết mới từ đó.

Hệ quả quan trọng nhất của thứ tự này: nếu HTML thô có noindex, Google có thể dừng ngay, không dựng trang. Đoạn JavaScript định "gỡ noindex khi dữ liệu tải xong" sẽ không bao giờ được chạy. Chiều ngược lại thì chạy: JavaScript thêm noindex vào trang sẽ được tôn trọng khi Google dựng.

Bảng so sánh các cách dựng trang

CáchHTML máy chủ trả vềGoogleBot không chạy JSHợp với
Dựng phía trình duyệt (SPA thuần)Khung rỗngĐọc được sau khi dựng, chậm hơnKhông thấy gìỨng dụng sau đăng nhập, bảng điều khiển
Dựng phía máy chủ (SSR)Đủ nội dungTốtThấy đủTrang sản phẩm, danh mục, tin tức
Dựng sẵn thành tệp tĩnh (SSG)Đủ nội dungTốt nhấtThấy đủBài viết, trang giới thiệu, tài liệu
Dựng động riêng cho botĐủ nội dung cho bot, khung rỗng cho ngườiĐược, nhưng Google gọi đây là giải pháp tạm và không khuyên dùng nữaThấy đủChỉ khi không thể sửa ứng dụng

Các khung như Next.js, Nuxt, Astro, SvelteKit đều dựng phía máy chủ hoặc dựng sẵn được. Câu hỏi thực tế không phải "có dùng React được không" mà là "trang nhận lượt tìm kiếm có trả HTML đầy đủ ngay từ máy chủ không".

Lỗi hay gặp

Liên kết không phải liên kết

Thẻ <div onclick="router.push('/san-pham/a')"> hay <span> có sự kiện bấm trông như liên kết với người dùng, nhưng Google chỉ đi theo thẻ <a> có thuộc tính href chứa URL thật. Trang sản phẩm chỉ đến được qua kiểu "liên kết" này sẽ không được phát hiện, trừ khi nằm trong sitemap, và kể cả khi vào sitemap nó vẫn thiếu tín hiệu từ liên kết nội bộ.

<!-- Google không đi theo -->
<span class="link" onclick="moTrang('/san-pham/a')">Sản phẩm A</span>
<a href="javascript:void(0)" onclick="moTrang('/san-pham/a')">Sản phẩm A</a>

<!-- Google đi theo; khung vẫn chặn sự kiện để chuyển trang mượt -->
<a href="/san-pham/a">Sản phẩm A</a>

Định tuyến bằng dấu thăng

Địa chỉ dạng vidu.com/#/san-pham/a: Google bỏ qua phần sau dấu #, coi mọi "trang" là một URL duy nhất. Dùng định tuyến theo đường dẫn (History API) để mỗi trang có địa chỉ riêng mà máy chủ trả được.

Mọi đường dẫn đều trả 200

Ứng dụng một trang thường cấu hình máy chủ trả index.html cho mọi URL, rồi JavaScript vẽ chữ "Không tìm thấy". Máy chủ đã trả 200 nên Google thấy hàng loạt trang lỗi có mã thành công, xếp vào "soft 404" hoặc tệ hơn là lập chỉ mục chúng. Cách sửa: máy chủ trả 404 thật cho đường dẫn không tồn tại, hoặc ít nhất JavaScript thêm noindex vào trang lỗi. Cùng lỗi cấu hình này còn làm /robots.txt và /sitemap.xml trả về trang HTML, như bài robots.txt đã nói.

Nội dung sau nút "Xem thêm" hoặc cuộn vô tận

Phần mô tả sản phẩm chỉ tải khi bấm tab "Thông số", danh sách bài chỉ tải thêm khi cuộn: Google không bấm, không cuộn để gọi dữ liệu, nên phần đó không tồn tại với nó. Nội dung cần được tìm thấy thì phải có trong DOM ngay khi tải (ẩn bằng CSS trong tab vẫn được), còn danh sách dài phải có trang phân trang với URL riêng, kiểu /tin-tuc?trang=2, liên kết bằng thẻ <a>.

Title và canonical do JavaScript đổi

HTML thô mang title chung "Ứng dụng" và canonical trỏ trang chủ, JavaScript sau đó đổi lại cho đúng. Google thường dùng bản đã dựng, nhưng hai tín hiệu khác nhau giữa lúc thu thập và lúc dựng là nguồn kết quả khó đoán, và mọi bot không chạy JS chỉ thấy bản sai. Đặt title, meta description, canonical, Open Graph đúng ngay từ máy chủ; xem bài thẻ canonical và Open Graph.

Chặn tệp JavaScript hoặc API trong robots.txt

Google cần tải được tệp .js và các đường API mà trang gọi để dựng. Chặn /api/ trong robots.txt là trang dựng ra rỗng với Google dù người dùng thấy đủ.

Ảnh lười tải chỉ có data-src

Thư viện lười tải đời cũ để ảnh ở thuộc tính data-src và chỉ đổi sang src khi bắt được sự kiện cuộn. Googlebot không cuộn như người, nên ảnh có thể không bao giờ được nạp, mất luôn cơ hội lên tìm kiếm hình ảnh. Thuộc tính gốc loading="lazy" của trình duyệt, hoặc thư viện dùng IntersectionObserver, thì an toàn; trong mọi trường hợp, đừng lười tải ảnh đầu trang.

Những việc không cần làm

  • Không cần viết lại toàn bộ ứng dụng nếu chỉ vài nhóm trang cần tìm kiếm. Dựng phía máy chủ hoặc dựng sẵn cho trang công khai, giữ phần sau đăng nhập là ứng dụng một trang.
  • Không cần dựng động riêng cho Googlebot nếu đã dựng phía máy chủ được; phục vụ nội dung khác nhau cho bot và người là cách tạm, dễ lệch và tốn công giữ.
  • Không cần lo Google không hiểu cú pháp JavaScript mới: Chrome dùng để dựng được cập nhật theo bản ổn định.

Cách kiểm site của bạn trong 10 phút

  1. Xem mã nguồn, không xem phần tử. Mở view-source: (hoặc Ctrl+U) chứ không phải công cụ Kiểm tra phần tử, vì công cụ kiểm tra hiện DOM sau khi JavaScript đã chạy. Tìm một câu trong nội dung chính: có trong mã nguồn là HTML thô đã đủ.
  2. Tải bằng dòng lệnh: curl -s https://vidu.com/san-pham/a | grep -c "tên sản phẩm". Kết quả 0 nghĩa là nội dung phụ thuộc JavaScript.
  3. Dùng Kiểm tra URL trong Search Console, chạy kiểm tra trực tiếp, xem HTML đã dựng và ảnh chụp màn hình: đó là thứ Google thấy sau khi dựng.
  4. Dán liên kết vào Zalo hoặc Facebook: bản xem trước không có tiêu đề, ảnh đúng nghĩa là Open Graph đang do JavaScript chèn.
  5. Thử đường dẫn bậy như /khong-co-trang-nay: phải trả mã 404, không phải 200.

Kiểm bằng SEO Gốc

Công cụ chấm điểm đọc HTML thô như bot không chạy JavaScript, không dựng trang. Vì vậy nếu site của bạn hiện đầy chữ trên trình duyệt mà công cụ báo trang chủ mỏng, thiếu H1 hay thiếu title, đó gần như chắc chắn là dấu hiệu nội dung đang phụ thuộc JavaScript; lỗi "trang mỏng" (dưới 300 chữ, ngưỡng cảnh báo của SEO Gốc, không phải luật Google) đặc biệt hay xuất hiện ở ứng dụng một trang. Muốn biết bot AI có đọc được site không, dùng thêm kiểm bot AI. Tài liệu chính chủ về JavaScript và tìm kiếm ở Google Search Central.

Hỏi đáp

Google có đọc được site React, Vue không?

Đọc được, vì Googlebot dựng trang bằng Chrome. Nhưng nội dung phải hiện mà không cần tương tác, liên kết phải là thẻ a có href, mỗi trang có URL riêng. Trang công khai cần lên tìm kiếm nên dựng phía máy chủ hoặc dựng sẵn để chắc ăn và nhanh hơn.

Vì sao xem trên trình duyệt có chữ mà công cụ báo trang mỏng?

Công cụ đọc HTML thô máy chủ trả về, không chạy JavaScript. Nếu chữ chỉ xuất hiện sau khi JavaScript chạy, HTML thô gần như rỗng. Đó cũng là thứ Facebook, Zalo và nhiều bot AI nhìn thấy.

Có thể gỡ noindex bằng JavaScript không?

Không nên dựa vào. Khi HTML thô có noindex, Google có thể bỏ qua bước dựng trang, nên đoạn mã gỡ noindex không được chạy. Hãy để máy chủ trả đúng thẻ robots ngay từ đầu.

Dựng động riêng cho bot có bị coi là che giấu không?

Nếu nội dung bot và người thấy là như nhau thì không bị coi là che giấu, nhưng Google gọi đây là giải pháp tạm thời và không còn khuyên dùng. Dựng phía máy chủ hoặc dựng sẵn bền hơn.

Đọc tiếp