Cách xây dựng phân tích SEO cho trang web đa ngôn ngữ với GSC API và BigQuery

Cách xây dựng phân tích SEO cho trang web đa ngôn ngữ với GSC API và BigQuery
Markus_automation
Markus_automation

Expert in data parsing and automation

Đối với các dự án đa ngôn ngữ, nhiệm vụ tổng hợp phân tích SEO nhanh chóng vượt quá khả năng của các giao diện web tiêu chuẩn. Càng nhiều phiên bản ngôn ngữ, khu vực và URL liên quan đến phân tích, khối lượng dữ liệu và số lượng chiều cần thu thập, chuẩn hóa và khớp với nhau càng lớn.

Với các dự án nhỏ hơn, nhiệm vụ này có thể được xử lý bằng cách xuất dữ liệu thủ công và các báo cáo có sẵn. Khi một dự án mở rộng quy mô lên hàng chục ngôn ngữ, phương pháp này trở nên kém hiệu quả: một chuyên gia phải dành một lượng thời gian đáng kể để thu thập và chuẩn bị dữ liệu thay vì phân tích nó. Các giới hạn của chính giao diện phân tích tạo ra thêm các rào cản phụ. Ví dụ: Google Search Console hiển thị số lượng hàng hạn chế, không đủ cho các dự án có hàng chục hoặc hàng trăm nghìn URL.

Đó là lý do tại sao, đối với các trang web đa ngôn ngữ lớn, việc chuyển việc thu thập và xử lý các chỉ số SEO sang cấp độ mã hóa là điều hợp lý. Điều này cho phép bạn tự động hóa việc xuất dữ liệu định kỳ, duy trì mức độ chi tiết cần thiết của chỉ số và xây dựng một hệ thống giám sát ít phụ thuộc hơn vào các giới hạn của giao diện dựa trên trình duyệt. Trong bài viết này, chúng ta sẽ xem xét cách tổ chức một kiến trúc như vậy cho một dự án đa ngôn ngữ và những giới hạn của Google Search Console API nào bạn cần lưu ý khi triển khai.

Nội dung

Duy trì danh tính ẩn trực tuyến của bạn với Octo Browser. Dấu vân tay số thật của bạn sẽ không thể bị truy vết.

Bạn muốn thử Octo Browser với giá ưu đãi không?
Sử dụng mã khuyến mãi OCTOBLOG để được giảm giá 30% cho bất kỳ gói đăng ký nào. Ưu đãi này chỉ dành cho người dùng mới.

Tại sao nên chuyển hướng khỏi giao diện web

Một hệ thống phân tích SEO đáng tin cậy bắt đầu bằng việc loại bỏ thao tác xuất dữ liệu thủ công. Giao diện Google Search Console thuận tiện cho việc kiểm tra nhanh một số chỉ số nhất định, nhưng khả năng của nó không đủ để phân tích sản phẩm chuyên sâu.

GSC API giúp có thể lấy dữ liệu ở cấp độ chi tiết hơn—theo từng URL, truy vấn tìm kiếm riêng lẻ và các khía cạnh khác. Điều này cho phép bạn không chỉ làm việc với các báo cáo tổng hợp mà còn với dữ liệu cơ sở mà từ đó bạn có thể tự xây dựng các phần phân tích và chỉ số của riêng mình.

Để hiểu được những lợi thế của kiến trúc này, điều quan trọng là phải xem xét một số yếu tố chính.

Số lượng thuộc tính dữ liệu và các hạn chế của giao diện web

Một trong những vấn đề chính của giao diện GSC là lượng dữ liệu hiển thị bị hạn chế. Điều này đặc biệt nghiêm trọng đối với một dự án đa ngôn ngữ: khi có số lượng lớn trang, quốc gia, thiết bị và truy vấn, một phần đáng kể thông tin sẽ nằm ngoài báo cáo tiêu chuẩn.

Đây là lúc số lượng thuộc tính dữ liệu (cardinality) trở nên quan trọng—số lượng tổ hợp tham số duy nhất trong một tập dữ liệu. Ví dụ: nếu một trang web hoạt động bằng 10 ngôn ngữ, nhận lưu lượng truy cập từ 50 quốc gia, sử dụng 3 loại thiết bị và xếp hạng cho 10.000 truy vấn tìm kiếm, số lượng tổ hợp có thể lên tới hàng triệu dòng.

Làm việc với khối lượng dữ liệu này thông qua giao diện web thực tế là không thể. API cho phép bạn truy xuất lượng dữ liệu lớn hơn đáng kể và chia việc xuất thành các phân đoạn riêng biệt. Thông qua lọc và xử lý tuần tự, bạn không chỉ có thể thu thập phần đầu của kết quả mà còn cả phần đuôi dài (long tail) của các truy vấn và URL thường bị mất trong các báo cáo tiêu chuẩn.

Hồ chứa dữ liệu (Data Lake) và lưu trữ lịch sử

Google Search Console chỉ lưu trữ dữ liệu lịch sử trong giao diện của nó trong 16 tháng qua, điều này không đủ cho phân tích SEO dài hạn.

Một kho dữ liệu chuyên dụng, chẳng hạn như BigQuery, sẽ giải quyết vấn đề này. Bạn có thể thường xuyên lưu dữ liệu thô thu được qua API ở đó mà không bị giới hạn bởi thời gian lưu trữ trong giao diện GSC. Điều này mang lại cho bạn một cơ sở dữ liệu SEO lịch sử có thể được sử dụng để phân tích dài hạn, xây dựng báo cáo và xử lý lại dữ liệu theo bất kỳ khía cạnh cần thiết nào.

Sự phụ thuộc vào các dịch vụ bên ngoài và chi phí mở rộng

Các cổng kết nối ETL có sẵn có thể được sử dụng để tự động hóa việc xuất dữ liệu, ví dụ: các dịch vụ SaaS như Supermetrics hoặc Fivetran. Chúng cho phép bạn thiết lập truyền dữ liệu nhanh chóng mà không cần tự phát triển nội bộ, nhưng khi dự án mở rộng, cách tiếp cận này có thể trở nên tốn kém và ràng buộc cơ sở hạ tầng của bạn quá chặt chẽ vào một dịch vụ cụ thể.

Các nền tảng SaaS tính phí dịch vụ của họ dựa trên khối lượng dòng được xử lý hoặc số lượng cổng kết nối. Khi dự án đa ngôn ngữ của bạn bắt đầu tạo ra hàng gigabyte dữ liệu SEO thô mỗi ngày, chi phí của dịch vụ đó có thể vượt quá chi phí lưu trữ dữ liệu trong BigQuery và thuê một máy chủ nhỏ cho các tập lệnh Python gấp vài lần.

Hơn nữa, một dịch vụ càng được tích hợp sâu vào quy trình thu thập và chuyển đổi dữ liệu thì sau này càng khó thay thế: việc di chuyển có thể yêu cầu định cấu hình lại các cổng kết nối, logic xử lý và báo cáo.

Cấp độ chi tiết của dữ liệu

Khi thu thập dữ liệu qua API, điều quan trọng là phải giữ nguyên càng nhiều chi tiết càng tốt. Nếu bạn kết hợp dữ liệu ngay tại giai đoạn xuất, bạn sẽ không thể tái cấu trúc các khía cạnh ban đầu sau này.

Ví dụ: khi thiết kế cơ sở dữ liệu SEO, bạn nên lưu trữ riêng các tham số như loại DeviceCountry. Nếu tập lệnh yêu cầu dữ liệu mà không có phân tích theo quốc gia, GSC sẽ trả về tổng số lượt nhấp cho truy vấn đó. Sau đó, không thể xác định được bao nhiêu lượt nhấp đến từ Đức và bao nhiêu lượt đến từ Pháp.

Đó là lý do tại sao tốt hơn nên lưu trữ dữ liệu ở dạng chi tiết và chỉ kết hợp dữ liệu đó cũng như tính toán các chỉ số cuối cùng ở giai đoạn phân tích hoặc trực quan hóa. Điều này bảo toàn khả năng xây dựng bất kỳ phần phân tích dữ liệu cần thiết nào trong tương lai, ngay cả khi ban đầu chúng không được dự tính trong các báo cáo.

Các hạn chế của GSC API khi xuất lượng dữ liệu lớn

Thoạt nhìn, làm việc với GSC API có vẻ đơn giản: ủy quyền tập lệnh, truy xuất dữ liệu, lưu dữ liệu vào cơ sở dữ liệu và chuyển sang phân tích. Trên thực tế, các dự án lớn nhanh chóng vấp phải các giới hạn kỹ thuật của API.

Nếu bạn cố gắng xuất lượng dữ liệu lớn mà không tính đến các hạn chế này, bạn có thể gặp phải lỗi hết thời gian chờ, lỗi 429 Too Many Requests và xuất không hoàn chỉnh. Do đó, chỉ một phần dữ liệu sẽ đến được kho dữ liệu và bản thân hệ thống sẽ trở nên không ổn định.

Đó là lý do tại sao quy trình xử lý nên tính trước các giới hạn API, độ trễ cập nhật dữ liệu, hạn ngạch truy vấn và cơ chế thử lại cho các yêu cầu không thành công. Hãy cùng xem xét các hạn chế chính của GSC API và cách làm việc với chúng một cách chính xác.

Hạn chế 50.000 dòng và phân đoạn xuất

Theo tài liệu của Google, tham số rowLimit cho phép bạn truy xuất không quá 25.000 dòng trong một yêu cầu duy nhất. Tham số startRow được sử dụng để phân trang: ban đầu bạn có thể yêu cầu 25.000 dòng đầu tiên và sau đó là 25.000 dòng tiếp theo.

Tuy nhiên, có một hạn chế bổ sung: tổng của startRow + rowLimit không thể vượt quá 50.000. Do đó, đối với một ngày duy nhất và một tổ hợp tham số đã chọn, bạn không thể truy xuất dòng thứ 50.001 theo cách này.

Nếu số lượng thuộc tính dữ liệu hàng ngày của bạn vượt quá 50.000 dòng, bạn cần chia việc xuất thành các phân đoạn riêng biệt bằng cách sử dụng Bộ lọc Thứ nguyên (Dimension Filters). Ví dụ: bạn có thể truy vấn dữ liệu riêng biệt cho các thư mục ngôn ngữ — /de/, /fr/, v.v., hoặc chia thêm các URL theo các mẫu bằng cách sử dụng biểu thức chính quy (regular expressions).

Điều này cho phép bạn có được tập dữ liệu hoàn chỉnh thông qua một số yêu cầu độc lập nhắm vào các phân đoạn dữ liệu khác nhau.

Độ trễ dữ liệu và làm việc với dataState

GSC API có độ trễ cập nhật dữ liệu mang tính hệ thống từ 48 đến 72 giờ. Do đó, khi xuất dữ liệu hàng ngày, điều quan trọng là phải phân biệt giữa dữ liệu sơ bộ và dữ liệu cuối cùng.

Tham số dataState kiểm soát điều này. Nó có hai giá trị:

  • "final" (mặc định) — chỉ trả về dữ liệu đã được tổng hợp và xác thực đầy đủ.

  • "all" — bao gồm dữ liệu mới chưa qua xử lý cuối cùng.

Điều này tạo ra sự đánh đổi giữa tốc độ và độ chính xác khi xây dựng quy trình xử lý. Hãy cùng xem xét cả hai kịch bản.

  • Sử dụng dataState: "final" (hành vi mặc định). Ở chế độ này, dữ liệu trong 24 giờ qua có thể chưa khả dụng. Nếu tập lệnh của bạn cố gắng xuất yesterday bằng giá trị mặc định, API sẽ trả về một mảng trống. Bạn cần áp dụng một khoảng bù cố định là current_date — 3 ngày.

  • Sử dụng dataState: "all". Bạn sẽ nhận được tập dữ liệu cần thiết cho 24 giờ trước đó. Tuy nhiên, Google cảnh báo rằng dữ liệu mới chỉ là dữ liệu sơ bộ. Hệ thống chưa hợp nhất tất cả các bản trùng lặp, lọc bỏ các bot spam hoặc tính toán lại các bất thường. Sau 2–3 ngày, các số liệu này sẽ thay đổi trên chính máy chủ của Google.

Điều này có thể ảnh hưởng đến kiến trúc lưu trữ của bạn như thế nào: nếu tập lệnh Python của bạn chỉ đơn giản là thêm dữ liệu thô mới vào BigQuery, cơ sở dữ liệu lịch sử của bạn sẽ bị bóp méo. Khi bạn ghi các chỉ số "mới", bạn đang lưu trữ một bản nháp sẽ không bao giờ khớp chính xác với các báo cáo cuối cùng trong giao diện GSC.

Do đó, đối với phân tích hoạt động, tốt hơn là sử dụng cách tiếp cận hai giai đoạn:

  1. Xuất dữ liệu cho ngày hôm trước bằng dataState: "all".

  2. Đồng thời, tập lệnh sẽ xuất lại dữ liệu cho current_date — 4 ngày bằng cách sử dụng dataState: "final".

  3. Trong BigQuery, thay vì Append đơn giản, hãy sử dụng toán tử MERGE (hoặc logic Upsert). Tập lệnh sẽ tìm dữ liệu sơ bộ từ bốn ngày trước đó trong cơ sở dữ liệu và ghi đè bằng các giá trị cuối cùng đã được hợp nhất.

Cách tiếp cận này cho phép bạn xem các chỉ số mới trên bảng điều khiển trong khi vẫn bảo toàn cơ sở dữ liệu lịch sử chính xác sau khi xử lý dữ liệu cuối cùng.

Hạn chế API và thuật toán giảm tải theo cấp số nhân (exponential backoff)

GSC API giới hạn số lượng yêu cầu để bảo vệ cơ sở hạ tầng của mình khỏi tải quá mức. GSC API có các hạn ngạch nghiêm ngặt: 50 truy vấn mỗi giây (QPS) và 1.200 truy vấn mỗi phút (QPM) cho mỗi dự án. Do đó, các hạn chế này cần được tính đến trước khi thực hiện xuất trên quy mô lớn.

Vấn đề đặc biệt dễ nhận thấy khi dữ liệu phải được chia thành hàng trăm phân đoạn để vượt qua giới hạn 50.000 dòng. Để tăng tốc quá trình, các nhà phát triển thường sử dụng các yêu cầu không đồng bộ (asyncio) hoặc các nhóm luồng (ThreadPoolExecutor). Nhưng điều này có thể nhanh chóng làm cạn kiệt giới hạn 50 QPS và API bắt đầu trả về lỗi 429 Too Many Requests hoặc 503 Service Unavailable.

Một khoảng trễ đơn giản bằng cách sử dụng time.sleep() không hoạt động hiệu quả ở đây. Nếu một vài luồng song song nhận được lỗi cùng một lúc và sau đó tạm dừng trong cùng một khoảng thời gian, chúng sẽ tiếp tục hầu như đồng thời và tạo ra một đỉnh đột biến lưu lượng truy cập khác.

Kiến trúc tập lệnh chính xác nên bao gồm một mẫu giảm tải theo cấp số nhân với nhiễu ngẫu nhiên được thêm vào (Jitter). Điều này làm cho khoảng thời gian giữa các yêu cầu thử lại tăng dần. Không phải tất cả các luồng sẽ thử lại cùng một lúc, làm giảm khả năng chúng vượt quá giới hạn.

Trong Python, bạn không nhất thiết phải triển khai logic này theo cách thủ công: bạn có thể sử dụng các hàm trang trí (decorators) từ thư viện tenacity.

Thu thập dữ liệu SEO cho các tên miền phụ và thư mục ngôn ngữ

Sau khi tính đến các giới hạn và độ trễ của GSC API, câu hỏi quan trọng tiếp theo là trang web đa ngôn ngữ được cấu trúc chính xác như thế nào. Cấu trúc dự án ảnh hưởng trực tiếp đến logic xuất, chuẩn hóa và kết hợp dữ liệu.

Trong SEO đa ngôn ngữ, có hai cách tiếp cận đối lập đối với cấu trúc trang web: tên miền phụ quốc gia và thư mục ngôn ngữ. Đối với người dùng, sự khác biệt là tối thiểu, nhưng đối với việc xây dựng các bản xuất, các cấu trúc khác nhau có thể thay đổi hoàn toàn cách tiếp cận.

Tên miền phụ và các tên miền riêng biệt

Nếu các phiên bản ngôn ngữ được lưu trữ trên các tên miền riêng biệt (site.de, site.fr) hoặc các tên miền phụ (de.site.com, fr.site.com), dữ liệu cho mỗi phiên bản phải được thu thập dưới dạng dữ liệu từ một tài nguyên riêng biệt.

Tại sao điều này lại hữu ích cho doanh nghiệp? Sự cô lập theo khu vực cho phép bạn kiểm soát ngân sách thu thập dữ liệu (crawl budget) một cách nghiêm ngặt hơn. Công cụ tìm kiếm sẽ không chi tiêu ngân sách thu thập dữ liệu của bot Đức để quét phiên bản tiếng Pháp của trang web. Từ góc độ SEO, đây là con đường an toàn nhất để mở rộng quy mô.

Đối với quy trình phân tích, điều này tạo ra hai vấn đề:

  • Nhiều điểm kết nối hơn. Nếu dự án có 10 phiên bản ngôn ngữ, tập lệnh cần truy vấn nhiều tài nguyên GSC một cách tuần tự hoặc song song. Càng có nhiều nguồn, thì hạn ngạch API, xử lý lỗi và khả năng phục hồi của toàn bộ kiến trúc xuất càng trở nên quan trọng.

  • Độ phức tạp của việc chuẩn hóa URL (ghép nối dữ liệu với nhau). Các trang phục vụ cùng một mục đích trên các tên miền khác nhau sẽ có các địa chỉ khác nhau—ví dụ: site.de/productsite.fr/product. Để so sánh hiệu suất của chúng như một thực thể duy nhất, các URL của chúng cần được chuẩn hóa.

Trong thư viện Pandas dành cho Python, việc chuẩn hóa này trông như thế này:

import pandas as pd
from urllib.parse import urlparse

# Chỉ giữ lại đường dẫn để ghép nối các chỉ số giữa các quốc gia
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Kết quả: /product
import pandas as pd
from urllib.parse import urlparse

# Chỉ giữ lại đường dẫn để ghép nối các chỉ số giữa các quốc gia
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Kết quả: /product

Nếu không có sự chuẩn hóa này, các chỉ số cho các bản địa hóa khác nhau sẽ vẫn bị tách biệt trên các URL khác nhau. Điều này sẽ khiến việc tính toán hiệu suất tổng thể của cùng một trang hoặc mẫu bằng các ngôn ngữ khác nhau trở nên khó khăn hơn.

Thư mục ngôn ngữ và phân đoạn dữ liệu

Nếu các phiên bản ngôn ngữ được đặt trong các thư mục, ví dụ: site.com/de/site.com/fr/, toàn bộ dự án vẫn nằm trong một tên miền duy nhất. Điều này giúp đơn giản hóa việc thu thập dữ liệu: thay vì thực hiện các yêu cầu riêng biệt đến nhiều tài nguyên, bạn có thể làm việc với một Domain Property duy nhất trong Google Search Console.

Thay vì 10 truy vấn riêng biệt, bạn có thể thực hiện một lần xuất lớn, sử dụng tính năng lọc để vượt qua giới hạn 50.000 dòng. Điều này giúp tiết kiệm hạn ngạch Google API và giảm tải mạng.

Các bản xuất lớn vẫn cần được chia thành các phân đoạn. Nhưng bản thân kiến trúc trở nên đơn giản hơn: ít điểm kết nối hơn, ít yêu cầu hơn và tải API thấp hơn.

Bởi vì API cung cấp cho chúng ta một luồng URL liên tục, tập lệnh phải tự gán các dấu mốc quốc gia cho các dòng. Điều này được thực hiện bằng cách sử dụng biểu thức chính quy (RegEx).

Sử dụng thư viện Pandas, chúng ta có thể trích xuất dấu mốc ngôn ngữ trực tiếp từ URL:

df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Xử ngoại lệ: nếu RegEx trả về NaN, đây phiên bản chính của trang web
df['language_market'].fillna('en', inplace=True)
df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Xử ngoại lệ: nếu RegEx trả về NaN, đây phiên bản chính của trang web
df['language_market'].fillna('en', inplace=True)

Điều này cho phép bạn trích xuất dấu mốc de từ một URL như site.com/de/product và sử dụng nó để phân tích thêm.

Hạn chế chính của cách tiếp cận này là sự phụ thuộc vào cấu trúc URL. Biểu thức chính quy phải khớp chính xác với các quy tắc được sử dụng để xây dựng các phiên bản ngôn ngữ. Nếu một số trang sử dụng một mẫu khác, chẳng hạn như site.com/category-de/product, các URL đó có thể bị phân loại sai hoặc hoàn toàn không đi vào phân đoạn yêu cầu.

Đó là lý do tại sao, trước khi định cấu hình RegEx, điều quan trọng là phải kiểm tra tất cả các mẫu URL ngôn ngữ có thể có và xử lý các ngoại lệ một cách riêng biệt.

Chuyển đổi dữ liệu và tính toán chỉ số trong Pandas

Sau khi thu thập và chuẩn hóa dữ liệu, dữ liệu đó cần được kết hợp và chuẩn bị để phân tích. Pandas rất thuận tiện cho việc này: thư viện giúp có thể làm việc với các bảng lớn, kết hợp các nguồn và tính toán các chỉ số ở cả cấp độ dòng và cấp độ nhóm.

Kết hợp dữ liệu GSC và GA4 theo URL

Google Search Console hiển thị các chỉ số tìm kiếm—số lượt hiển thị, lượt nhấp, CTR và vị trí. GA4 bổ sung cho các chỉ số này bằng các chỉ số hành vi và kinh doanh, chẳng hạn như số phiên và lượt chuyển đổi.

Để có được bức tranh hoàn chỉnh hơn về hiệu suất lưu lượng truy cập SEO, dữ liệu GSC và GA4 có thể được kết hợp bằng cách sử dụng một khóa chung—URL trang đích đã được chuẩn hóa.

Trong Pandas, điều này được thực hiện bằng cách tham gia các bảng bằng một khóa chung, URL đã chuẩn hóa:

import pandas as pd

# df_gsc xuất từ Search Console
# df_ga4 xuất từ GA4 (Phiên, Chuyển đổi)

# Liên kết dữ liệu theo trang đích (Left Join để các trang không lưu lượng truy cập không bị mất)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Giờ đây chúng ta thể tính tỷ lệ chuyển đổi của một cụm SEO cụ thể:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100
import pandas as pd

# df_gsc xuất từ Search Console
# df_ga4 xuất từ GA4 (Phiên, Chuyển đổi)

# Liên kết dữ liệu theo trang đích (Left Join để các trang không lưu lượng truy cập không bị mất)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Giờ đây chúng ta thể tính tỷ lệ chuyển đổi của một cụm SEO cụ thể:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100

Tính toán chính xác CTR và vị trí trung bình

Khi kết hợp dữ liệu từ nhiều phiên bản ngôn ngữ, bạn không thể tính CTR và vị trí trung bình chỉ bằng cách sử dụng số trung bình cộng. Điều này làm sai lệch kết quả vì nó không tính đến khối lượng hiển thị khác nhau.

Ví dụ:

  • Tên miền phụ tiếng Pháp: 2 lượt nhấp trên 4 lượt hiển thị, CTR = 50%;

  • Tên miền phụ tiếng Đức: 20 lượt nhấp trên 1.000 lượt hiển thị, CTR = 2%.

Nếu bạn chỉ đơn giản tính trung bình các giá trị CTR, bạn sẽ có được:

(50% + 2%) / 2 = 26%

Nhưng CTR thực tế trên hai tên miền phụ là:

22 lượt nhấp / 1004 lượt hiển thị = 2,19%

Do đó, khi tổng hợp dữ liệu từ các bản địa hóa khác nhau, các chỉ số cần được tính toán lại từ các giá trị cơ sở:

  • CTR được tính bằng tỷ lệ giữa tổng số lượt nhấp trên tổng số lượt hiển thị.

  • Vị trí trung bình nên được tính trọng số theo lượt hiển thị: vị trí của mỗi dòng được nhân với số lượt hiển thị, và tổng của các giá trị này sau đó được chia cho tổng số lượt hiển thị.

Trong Pandas, điều này có thể được triển khai như sau:

# Nhóm dữ liệu theo truy vấn tìm kiếm trên tất cả các quốc gia
def weighted_metrics(x):
    # Vị trí trung bình trọng số = Sum (Vị trí * Lượt hiển thị) / Sum (Lượt hiển thị)
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # CTR thực tế
    real_ctr = (x['clicks'].sum() / x['impressions'].sum()) * 100
    
    return pd.Series({
        'total_clicks': x['clicks'].sum(),
        'total_impressions': x['impressions'].sum(),
        'weighted_position': weighted_pos,
        'real_ctr': real_ctr
    })

# Áp dụng hàm cho dataframe đã được nhóm
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)
# Nhóm dữ liệu theo truy vấn tìm kiếm trên tất cả các quốc gia
def weighted_metrics(x):
    # Vị trí trung bình trọng số = Sum (Vị trí * Lượt hiển thị) / Sum (Lượt hiển thị)
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # CTR thực tế
    real_ctr = (x['clicks'].sum() / x['impressions'].sum()) * 100
    
    return pd.Series({
        'total_clicks': x['clicks'].sum(),
        'total_impressions': x['impressions'].sum(),
        'weighted_position': weighted_pos,
        'real_ctr': real_ctr
    })

# Áp dụng hàm cho dataframe đã được nhóm
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)

Tự động hóa hreflang và giám sát ăn bớt lưu lượng truy cập (cannibalization)

Một kho dữ liệu chuyên dụng có thể được sử dụng không chỉ để báo cáo mà còn để tự động phát hiện các vấn đề SEO kỹ thuật. Hai loại vấn đề đặc biệt quan trọng đối với các dự án đa ngôn ngữ: mối quan hệ bản địa hóa bị hỏng và sự cạnh tranh nội bộ giữa nhiều trang cho cùng một nhu cầu tìm kiếm.

Giám sát hreflang tự động

Tối ưu hóa SEO kỹ thuật cho các dự án quốc tế dựa trên tính nhất quán và tính hai chiều của các thẻ bản địa hóa. Thẻ hreflang hoạt động như một hệ thống tham chiếu chéo hai chiều nghiêm ngặt. Ví dụ: nếu một trang tiếng Pháp trỏ đến một trang tiếng Đức như một giải pháp thay thế, trang tiếng Đức phải chứa một liên kết đối ứng. Phá vỡ chuỗi này sẽ phá vỡ toàn bộ cụm trong mắt Google.

Với một dự án lớn, việc kiểm tra các liên kết này một cách thủ công là không thể, vì vậy việc giám sát nên dựa trên việc so sánh ít nhất hai nguồn dữ liệu:

  • Screaming Frog. Chạy trình thu thập thông tin theo lịch trình. Nó quét sự hiện diện thực tế của các thẻ trong mã HTML và xác thực mã ngôn ngữ (ISO 639-1) và mã quốc gia (ISO 3166-1 Alpha 2). Kết quả được xuất sang cơ sở dữ liệu.

  • GSC API. Search Console API cung cấp báo cáo lập chỉ mục và cho thấy cách Google diễn giải các mối quan hệ này trong lần thu thập thông tin mới nhất của nó.

Kết quả thu thập thông tin và dữ liệu Google có thể được lưu trữ trong cùng một cơ sở dữ liệu và sau đó được so khớp bằng SQL. Ví dụ: FULL OUTER JOIN có thể xác định các lỗi nghiêm trọng trong dữ liệu tổng hợp: các trang về mặt kỹ thuật có thẻ chính xác trong mã của chúng nhưng đã bị công cụ tìm kiếm bỏ qua.

Có thể có nhiều lý do cho việc này. Một khả năng là kết xuất phía máy khách (client-side rendering): các khung JavaScript (React, Vue) mất quá nhiều thời gian để kết xuất các thẻ trong <head>, hoặc các chỉ số hiệu suất (Core Web Vitals) kém đến mức Googlebot hết thời gian chờ trước khi có thể đọc hreflang. Tự động hóa sẽ bắt được các vấn đề này trước khi lưu lượng truy cập bắt đầu giảm sút.

Ăn bớt lưu lượng truy cập (cannibalization) và tìm kiếm các URL xung đột

Vấn đề đa ngôn ngữ thứ hai là cạnh tranh nội bộ. Hiện tượng ăn bớt lưu lượng truy cập (cannibalization) xảy ra khi một công cụ tìm kiếm bị nhầm lẫn về mức độ liên quan và bắt đầu xếp hạng, ví dụ, phiên bản tiếng Anh của một trang cho một truy vấn từ Đức mặc dù bạn có một trang đích tiếng Đức chuyên dụng.

Những sự trùng lặp như vậy rất khó phân tích trên quy mô lớn trong giao diện GSC tiêu chuẩn. Nếu dữ liệu thô được lưu trữ trong BigQuery, hiện tượng ăn bớt lưu lượng truy cập tiềm ẩn có thể được phát hiện tự động bằng SQL.

Thuật toán phát hiện ăn bớt lưu lượng truy cập như sau:

  1. Nhóm dữ liệu theo hai tham số: querycountry.

  2. Đếm số lượng URL duy nhất (COUNT(DISTINCT page)) nhận được lượt hiển thị cho tổ hợp này.

  3. Lọc kết quả bằng cách sử dụng HAVING count > 1.

Nếu nhiều trang nhận được lượt hiển thị cho cùng một tổ hợp query + country, đây là tín hiệu của một xung đột mức độ liên quan tiềm ẩn.

Dữ liệu GSC có thể được bổ sung bằng cách kiểm tra kết quả tìm kiếm thực tế cho các khu vực liên quan. Điều này đặc biệt hữu ích khi phân tích đã xác định được một bất thường, nhưng chỉ riêng các con số thì không làm rõ được chính xác người dùng nhìn thấy gì và Google hiển thị phiên bản nào của trang ở một quốc gia cụ thể.

Chúng tôi đã đề cập đến các phương pháp tự động thu thập SERP trong một bài viết riêng. Và khi bạn cần kiểm tra thủ công các truy vấn và bản địa hóa riêng lẻ trong các môi trường khu vực khác nhau, bạn có thể sử dụng một trình duyệt chống phát hiện như Octo Browser.

Cách Octo Browser bổ sung cho phân tích SEO

GSC và BigQuery rất phù hợp để tìm kiếm các vấn đề trên khối lượng dữ liệu lớn. Chúng có thể giúp bạn nhận thấy, ví dụ, một trang tiếng Đức đã bắt đầu mất lượt hiển thị, việc bản địa hóa sai xếp hạng cho các truy vấn từ một quốc gia cụ thể hoặc một số URL đang cạnh tranh với nhau.

Nhưng sau khi tìm thấy một vấn đề như vậy, câu hỏi thường đặt ra là: người dùng thực sự nhìn thấy gì trong kết quả tìm kiếm?

Dữ liệu GSC giúp xác định một bất thường và hiểu được quy mô của nó. Để chẩn đoán một trường hợp cụ thể, việc xem xét kết quả tìm kiếm từ khu vực yêu cầu và kiểm tra xem trang web thực sự hoạt động như thế nào là rất hữu ích.

Đây là lúc Octo Browser phát huy tác dụng. Đối với các quốc gia khác nhau, bạn có thể tạo các hồ sơ riêng biệt, kết nối proxy với vị trí địa lý yêu cầu và thực hiện kiểm tra trong các phiên trình duyệt riêng biệt. Điều này rất thuận tiện khi bạn thường xuyên làm việc với một số vị trí địa lý và không muốn trộn lẫn cookie, lịch sử và dữ liệu khác giữa các lần kiểm tra.

Ví dụ: tập lệnh của chúng tôi phát hiện ra rằng URL tiếng Anh đang nhận được lượt hiển thị cho các truy vấn từ Đức mặc dù trang web có phiên bản tiếng Đức hoàn chỉnh tại /de/. Điều này không nhất thiết có nghĩa là vấn đề chắc chắn liên quan đến bản địa hóa. Đầu tiên, bạn nên kiểm tra xem điều gì đang xảy ra trong kết quả tìm kiếm thực tế.

Mở một hồ sơ Octo với proxy Đức và kiểm tra xem Google hiển thị URL nào cho truy vấn mục tiêu. Đồng thời, bạn có thể kiểm tra xem phiên bản chính xác của trang web có mở ra hay không, có tự động chuyển hướng sang ngôn ngữ khác hay không và nội dung trang có khớp với khu vực đã chọn hay không.

Bạn có thể sử dụng cùng một phương pháp để kiểm tra có chọn lọc:

  • sự xuất hiện của phiên bản ngôn ngữ sai trong SERP;

  • sự khác biệt trong kết quả tìm kiếm trên nhiều khu vực;

  • hoạt động của các chuyển hướng theo vùng;

  • việc bản địa hóa nội dung, giá cả và các yếu tố khác của trang;

  • các thay đổi sau khi sửa lỗi hreflang, canonical, hoặc liên kết nội bộ.

Bằng cách này, GSC API và BigQuery giúp xác định các trường hợp đáng ngờ trong toàn bộ dự án, trong khi Octo Browser giúp điều tra các bất thường riêng lẻ bằng cách sử dụng các vị trí địa lý yêu cầu trong các môi trường riêng biệt.

Kết luận

Chuyển phân tích SEO từ giao diện web sang hệ thống thu thập và lưu trữ dữ liệu tùy chỉnh là một bước nâng cấp lên một cấp độ quản lý dự án hoàn toàn mới.

Ban đầu, một kiến trúc như vậy đòi hỏi khắt khe về mặt kỹ thuật: bạn cần định cấu hình ủy quyền, xử lý lỗi, chuẩn hóa dữ liệu, xuất dữ liệu thường xuyên và quản lý quy trình. Nhưng kết quả là, bạn có được một hệ thống mở rộng quy mô theo dự án và không phụ thuộc vào các hạn chế của giao diện web.

Thay vì thu thập các báo cáo một cách thủ công, bạn sẽ có một cơ sở dữ liệu duy nhất chứa lịch sử nơi bạn có thể phân tích tất cả các phiên bản ngôn ngữ, tính toán lại các chỉ số một cách chính xác, xác định các vấn đề kỹ thuật và xây dựng các phần phân tích dữ liệu bạn cần mà không làm mất đi độ chi tiết.

Duy trì danh tính ẩn trực tuyến của bạn với Octo Browser. Dấu vân tay số thật của bạn sẽ không thể bị truy vết.

Bạn muốn thử Octo Browser với giá ưu đãi không?
Sử dụng mã khuyến mãi OCTOBLOG để được giảm giá 30% cho bất kỳ gói đăng ký nào. Ưu đãi này chỉ dành cho người dùng mới.

Tại sao nên chuyển hướng khỏi giao diện web

Một hệ thống phân tích SEO đáng tin cậy bắt đầu bằng việc loại bỏ thao tác xuất dữ liệu thủ công. Giao diện Google Search Console thuận tiện cho việc kiểm tra nhanh một số chỉ số nhất định, nhưng khả năng của nó không đủ để phân tích sản phẩm chuyên sâu.

GSC API giúp có thể lấy dữ liệu ở cấp độ chi tiết hơn—theo từng URL, truy vấn tìm kiếm riêng lẻ và các khía cạnh khác. Điều này cho phép bạn không chỉ làm việc với các báo cáo tổng hợp mà còn với dữ liệu cơ sở mà từ đó bạn có thể tự xây dựng các phần phân tích và chỉ số của riêng mình.

Để hiểu được những lợi thế của kiến trúc này, điều quan trọng là phải xem xét một số yếu tố chính.

Số lượng thuộc tính dữ liệu và các hạn chế của giao diện web

Một trong những vấn đề chính của giao diện GSC là lượng dữ liệu hiển thị bị hạn chế. Điều này đặc biệt nghiêm trọng đối với một dự án đa ngôn ngữ: khi có số lượng lớn trang, quốc gia, thiết bị và truy vấn, một phần đáng kể thông tin sẽ nằm ngoài báo cáo tiêu chuẩn.

Đây là lúc số lượng thuộc tính dữ liệu (cardinality) trở nên quan trọng—số lượng tổ hợp tham số duy nhất trong một tập dữ liệu. Ví dụ: nếu một trang web hoạt động bằng 10 ngôn ngữ, nhận lưu lượng truy cập từ 50 quốc gia, sử dụng 3 loại thiết bị và xếp hạng cho 10.000 truy vấn tìm kiếm, số lượng tổ hợp có thể lên tới hàng triệu dòng.

Làm việc với khối lượng dữ liệu này thông qua giao diện web thực tế là không thể. API cho phép bạn truy xuất lượng dữ liệu lớn hơn đáng kể và chia việc xuất thành các phân đoạn riêng biệt. Thông qua lọc và xử lý tuần tự, bạn không chỉ có thể thu thập phần đầu của kết quả mà còn cả phần đuôi dài (long tail) của các truy vấn và URL thường bị mất trong các báo cáo tiêu chuẩn.

Hồ chứa dữ liệu (Data Lake) và lưu trữ lịch sử

Google Search Console chỉ lưu trữ dữ liệu lịch sử trong giao diện của nó trong 16 tháng qua, điều này không đủ cho phân tích SEO dài hạn.

Một kho dữ liệu chuyên dụng, chẳng hạn như BigQuery, sẽ giải quyết vấn đề này. Bạn có thể thường xuyên lưu dữ liệu thô thu được qua API ở đó mà không bị giới hạn bởi thời gian lưu trữ trong giao diện GSC. Điều này mang lại cho bạn một cơ sở dữ liệu SEO lịch sử có thể được sử dụng để phân tích dài hạn, xây dựng báo cáo và xử lý lại dữ liệu theo bất kỳ khía cạnh cần thiết nào.

Sự phụ thuộc vào các dịch vụ bên ngoài và chi phí mở rộng

Các cổng kết nối ETL có sẵn có thể được sử dụng để tự động hóa việc xuất dữ liệu, ví dụ: các dịch vụ SaaS như Supermetrics hoặc Fivetran. Chúng cho phép bạn thiết lập truyền dữ liệu nhanh chóng mà không cần tự phát triển nội bộ, nhưng khi dự án mở rộng, cách tiếp cận này có thể trở nên tốn kém và ràng buộc cơ sở hạ tầng của bạn quá chặt chẽ vào một dịch vụ cụ thể.

Các nền tảng SaaS tính phí dịch vụ của họ dựa trên khối lượng dòng được xử lý hoặc số lượng cổng kết nối. Khi dự án đa ngôn ngữ của bạn bắt đầu tạo ra hàng gigabyte dữ liệu SEO thô mỗi ngày, chi phí của dịch vụ đó có thể vượt quá chi phí lưu trữ dữ liệu trong BigQuery và thuê một máy chủ nhỏ cho các tập lệnh Python gấp vài lần.

Hơn nữa, một dịch vụ càng được tích hợp sâu vào quy trình thu thập và chuyển đổi dữ liệu thì sau này càng khó thay thế: việc di chuyển có thể yêu cầu định cấu hình lại các cổng kết nối, logic xử lý và báo cáo.

Cấp độ chi tiết của dữ liệu

Khi thu thập dữ liệu qua API, điều quan trọng là phải giữ nguyên càng nhiều chi tiết càng tốt. Nếu bạn kết hợp dữ liệu ngay tại giai đoạn xuất, bạn sẽ không thể tái cấu trúc các khía cạnh ban đầu sau này.

Ví dụ: khi thiết kế cơ sở dữ liệu SEO, bạn nên lưu trữ riêng các tham số như loại DeviceCountry. Nếu tập lệnh yêu cầu dữ liệu mà không có phân tích theo quốc gia, GSC sẽ trả về tổng số lượt nhấp cho truy vấn đó. Sau đó, không thể xác định được bao nhiêu lượt nhấp đến từ Đức và bao nhiêu lượt đến từ Pháp.

Đó là lý do tại sao tốt hơn nên lưu trữ dữ liệu ở dạng chi tiết và chỉ kết hợp dữ liệu đó cũng như tính toán các chỉ số cuối cùng ở giai đoạn phân tích hoặc trực quan hóa. Điều này bảo toàn khả năng xây dựng bất kỳ phần phân tích dữ liệu cần thiết nào trong tương lai, ngay cả khi ban đầu chúng không được dự tính trong các báo cáo.

Các hạn chế của GSC API khi xuất lượng dữ liệu lớn

Thoạt nhìn, làm việc với GSC API có vẻ đơn giản: ủy quyền tập lệnh, truy xuất dữ liệu, lưu dữ liệu vào cơ sở dữ liệu và chuyển sang phân tích. Trên thực tế, các dự án lớn nhanh chóng vấp phải các giới hạn kỹ thuật của API.

Nếu bạn cố gắng xuất lượng dữ liệu lớn mà không tính đến các hạn chế này, bạn có thể gặp phải lỗi hết thời gian chờ, lỗi 429 Too Many Requests và xuất không hoàn chỉnh. Do đó, chỉ một phần dữ liệu sẽ đến được kho dữ liệu và bản thân hệ thống sẽ trở nên không ổn định.

Đó là lý do tại sao quy trình xử lý nên tính trước các giới hạn API, độ trễ cập nhật dữ liệu, hạn ngạch truy vấn và cơ chế thử lại cho các yêu cầu không thành công. Hãy cùng xem xét các hạn chế chính của GSC API và cách làm việc với chúng một cách chính xác.

Hạn chế 50.000 dòng và phân đoạn xuất

Theo tài liệu của Google, tham số rowLimit cho phép bạn truy xuất không quá 25.000 dòng trong một yêu cầu duy nhất. Tham số startRow được sử dụng để phân trang: ban đầu bạn có thể yêu cầu 25.000 dòng đầu tiên và sau đó là 25.000 dòng tiếp theo.

Tuy nhiên, có một hạn chế bổ sung: tổng của startRow + rowLimit không thể vượt quá 50.000. Do đó, đối với một ngày duy nhất và một tổ hợp tham số đã chọn, bạn không thể truy xuất dòng thứ 50.001 theo cách này.

Nếu số lượng thuộc tính dữ liệu hàng ngày của bạn vượt quá 50.000 dòng, bạn cần chia việc xuất thành các phân đoạn riêng biệt bằng cách sử dụng Bộ lọc Thứ nguyên (Dimension Filters). Ví dụ: bạn có thể truy vấn dữ liệu riêng biệt cho các thư mục ngôn ngữ — /de/, /fr/, v.v., hoặc chia thêm các URL theo các mẫu bằng cách sử dụng biểu thức chính quy (regular expressions).

Điều này cho phép bạn có được tập dữ liệu hoàn chỉnh thông qua một số yêu cầu độc lập nhắm vào các phân đoạn dữ liệu khác nhau.

Độ trễ dữ liệu và làm việc với dataState

GSC API có độ trễ cập nhật dữ liệu mang tính hệ thống từ 48 đến 72 giờ. Do đó, khi xuất dữ liệu hàng ngày, điều quan trọng là phải phân biệt giữa dữ liệu sơ bộ và dữ liệu cuối cùng.

Tham số dataState kiểm soát điều này. Nó có hai giá trị:

  • "final" (mặc định) — chỉ trả về dữ liệu đã được tổng hợp và xác thực đầy đủ.

  • "all" — bao gồm dữ liệu mới chưa qua xử lý cuối cùng.

Điều này tạo ra sự đánh đổi giữa tốc độ và độ chính xác khi xây dựng quy trình xử lý. Hãy cùng xem xét cả hai kịch bản.

  • Sử dụng dataState: "final" (hành vi mặc định). Ở chế độ này, dữ liệu trong 24 giờ qua có thể chưa khả dụng. Nếu tập lệnh của bạn cố gắng xuất yesterday bằng giá trị mặc định, API sẽ trả về một mảng trống. Bạn cần áp dụng một khoảng bù cố định là current_date — 3 ngày.

  • Sử dụng dataState: "all". Bạn sẽ nhận được tập dữ liệu cần thiết cho 24 giờ trước đó. Tuy nhiên, Google cảnh báo rằng dữ liệu mới chỉ là dữ liệu sơ bộ. Hệ thống chưa hợp nhất tất cả các bản trùng lặp, lọc bỏ các bot spam hoặc tính toán lại các bất thường. Sau 2–3 ngày, các số liệu này sẽ thay đổi trên chính máy chủ của Google.

Điều này có thể ảnh hưởng đến kiến trúc lưu trữ của bạn như thế nào: nếu tập lệnh Python của bạn chỉ đơn giản là thêm dữ liệu thô mới vào BigQuery, cơ sở dữ liệu lịch sử của bạn sẽ bị bóp méo. Khi bạn ghi các chỉ số "mới", bạn đang lưu trữ một bản nháp sẽ không bao giờ khớp chính xác với các báo cáo cuối cùng trong giao diện GSC.

Do đó, đối với phân tích hoạt động, tốt hơn là sử dụng cách tiếp cận hai giai đoạn:

  1. Xuất dữ liệu cho ngày hôm trước bằng dataState: "all".

  2. Đồng thời, tập lệnh sẽ xuất lại dữ liệu cho current_date — 4 ngày bằng cách sử dụng dataState: "final".

  3. Trong BigQuery, thay vì Append đơn giản, hãy sử dụng toán tử MERGE (hoặc logic Upsert). Tập lệnh sẽ tìm dữ liệu sơ bộ từ bốn ngày trước đó trong cơ sở dữ liệu và ghi đè bằng các giá trị cuối cùng đã được hợp nhất.

Cách tiếp cận này cho phép bạn xem các chỉ số mới trên bảng điều khiển trong khi vẫn bảo toàn cơ sở dữ liệu lịch sử chính xác sau khi xử lý dữ liệu cuối cùng.

Hạn chế API và thuật toán giảm tải theo cấp số nhân (exponential backoff)

GSC API giới hạn số lượng yêu cầu để bảo vệ cơ sở hạ tầng của mình khỏi tải quá mức. GSC API có các hạn ngạch nghiêm ngặt: 50 truy vấn mỗi giây (QPS) và 1.200 truy vấn mỗi phút (QPM) cho mỗi dự án. Do đó, các hạn chế này cần được tính đến trước khi thực hiện xuất trên quy mô lớn.

Vấn đề đặc biệt dễ nhận thấy khi dữ liệu phải được chia thành hàng trăm phân đoạn để vượt qua giới hạn 50.000 dòng. Để tăng tốc quá trình, các nhà phát triển thường sử dụng các yêu cầu không đồng bộ (asyncio) hoặc các nhóm luồng (ThreadPoolExecutor). Nhưng điều này có thể nhanh chóng làm cạn kiệt giới hạn 50 QPS và API bắt đầu trả về lỗi 429 Too Many Requests hoặc 503 Service Unavailable.

Một khoảng trễ đơn giản bằng cách sử dụng time.sleep() không hoạt động hiệu quả ở đây. Nếu một vài luồng song song nhận được lỗi cùng một lúc và sau đó tạm dừng trong cùng một khoảng thời gian, chúng sẽ tiếp tục hầu như đồng thời và tạo ra một đỉnh đột biến lưu lượng truy cập khác.

Kiến trúc tập lệnh chính xác nên bao gồm một mẫu giảm tải theo cấp số nhân với nhiễu ngẫu nhiên được thêm vào (Jitter). Điều này làm cho khoảng thời gian giữa các yêu cầu thử lại tăng dần. Không phải tất cả các luồng sẽ thử lại cùng một lúc, làm giảm khả năng chúng vượt quá giới hạn.

Trong Python, bạn không nhất thiết phải triển khai logic này theo cách thủ công: bạn có thể sử dụng các hàm trang trí (decorators) từ thư viện tenacity.

Thu thập dữ liệu SEO cho các tên miền phụ và thư mục ngôn ngữ

Sau khi tính đến các giới hạn và độ trễ của GSC API, câu hỏi quan trọng tiếp theo là trang web đa ngôn ngữ được cấu trúc chính xác như thế nào. Cấu trúc dự án ảnh hưởng trực tiếp đến logic xuất, chuẩn hóa và kết hợp dữ liệu.

Trong SEO đa ngôn ngữ, có hai cách tiếp cận đối lập đối với cấu trúc trang web: tên miền phụ quốc gia và thư mục ngôn ngữ. Đối với người dùng, sự khác biệt là tối thiểu, nhưng đối với việc xây dựng các bản xuất, các cấu trúc khác nhau có thể thay đổi hoàn toàn cách tiếp cận.

Tên miền phụ và các tên miền riêng biệt

Nếu các phiên bản ngôn ngữ được lưu trữ trên các tên miền riêng biệt (site.de, site.fr) hoặc các tên miền phụ (de.site.com, fr.site.com), dữ liệu cho mỗi phiên bản phải được thu thập dưới dạng dữ liệu từ một tài nguyên riêng biệt.

Tại sao điều này lại hữu ích cho doanh nghiệp? Sự cô lập theo khu vực cho phép bạn kiểm soát ngân sách thu thập dữ liệu (crawl budget) một cách nghiêm ngặt hơn. Công cụ tìm kiếm sẽ không chi tiêu ngân sách thu thập dữ liệu của bot Đức để quét phiên bản tiếng Pháp của trang web. Từ góc độ SEO, đây là con đường an toàn nhất để mở rộng quy mô.

Đối với quy trình phân tích, điều này tạo ra hai vấn đề:

  • Nhiều điểm kết nối hơn. Nếu dự án có 10 phiên bản ngôn ngữ, tập lệnh cần truy vấn nhiều tài nguyên GSC một cách tuần tự hoặc song song. Càng có nhiều nguồn, thì hạn ngạch API, xử lý lỗi và khả năng phục hồi của toàn bộ kiến trúc xuất càng trở nên quan trọng.

  • Độ phức tạp của việc chuẩn hóa URL (ghép nối dữ liệu với nhau). Các trang phục vụ cùng một mục đích trên các tên miền khác nhau sẽ có các địa chỉ khác nhau—ví dụ: site.de/productsite.fr/product. Để so sánh hiệu suất của chúng như một thực thể duy nhất, các URL của chúng cần được chuẩn hóa.

Trong thư viện Pandas dành cho Python, việc chuẩn hóa này trông như thế này:

import pandas as pd
from urllib.parse import urlparse

# Chỉ giữ lại đường dẫn để ghép nối các chỉ số giữa các quốc gia
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Kết quả: /product

Nếu không có sự chuẩn hóa này, các chỉ số cho các bản địa hóa khác nhau sẽ vẫn bị tách biệt trên các URL khác nhau. Điều này sẽ khiến việc tính toán hiệu suất tổng thể của cùng một trang hoặc mẫu bằng các ngôn ngữ khác nhau trở nên khó khăn hơn.

Thư mục ngôn ngữ và phân đoạn dữ liệu

Nếu các phiên bản ngôn ngữ được đặt trong các thư mục, ví dụ: site.com/de/site.com/fr/, toàn bộ dự án vẫn nằm trong một tên miền duy nhất. Điều này giúp đơn giản hóa việc thu thập dữ liệu: thay vì thực hiện các yêu cầu riêng biệt đến nhiều tài nguyên, bạn có thể làm việc với một Domain Property duy nhất trong Google Search Console.

Thay vì 10 truy vấn riêng biệt, bạn có thể thực hiện một lần xuất lớn, sử dụng tính năng lọc để vượt qua giới hạn 50.000 dòng. Điều này giúp tiết kiệm hạn ngạch Google API và giảm tải mạng.

Các bản xuất lớn vẫn cần được chia thành các phân đoạn. Nhưng bản thân kiến trúc trở nên đơn giản hơn: ít điểm kết nối hơn, ít yêu cầu hơn và tải API thấp hơn.

Bởi vì API cung cấp cho chúng ta một luồng URL liên tục, tập lệnh phải tự gán các dấu mốc quốc gia cho các dòng. Điều này được thực hiện bằng cách sử dụng biểu thức chính quy (RegEx).

Sử dụng thư viện Pandas, chúng ta có thể trích xuất dấu mốc ngôn ngữ trực tiếp từ URL:

df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Xử ngoại lệ: nếu RegEx trả về NaN, đây phiên bản chính của trang web
df['language_market'].fillna('en', inplace=True)

Điều này cho phép bạn trích xuất dấu mốc de từ một URL như site.com/de/product và sử dụng nó để phân tích thêm.

Hạn chế chính của cách tiếp cận này là sự phụ thuộc vào cấu trúc URL. Biểu thức chính quy phải khớp chính xác với các quy tắc được sử dụng để xây dựng các phiên bản ngôn ngữ. Nếu một số trang sử dụng một mẫu khác, chẳng hạn như site.com/category-de/product, các URL đó có thể bị phân loại sai hoặc hoàn toàn không đi vào phân đoạn yêu cầu.

Đó là lý do tại sao, trước khi định cấu hình RegEx, điều quan trọng là phải kiểm tra tất cả các mẫu URL ngôn ngữ có thể có và xử lý các ngoại lệ một cách riêng biệt.

Chuyển đổi dữ liệu và tính toán chỉ số trong Pandas

Sau khi thu thập và chuẩn hóa dữ liệu, dữ liệu đó cần được kết hợp và chuẩn bị để phân tích. Pandas rất thuận tiện cho việc này: thư viện giúp có thể làm việc với các bảng lớn, kết hợp các nguồn và tính toán các chỉ số ở cả cấp độ dòng và cấp độ nhóm.

Kết hợp dữ liệu GSC và GA4 theo URL

Google Search Console hiển thị các chỉ số tìm kiếm—số lượt hiển thị, lượt nhấp, CTR và vị trí. GA4 bổ sung cho các chỉ số này bằng các chỉ số hành vi và kinh doanh, chẳng hạn như số phiên và lượt chuyển đổi.

Để có được bức tranh hoàn chỉnh hơn về hiệu suất lưu lượng truy cập SEO, dữ liệu GSC và GA4 có thể được kết hợp bằng cách sử dụng một khóa chung—URL trang đích đã được chuẩn hóa.

Trong Pandas, điều này được thực hiện bằng cách tham gia các bảng bằng một khóa chung, URL đã chuẩn hóa:

import pandas as pd

# df_gsc xuất từ Search Console
# df_ga4 xuất từ GA4 (Phiên, Chuyển đổi)

# Liên kết dữ liệu theo trang đích (Left Join để các trang không lưu lượng truy cập không bị mất)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Giờ đây chúng ta thể tính tỷ lệ chuyển đổi của một cụm SEO cụ thể:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100

Tính toán chính xác CTR và vị trí trung bình

Khi kết hợp dữ liệu từ nhiều phiên bản ngôn ngữ, bạn không thể tính CTR và vị trí trung bình chỉ bằng cách sử dụng số trung bình cộng. Điều này làm sai lệch kết quả vì nó không tính đến khối lượng hiển thị khác nhau.

Ví dụ:

  • Tên miền phụ tiếng Pháp: 2 lượt nhấp trên 4 lượt hiển thị, CTR = 50%;

  • Tên miền phụ tiếng Đức: 20 lượt nhấp trên 1.000 lượt hiển thị, CTR = 2%.

Nếu bạn chỉ đơn giản tính trung bình các giá trị CTR, bạn sẽ có được:

(50% + 2%) / 2 = 26%

Nhưng CTR thực tế trên hai tên miền phụ là:

22 lượt nhấp / 1004 lượt hiển thị = 2,19%

Do đó, khi tổng hợp dữ liệu từ các bản địa hóa khác nhau, các chỉ số cần được tính toán lại từ các giá trị cơ sở:

  • CTR được tính bằng tỷ lệ giữa tổng số lượt nhấp trên tổng số lượt hiển thị.

  • Vị trí trung bình nên được tính trọng số theo lượt hiển thị: vị trí của mỗi dòng được nhân với số lượt hiển thị, và tổng của các giá trị này sau đó được chia cho tổng số lượt hiển thị.

Trong Pandas, điều này có thể được triển khai như sau:

# Nhóm dữ liệu theo truy vấn tìm kiếm trên tất cả các quốc gia
def weighted_metrics(x):
    # Vị trí trung bình trọng số = Sum (Vị trí * Lượt hiển thị) / Sum (Lượt hiển thị)
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # CTR thực tế
    real_ctr = (x['clicks'].sum() / x['impressions'].sum()) * 100
    
    return pd.Series({
        'total_clicks': x['clicks'].sum(),
        'total_impressions': x['impressions'].sum(),
        'weighted_position': weighted_pos,
        'real_ctr': real_ctr
    })

# Áp dụng hàm cho dataframe đã được nhóm
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)

Tự động hóa hreflang và giám sát ăn bớt lưu lượng truy cập (cannibalization)

Một kho dữ liệu chuyên dụng có thể được sử dụng không chỉ để báo cáo mà còn để tự động phát hiện các vấn đề SEO kỹ thuật. Hai loại vấn đề đặc biệt quan trọng đối với các dự án đa ngôn ngữ: mối quan hệ bản địa hóa bị hỏng và sự cạnh tranh nội bộ giữa nhiều trang cho cùng một nhu cầu tìm kiếm.

Giám sát hreflang tự động

Tối ưu hóa SEO kỹ thuật cho các dự án quốc tế dựa trên tính nhất quán và tính hai chiều của các thẻ bản địa hóa. Thẻ hreflang hoạt động như một hệ thống tham chiếu chéo hai chiều nghiêm ngặt. Ví dụ: nếu một trang tiếng Pháp trỏ đến một trang tiếng Đức như một giải pháp thay thế, trang tiếng Đức phải chứa một liên kết đối ứng. Phá vỡ chuỗi này sẽ phá vỡ toàn bộ cụm trong mắt Google.

Với một dự án lớn, việc kiểm tra các liên kết này một cách thủ công là không thể, vì vậy việc giám sát nên dựa trên việc so sánh ít nhất hai nguồn dữ liệu:

  • Screaming Frog. Chạy trình thu thập thông tin theo lịch trình. Nó quét sự hiện diện thực tế của các thẻ trong mã HTML và xác thực mã ngôn ngữ (ISO 639-1) và mã quốc gia (ISO 3166-1 Alpha 2). Kết quả được xuất sang cơ sở dữ liệu.

  • GSC API. Search Console API cung cấp báo cáo lập chỉ mục và cho thấy cách Google diễn giải các mối quan hệ này trong lần thu thập thông tin mới nhất của nó.

Kết quả thu thập thông tin và dữ liệu Google có thể được lưu trữ trong cùng một cơ sở dữ liệu và sau đó được so khớp bằng SQL. Ví dụ: FULL OUTER JOIN có thể xác định các lỗi nghiêm trọng trong dữ liệu tổng hợp: các trang về mặt kỹ thuật có thẻ chính xác trong mã của chúng nhưng đã bị công cụ tìm kiếm bỏ qua.

Có thể có nhiều lý do cho việc này. Một khả năng là kết xuất phía máy khách (client-side rendering): các khung JavaScript (React, Vue) mất quá nhiều thời gian để kết xuất các thẻ trong <head>, hoặc các chỉ số hiệu suất (Core Web Vitals) kém đến mức Googlebot hết thời gian chờ trước khi có thể đọc hreflang. Tự động hóa sẽ bắt được các vấn đề này trước khi lưu lượng truy cập bắt đầu giảm sút.

Ăn bớt lưu lượng truy cập (cannibalization) và tìm kiếm các URL xung đột

Vấn đề đa ngôn ngữ thứ hai là cạnh tranh nội bộ. Hiện tượng ăn bớt lưu lượng truy cập (cannibalization) xảy ra khi một công cụ tìm kiếm bị nhầm lẫn về mức độ liên quan và bắt đầu xếp hạng, ví dụ, phiên bản tiếng Anh của một trang cho một truy vấn từ Đức mặc dù bạn có một trang đích tiếng Đức chuyên dụng.

Những sự trùng lặp như vậy rất khó phân tích trên quy mô lớn trong giao diện GSC tiêu chuẩn. Nếu dữ liệu thô được lưu trữ trong BigQuery, hiện tượng ăn bớt lưu lượng truy cập tiềm ẩn có thể được phát hiện tự động bằng SQL.

Thuật toán phát hiện ăn bớt lưu lượng truy cập như sau:

  1. Nhóm dữ liệu theo hai tham số: querycountry.

  2. Đếm số lượng URL duy nhất (COUNT(DISTINCT page)) nhận được lượt hiển thị cho tổ hợp này.

  3. Lọc kết quả bằng cách sử dụng HAVING count > 1.

Nếu nhiều trang nhận được lượt hiển thị cho cùng một tổ hợp query + country, đây là tín hiệu của một xung đột mức độ liên quan tiềm ẩn.

Dữ liệu GSC có thể được bổ sung bằng cách kiểm tra kết quả tìm kiếm thực tế cho các khu vực liên quan. Điều này đặc biệt hữu ích khi phân tích đã xác định được một bất thường, nhưng chỉ riêng các con số thì không làm rõ được chính xác người dùng nhìn thấy gì và Google hiển thị phiên bản nào của trang ở một quốc gia cụ thể.

Chúng tôi đã đề cập đến các phương pháp tự động thu thập SERP trong một bài viết riêng. Và khi bạn cần kiểm tra thủ công các truy vấn và bản địa hóa riêng lẻ trong các môi trường khu vực khác nhau, bạn có thể sử dụng một trình duyệt chống phát hiện như Octo Browser.

Cách Octo Browser bổ sung cho phân tích SEO

GSC và BigQuery rất phù hợp để tìm kiếm các vấn đề trên khối lượng dữ liệu lớn. Chúng có thể giúp bạn nhận thấy, ví dụ, một trang tiếng Đức đã bắt đầu mất lượt hiển thị, việc bản địa hóa sai xếp hạng cho các truy vấn từ một quốc gia cụ thể hoặc một số URL đang cạnh tranh với nhau.

Nhưng sau khi tìm thấy một vấn đề như vậy, câu hỏi thường đặt ra là: người dùng thực sự nhìn thấy gì trong kết quả tìm kiếm?

Dữ liệu GSC giúp xác định một bất thường và hiểu được quy mô của nó. Để chẩn đoán một trường hợp cụ thể, việc xem xét kết quả tìm kiếm từ khu vực yêu cầu và kiểm tra xem trang web thực sự hoạt động như thế nào là rất hữu ích.

Đây là lúc Octo Browser phát huy tác dụng. Đối với các quốc gia khác nhau, bạn có thể tạo các hồ sơ riêng biệt, kết nối proxy với vị trí địa lý yêu cầu và thực hiện kiểm tra trong các phiên trình duyệt riêng biệt. Điều này rất thuận tiện khi bạn thường xuyên làm việc với một số vị trí địa lý và không muốn trộn lẫn cookie, lịch sử và dữ liệu khác giữa các lần kiểm tra.

Ví dụ: tập lệnh của chúng tôi phát hiện ra rằng URL tiếng Anh đang nhận được lượt hiển thị cho các truy vấn từ Đức mặc dù trang web có phiên bản tiếng Đức hoàn chỉnh tại /de/. Điều này không nhất thiết có nghĩa là vấn đề chắc chắn liên quan đến bản địa hóa. Đầu tiên, bạn nên kiểm tra xem điều gì đang xảy ra trong kết quả tìm kiếm thực tế.

Mở một hồ sơ Octo với proxy Đức và kiểm tra xem Google hiển thị URL nào cho truy vấn mục tiêu. Đồng thời, bạn có thể kiểm tra xem phiên bản chính xác của trang web có mở ra hay không, có tự động chuyển hướng sang ngôn ngữ khác hay không và nội dung trang có khớp với khu vực đã chọn hay không.

Bạn có thể sử dụng cùng một phương pháp để kiểm tra có chọn lọc:

  • sự xuất hiện của phiên bản ngôn ngữ sai trong SERP;

  • sự khác biệt trong kết quả tìm kiếm trên nhiều khu vực;

  • hoạt động của các chuyển hướng theo vùng;

  • việc bản địa hóa nội dung, giá cả và các yếu tố khác của trang;

  • các thay đổi sau khi sửa lỗi hreflang, canonical, hoặc liên kết nội bộ.

Bằng cách này, GSC API và BigQuery giúp xác định các trường hợp đáng ngờ trong toàn bộ dự án, trong khi Octo Browser giúp điều tra các bất thường riêng lẻ bằng cách sử dụng các vị trí địa lý yêu cầu trong các môi trường riêng biệt.

Kết luận

Chuyển phân tích SEO từ giao diện web sang hệ thống thu thập và lưu trữ dữ liệu tùy chỉnh là một bước nâng cấp lên một cấp độ quản lý dự án hoàn toàn mới.

Ban đầu, một kiến trúc như vậy đòi hỏi khắt khe về mặt kỹ thuật: bạn cần định cấu hình ủy quyền, xử lý lỗi, chuẩn hóa dữ liệu, xuất dữ liệu thường xuyên và quản lý quy trình. Nhưng kết quả là, bạn có được một hệ thống mở rộng quy mô theo dự án và không phụ thuộc vào các hạn chế của giao diện web.

Thay vì thu thập các báo cáo một cách thủ công, bạn sẽ có một cơ sở dữ liệu duy nhất chứa lịch sử nơi bạn có thể phân tích tất cả các phiên bản ngôn ngữ, tính toán lại các chỉ số một cách chính xác, xác định các vấn đề kỹ thuật và xây dựng các phần phân tích dữ liệu bạn cần mà không làm mất đi độ chi tiết.

Cập nhật với các tin tức Octo Browser mới nhất

Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.

Cập nhật với các tin tức Octo Browser mới nhất

Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.

Cập nhật với các tin tức Octo Browser mới nhất

Khi nhấp vào nút này, bạn sẽ đồng ý với Chính sách Quyền riêng tư của chúng tôi.

Tham gia Octo Browser ngay

Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.

Tham gia Octo Browser ngay

Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.

Tham gia Octo Browser ngay

Hoặc liên hệ với Dịch vụ khách hàng bất kì lúc nào nếu bạn có bất cứ thắc mắc nào.

©

2026

Octo Browser

©

2026

Octo Browser

©

2026

Octo Browser