Как собрать SEO-аналитику мультиязычного сайта через GSC API и BigQuery

Как собрать SEO-аналитику мультиязычного сайта через GSC API и BigQuery
Markus_automation
Markus_automation

Expert in data parsing and automation

Для мультиязычных проектов задача сводной SEO-аналитики быстро выходит за рамки стандартных веб-интерфейсов. Чем больше языковых версий, регионов и URL участвует в анализе, тем выше объем данных и количество измерений, которые необходимо собрать, нормализовать и сопоставить между собой.

На небольших проектах эту задачу можно решать с помощью ручных выгрузок и готовых отчетов. При масштабировании на десятки языков такой подход становится неэффективным: специалист тратит значительную часть времени на сбор и подготовку данных вместо их анализа. Дополнительные ограничения создают сами интерфейсы аналитических систем. Например, Google Search Console отображает ограниченный объем строк, чего недостаточно для проектов с десятками или сотнями тысяч URL.

Поэтому для крупных мультиязычных сайтов имеет смысл выносить сбор и обработку SEO-метрик на программный уровень. Так можно автоматизировать регулярные выгрузки, сохранить необходимую детализацию метрик и построить систему мониторинга, которая меньше зависит от ограничений браузерных интерфейсов. В этой статье разберем, как организовать такую архитектуру для мультиязычного проекта и какие ограничения Google Search Console API необходимо учитывать при ее реализации.

Содержание

Сохраняйте анонимность с Octo Browser, ведь отследить ваш реальный цифровой отпечаток невозможно.

Хотите попробовать Octo Browser со скидкой?
По промокоду OCTOBLOG получите 30% скидку на любую подписку. Предложение действительно только для новых пользователей.

Зачем уходить от веб-интерфейсов

Надежная система SEO-аналитики начинается с отказа от ручных выгрузок. Интерфейс Google Search Console удобен для быстрой проверки показателей, но его возможностей недостаточно для глубокой продуктовой аналитики.

GSC API позволяет получать данные на более детальном уровне — по отдельным URL, поисковым запросам и другим измерениям. Это дает возможность работать не только с агрегированными отчетами, но и с исходными данными, из которых можно формировать собственные срезы и метрики.

Чтобы понять преимущества такой архитектуры, важно учитывать несколько ключевых факторов.

Кардинальность данных и ограничения веб-интерфейса

Одна из главных проблем интерфейса GSC — ограниченный объем отображаемых данных. Для мультиязычного проекта это особенно критично: при большом количестве страниц, стран, устройств и запросов значительная часть информации остается за пределами стандартного отчета.

Здесь важна кардинальность — количество уникальных комбинаций параметров в наборе данных. Например, если сайт работает на 10 языках, получает трафик из 50 стран, с 3 типов устройств и по 10 000 поисковых запросов, количество возможных комбинаций измеряется миллионами строк.

Работать с таким объемом через веб-интерфейс практически невозможно. API позволяет получать существенно больше данных и разбивать выгрузку на отдельные сегменты. За счет фильтрации и последовательной обработки можно собирать не только верхнюю часть выдачи, но и длинный хвост запросов и URL, который обычно теряется в стандартных отчетах.

Озеро данных (Data Lake) и хранение истории

Google Search Console хранит исторические данные в интерфейсе только за последние 16 месяцев, чего недостаточно для долгосрочной SEO-аналитики.

Эту проблему решает собственное хранилище данных, например BigQuery. В него можно регулярно сохранять сырые данные, полученные через API, не ограничиваясь сроком хранения в интерфейсе GSC. Так у вас будет историческая база SEO-данных, которую можно использовать для долгосрочного анализа, построения отчетов и повторной обработки данных в любых необходимых разрезах.

Зависимость от внешних сервисов и цена масштабирования 

Для автоматической выгрузки данных можно использовать готовые ETL-коннекторы — например, SaaS-сервисы вроде Supermetrics или Fivetran. Они позволяют быстро настроить передачу данных без собственной разработки, но при масштабировании такой подход может стать дорогим и слишком сильно привязать инфраструктуру к конкретному сервису.

SaaS-платформы тарифицируют услуги по объему обрабатываемых строк или количеству коннекторов. Когда ваш мультиязычный проект начнет генерировать гигабайты сырых SEO-данных в сутки, счет за использование подобного сервиса превысит стоимость хранения данных в BigQuery и аренды небольшого сервера под Python-скрипты в несколько раз.

Кроме того, чем глубже сервис встроен в процесс сбора и трансформации данных, тем сложнее затем отказаться от него: миграция может потребовать перенастройки коннекторов, логики обработки и отчетности.

Уровень детализации данных 

При сборе данных через API важно сохранять максимально возможную детализацию. Если объединить данные уже на этапе выгрузки, восстановить исходные разрезы позже не получится.

Например, при проектировании SEO-базы стоит отдельно сохранять такие параметры, как тип устройства (Device) и страна (Country). Если скрипт запросит данные без разбивки по странам, GSC вернет уже суммарное количество кликов по запросу. После этого определить, сколько кликов пришло из Германии, а сколько из Франции, будет невозможно.

Поэтому лучше хранить данные в детализированном виде, а объединять и рассчитывать итоговые метрики уже на этапе анализа или визуализации. Так вы сохраняете возможность в будущем строить любые необходимые срезы — даже если изначально они не были предусмотрены в отчетах.

Ограничения GSC API при массовой выгрузке данных 

На первый взгляд работа с GSC API выглядит просто: авторизовать скрипт, получить данные, сохранить их в базу и перейти к анализу. На практике для крупных проектов такой сценарий быстро упирается в технические ограничения API.

Если попытаться выгружать большие объемы данных без учета этих ограничений, можно столкнуться с тайм-аутами, ошибками 429 Too Many Requests и неполными выгрузками. В результате в хранилище попадет только часть данных, а сама система будет работать нестабильно.

Поэтому при построении пайплайна важно заранее учитывать лимиты API, задержку обновления данных, квоты на количество запросов и механизмы повторных обращений при ошибках. Разберем основные ограничения GSC API и способы корректно работать с ними.

Лимит в 50 000 строк и сегментация выгрузки

Согласно документации Google, параметр rowLimit позволяет получить не более 25 000 строк за один запрос. Для постраничной выгрузки используется параметр startRow: сначала можно запросить первые 25 000 строк, затем следующие 25 000.

Однако здесь действует дополнительное ограничение: сумма startRow + rowLimit не может превышать 50 000. Поэтому для одной даты и выбранной комбинации параметров получить 50 001-ю строку таким способом уже не получится.

Если дневная кардинальность ваших данных превышает 50 000 строк, выгрузку нужно разбивать на отдельные сегменты с помощью Dimension Filters. Например, можно запрашивать данные отдельно по языковым папкам — /de/, /fr/ и т. д. — или дополнительно делить URL по шаблонам с помощью регулярных выражений.

Так вы сможете получить полные данные за счет нескольких независимых запросов к разным сегментам.

Задержка данных и работа с dataState 

GSC API имеет системную задержку обновления, которая составляет от 48 до 72 часов. Поэтому при ежедневной выгрузке важно различать предварительные и окончательные данные.

За это отвечает параметр dataState. У него есть два значения:

  • "final" (по умолчанию) — возвращает только полностью агрегированные и проверенные данные.

  • "all" — включает свежие данные, которые еще не прошли финальную обработку.

Из-за этого при построении пайплайна возникает выбор между оперативностью и точностью. Рассмотрим оба сценария.

  • Использование dataState: "final" (поведение по умолчанию). В этом режиме данные за последние сутки могут быть еще недоступны. Если ваш скрипт попытается выгрузить yesterday со значением по умолчанию, API вернет пустой массив. Необходимо ставить жесткое смещение current_date — 3 days.

  • Использование dataState: "all". Вы получите нужный массив за прошедшие 24 часа. Но Google предупреждает, что свежие данные являются предварительными. Система еще не свела все дубликаты, не отфильтровала спам-ботов и не пересчитала аномалии. Через 2–3 дня эти цифры изменятся на серверах самого Google.

Как это может повлиять на архитектуру хранилища: если ваш Python-скрипт просто добавляет сырые свежие данные в BigQuery, ваша историческая база будет искажена. Записывая «свежие» метрики, вы сохраняете черновик, который никогда не совпадет с финальными отчетами в интерфейсе GSC.

Поэтому для оперативной аналитики лучше использовать двухэтапную схему:

  1. Выгружать данные за предыдущий день с dataState: "all".

  2. Одновременно с этим скрипт должен делать повторную выгрузку за current_date — 4 days с параметром dataState: "final".

  3. В BigQuery вместо простого добавления (Append) используйте оператор MERGE (или Upsert-логику). Скрипт должен находить в базе предварительные данные четырехдневной давности и перезаписывать их финальными, консолидированными значениями.

Такой подход позволяет одновременно видеть свежие показатели на дашборде и сохранять корректную историческую базу после финальной обработки данных.

Лимиты API и экспоненциальная задержка

GSC API ограничивает количество запросов, чтобы защищать инфраструктуру от чрезмерной нагрузки. Для GSC API действуют строгие квоты: 50 запросов в секунду (QPS) и 1 200 запросов в минуту (QPM) на один проект. Поэтому при массовой выгрузке данных эти ограничения необходимо учитывать заранее.

Проблема особенно заметна, когда данные приходится разбивать на сотни сегментов для обхода лимита в 50 000 строк. Чтобы ускорить процесс, разработчики часто используют асинхронные запросы (asyncio) или пулы потоков (ThreadPoolExecutor). Но так 50 QPS быстро исчерпываются, и API начинает возвращать ошибки 429 Too Many Requests или 503 Service Unavailable.

Простая задержка через time.sleep() здесь работает не лучшим образом. Если несколько параллельных потоков одновременно получают ошибку и затем засыпают на одинаковое время, они почти одновременно возобновят работу и снова создадут пиковую нагрузку.

Правильная архитектура скрипта должна включать паттерн экспоненциальной задержки с добавлением случайного шума (Jitter). Так интервал между повторными запросами будет постепенно увеличиваться. Все потоки не будут повторять запросы одновременно и меньше шанс, что они превысят лимиты.

В Python эту логику не обязательно реализовывать вручную: можно использовать декораторы из библиотеки tenacity.

Сбор SEO-данных для поддоменов и языковых папок

После учета лимитов и задержек GSC API следующий важный вопрос — как именно организован мультиязычный сайт. Структура проекта напрямую влияет на логику выгрузки, нормализации и объединения данных. 

В мультиязычном SEO существует два полярных подхода к структуре сайта: национальные поддомены и языковые папки. Для пользователя разница минимальна, но для формирования выгрузки разная структура может полностью поменять подход.

Поддомены и отдельные домены

Если языковые версии размещены на отдельных доменах (site.de, site.fr) или поддоменах (de.site.com, fr.site.com), данные по ним приходится собирать как по отдельным ресурсам.

Зачем это бизнесу? Изоляция регионов позволяет жестко контролировать краулинговый бюджет. Поисковик не будет тратить лимиты немецкого бота на сканирование французской версии сайта. С точки зрения SEO это самый безопасный путь для масштабирования.

Для аналитического пайплайна это создает две проблемы:

  • Больше точек подключения. Если у проекта 10 языковых версий, скрипту необходимо последовательно или параллельно обращаться к нескольким ресурсам GSC. Чем больше таких источников, тем важнее учитывать квоты API, обработку ошибок и устойчивость всей схемы выгрузки.

  • Сложность нормализации URL (склейка данных). Одинаковые по назначению страницы на разных доменах будут иметь разные адреса — например, site.de/product и site.fr/product. Чтобы сравнивать их показатели как одну сущность, URL нужно привести к общему виду.

В библиотеке Pandas (Python) эта нормализация выглядит так:

import pandas as pd
from urllib.parse import urlparse

# Оставляем только путь (Path) для склейки метрик разных стран
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Результат: /product
import pandas as pd
from urllib.parse import urlparse

# Оставляем только путь (Path) для склейки метрик разных стран
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Результат: /product

Без такой нормализации показатели разных локализаций останутся разделены между отдельными URL. Это затруднит расчет общей эффективности одной и той же страницы или шаблона на разных языках.

Языковые папки и сегментация данных

Если языковые версии размещены в папках — например, site.com/de/ и site.com/fr/ — весь проект остается в рамках одного домена. Это упрощает сбор данных: вместо отдельных обращений к нескольким ресурсам можно работать с одним профилем Domain Property в Google Search Console. 

Вместо 10 разных запросов можно делать одну массивную выгрузку (с применением фильтрации для обхода лимита в 50 000 строк). Так вы экономите квоты API Google и снижаете нагрузку на сеть.

Крупную выгрузку все равно приходится делить на сегменты. Но сама архитектура становится проще: меньше точек подключения, меньше запросов и ниже нагрузка на API.

Поскольку API отдает нам сплошной поток URL, скрипт должен самостоятельно разметить строки маркерами стран. Это делается с помощью регулярных выражений (RegEx).

Если брать библиотеку Pandas, мы извлекаем маркер языка прямо из URL:

df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Обработка исключений: если RegEx вернуло NaN, значит, это основная версия сайта
df['language_market'].fillna('en', inplace=True)
df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Обработка исключений: если RegEx вернуло NaN, значит, это основная версия сайта
df['language_market'].fillna('en', inplace=True)

Так из URL вида site.com/de/product можно получить маркер de и использовать его при дальнейшем анализе.

Основное ограничение этого подхода — зависимость от структуры URL. Регулярное выражение должно точно соответствовать правилам формирования языковых версий. Если часть страниц использует другой шаблон, например site.com/category-de/product, такие URL могут быть определены неверно или вообще не попасть в нужный сегмент.

Поэтому перед настройкой RegEx важно проверить все варианты формирования языковых URL и отдельно обработать исключения.

Трансформация данных и расчет метрик в Pandas

После сбора и нормализации данные необходимо объединить и подготовить к анализу. Для этого удобно использовать Pandas: библиотека позволяет работать с большими таблицами, объединять источники и рассчитывать метрики на уровне строк и групп.

Объединение данных GSC и GA4 по URL

Google Search Console отображает поисковые метрики — показы, клики, CTR и позиции. GA4 дополняет их поведенческими и бизнес-показателями, например сессиями и конверсиями.

Чтобы получить более полную картину эффективности SEO-трафика, данные из GSC и GA4 можно объединить по общему ключу — нормализованному URL посадочной страницы.

В Pandas это делается через объединение таблиц по общему ключу — нормализованному URL:

import pandas as pd

# df_gsc выгрузка из Search Console
# df_ga4 выгрузка из GA4 (Sessions, Conversions)

# Объединяем данные по посадочной странице (Left Join, чтобы не потерять страницы без трафика)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Теперь мы можем рассчитать конверсию конкретного SEO-кластера:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100
import pandas as pd

# df_gsc выгрузка из Search Console
# df_ga4 выгрузка из GA4 (Sessions, Conversions)

# Объединяем данные по посадочной странице (Left Join, чтобы не потерять страницы без трафика)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Теперь мы можем рассчитать конверсию конкретного SEO-кластера:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100

Корректный расчет CTR и средней позиции

При объединении данных нескольких языковых версий нельзя рассчитывать CTR и среднюю позицию через обычное среднее арифметическое. Такой подход искажает результат, потому что не учитывает разный объем показов.

Например:

  • французский поддомен: 2 клика из 4 показов, CTR = 50%;

  • немецкий поддомен: 20 кликов из 1 000 показов, CTR = 2%.

Если просто усреднить значения CTR, получится:

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

Но фактический CTR по двум поддоменам равен:

22 клика / 1004 показа = 2,19%

Поэтому при агрегации данных разных локализаций метрики нужно пересчитывать на основе исходных значений:

  • CTR рассчитывается как отношение суммарного количества кликов к суммарному количеству показов.

  • Средняя позиция должна быть взвешенной по показам: позиция каждой строки умножается на количество показов, после чего сумма этих значений делится на общее количество показов.

В Pandas это можно реализовать так:

# Группируем данные по поисковому запросу для всех стран сразу
def weighted_metrics(x):
    # Взвешенная средняя позиция = Сумма (Позиция * Показы) / Сумма показов
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # Реальный CTR
    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
    })

# Применяем функцию к сгруппированному датафрейму
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)
# Группируем данные по поисковому запросу для всех стран сразу
def weighted_metrics(x):
    # Взвешенная средняя позиция = Сумма (Позиция * Показы) / Сумма показов
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # Реальный CTR
    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
    })

# Применяем функцию к сгруппированному датафрейму
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)

Автоматизация мониторинга hreflang и каннибализации

Собственное хранилище данных можно использовать не только для отчетности, но и для автоматического поиска технических SEO-проблем. Для мультиязычных проектов особенно важны два типа ошибок: разорванные связи локализации и внутренняя конкуренция нескольких страниц за один и тот же поисковый запрос. 

Автоматический контроль hreflang 

Техническая SEO-оптимизация международных проектов опирается на консистентность и двунаправленность тегов локализации. Тег hreflang работает как строгая двунаправленная система перекрестных ссылок. Если, к примеру, французская страница ссылается на немецкую как на альтернативную, немецкая обязана содержать обратную ссылку. Разрыв этой цепи ломает весь кластер в глазах Google.

На крупном проекте вручную проверять такие связи невозможно, поэтому контроль лучше строить на сравнении хотя бы двух источников данных: 

  • Screaming Frog. Вы запускаете краулер по расписанию. Он сканирует фактическое наличие тегов в HTML-коде, валидирует коды языков (ISO 639-1) и стран (ISO 3166-1 Alpha 2). Результат выгружается в базу данных.

  • GSC API. API Search Console отдает отчет об индексации и показывает, как именно Google интерпретировал эти связи во время последнего обхода.

Результаты краулинга и данные из Google можно сохранять в одну базу и затем сопоставлять через SQL. Например, FULL OUTER JOIN позволяет находить критические баги в агрегированных данных: страницы, которые технически имеют правильные теги в коде, но проигнорированы поисковиком.

Причин этому может быть много, как вариант — рендеринг на стороне клиента: JavaScript-фреймворки (React, Vue) слишком долго рендерят теги в <head> или показатели скорости (Core Web Vitals) настолько низкие, что краулер Googlebot отваливается по тайм-ауту, не успев прочитать hreflang. Автоматика ловит эти моменты до того, как трафик начнет падать.

Каннибализация трафика и поиск конфликтующих URL

Вторая проблема мультиязычности — внутренняя конкуренция. Каннибализация возникает, когда поисковик путается в релевантности и начинает ранжировать, например, английскую версию страницы по запросу из Германии, хотя у вас есть посадочная страница на немецком языке.

В стандартном интерфейсе GSC такие пересечения сложно анализировать на больших объемах данных. Если же сырые данные хранятся в BigQuery, потенциальную каннибализацию можно выявлять автоматически с помощью SQL. 

Алгоритм выявления каннибализации такой:

  1. Группируем массив данных по двум параметрам: query и country.

  2. Подсчитываем количество уникальных URL (COUNT(DISTINCT page)), получающих показы по этой связке.

  3. Фильтруем результаты с помощью HAVING count > 1.

Если по одной связке query + country показы получают несколько страниц, это сигнал о возможном конфликте релевантности.

Данные GSC можно дополнить проверкой фактической поисковой выдачи по нужным регионам. Это особенно полезно в случаях, когда аналитика уже обнаружила аномалию, но по цифрам сложно понять, что именно видит пользователь и какую версию страницы Google показывает в конкретной стране.

Подробнее о способах автоматического сбора SERP мы рассказывали в отдельной статье. А если нужно вручную проверить отдельные запросы и локализации в разных региональных окружениях, используйте антидетект-браузер, такой как Octo Browser.

Как Octo Browser дополняет SEO-аналитику

GSC и BigQuery хорошо подходят для поиска проблем на больших объемах данных. С их помощью можно заметить, например, что немецкая страница начала терять показы, по запросам из определенной страны ранжируется не та локализация или несколько URL конкурируют между собой.

Но после такой находки обычно возникает вопрос: а что видит пользователь в поисковой выдаче?

Данные GSC помогают найти аномалию и понять ее масштаб. Для диагностики конкретного случая полезно посмотреть на выдачу из нужного региона и проверить, как ведет себя сайт.

Здесь пригодится Octo Browser. Для разных стран можно создать отдельные профили, подключить к ним прокси с нужным гео и проводить проверки в изолированных браузерных сессиях. Это удобно, когда приходится регулярно работать сразу с несколькими гео и не хочется смешивать куки, историю и другие данные между проверками.

Представим, что наш скрипт обнаружил: по запросам из Германии показы получает английский URL, хотя на сайте существует полноценная немецкая версия /de/. Это еще не означает, что проблема точно связана с локализацией. Сначала стоит посмотреть, что происходит в самой выдаче.

Открываем профиль Octo с немецким прокси и проверяем, какой URL Google показывает по нужному запросу. Заодно можно посмотреть, открывается ли правильная версия сайта, нет ли автоматического редиректа на другую локаль и соответствует ли контент страницы выбранному региону.

Таким же способом можно выборочно проверять:

  • появление неправильной языковой версии в SERP;

  • различия выдачи между несколькими регионами;

  • работу региональных редиректов;

  • локализацию контента, цен и других элементов страницы;

  • изменения после исправления hreflang, canonical или внутренней перелинковки.

Таким образом, GSC API и BigQuery помогут находить подозрительные случаи в масштабе всего проекта, а Octo Browser — разбирать отдельные аномалии, используя нужные гео в изолированном окружении.

Заключение

Перенос SEO-аналитики из веб-интерфейсов в собственную систему сбора и хранения данных — это переход управления проектом на качественно новый уровень.

На старте такая архитектура требует больше технической работы: нужно настроить авторизацию, обработку ошибок, нормализацию данных, регулярные выгрузки и управление процессами. Но в результате вы получаете систему, которая масштабируется вместе с проектом и не зависит от ограничений веб-интерфейсов.

Вместо ручного сбора отчетов появится единая историческая база, где можно анализировать все языковые версии, корректно пересчитывать метрики, находить технические проблемы и строить нужные срезы данных без потери детализации.

Сохраняйте анонимность с Octo Browser, ведь отследить ваш реальный цифровой отпечаток невозможно.

Хотите попробовать Octo Browser со скидкой?
По промокоду OCTOBLOG получите 30% скидку на любую подписку. Предложение действительно только для новых пользователей.

Зачем уходить от веб-интерфейсов

Надежная система SEO-аналитики начинается с отказа от ручных выгрузок. Интерфейс Google Search Console удобен для быстрой проверки показателей, но его возможностей недостаточно для глубокой продуктовой аналитики.

GSC API позволяет получать данные на более детальном уровне — по отдельным URL, поисковым запросам и другим измерениям. Это дает возможность работать не только с агрегированными отчетами, но и с исходными данными, из которых можно формировать собственные срезы и метрики.

Чтобы понять преимущества такой архитектуры, важно учитывать несколько ключевых факторов.

Кардинальность данных и ограничения веб-интерфейса

Одна из главных проблем интерфейса GSC — ограниченный объем отображаемых данных. Для мультиязычного проекта это особенно критично: при большом количестве страниц, стран, устройств и запросов значительная часть информации остается за пределами стандартного отчета.

Здесь важна кардинальность — количество уникальных комбинаций параметров в наборе данных. Например, если сайт работает на 10 языках, получает трафик из 50 стран, с 3 типов устройств и по 10 000 поисковых запросов, количество возможных комбинаций измеряется миллионами строк.

Работать с таким объемом через веб-интерфейс практически невозможно. API позволяет получать существенно больше данных и разбивать выгрузку на отдельные сегменты. За счет фильтрации и последовательной обработки можно собирать не только верхнюю часть выдачи, но и длинный хвост запросов и URL, который обычно теряется в стандартных отчетах.

Озеро данных (Data Lake) и хранение истории

Google Search Console хранит исторические данные в интерфейсе только за последние 16 месяцев, чего недостаточно для долгосрочной SEO-аналитики.

Эту проблему решает собственное хранилище данных, например BigQuery. В него можно регулярно сохранять сырые данные, полученные через API, не ограничиваясь сроком хранения в интерфейсе GSC. Так у вас будет историческая база SEO-данных, которую можно использовать для долгосрочного анализа, построения отчетов и повторной обработки данных в любых необходимых разрезах.

Зависимость от внешних сервисов и цена масштабирования 

Для автоматической выгрузки данных можно использовать готовые ETL-коннекторы — например, SaaS-сервисы вроде Supermetrics или Fivetran. Они позволяют быстро настроить передачу данных без собственной разработки, но при масштабировании такой подход может стать дорогим и слишком сильно привязать инфраструктуру к конкретному сервису.

SaaS-платформы тарифицируют услуги по объему обрабатываемых строк или количеству коннекторов. Когда ваш мультиязычный проект начнет генерировать гигабайты сырых SEO-данных в сутки, счет за использование подобного сервиса превысит стоимость хранения данных в BigQuery и аренды небольшого сервера под Python-скрипты в несколько раз.

Кроме того, чем глубже сервис встроен в процесс сбора и трансформации данных, тем сложнее затем отказаться от него: миграция может потребовать перенастройки коннекторов, логики обработки и отчетности.

Уровень детализации данных 

При сборе данных через API важно сохранять максимально возможную детализацию. Если объединить данные уже на этапе выгрузки, восстановить исходные разрезы позже не получится.

Например, при проектировании SEO-базы стоит отдельно сохранять такие параметры, как тип устройства (Device) и страна (Country). Если скрипт запросит данные без разбивки по странам, GSC вернет уже суммарное количество кликов по запросу. После этого определить, сколько кликов пришло из Германии, а сколько из Франции, будет невозможно.

Поэтому лучше хранить данные в детализированном виде, а объединять и рассчитывать итоговые метрики уже на этапе анализа или визуализации. Так вы сохраняете возможность в будущем строить любые необходимые срезы — даже если изначально они не были предусмотрены в отчетах.

Ограничения GSC API при массовой выгрузке данных 

На первый взгляд работа с GSC API выглядит просто: авторизовать скрипт, получить данные, сохранить их в базу и перейти к анализу. На практике для крупных проектов такой сценарий быстро упирается в технические ограничения API.

Если попытаться выгружать большие объемы данных без учета этих ограничений, можно столкнуться с тайм-аутами, ошибками 429 Too Many Requests и неполными выгрузками. В результате в хранилище попадет только часть данных, а сама система будет работать нестабильно.

Поэтому при построении пайплайна важно заранее учитывать лимиты API, задержку обновления данных, квоты на количество запросов и механизмы повторных обращений при ошибках. Разберем основные ограничения GSC API и способы корректно работать с ними.

Лимит в 50 000 строк и сегментация выгрузки

Согласно документации Google, параметр rowLimit позволяет получить не более 25 000 строк за один запрос. Для постраничной выгрузки используется параметр startRow: сначала можно запросить первые 25 000 строк, затем следующие 25 000.

Однако здесь действует дополнительное ограничение: сумма startRow + rowLimit не может превышать 50 000. Поэтому для одной даты и выбранной комбинации параметров получить 50 001-ю строку таким способом уже не получится.

Если дневная кардинальность ваших данных превышает 50 000 строк, выгрузку нужно разбивать на отдельные сегменты с помощью Dimension Filters. Например, можно запрашивать данные отдельно по языковым папкам — /de/, /fr/ и т. д. — или дополнительно делить URL по шаблонам с помощью регулярных выражений.

Так вы сможете получить полные данные за счет нескольких независимых запросов к разным сегментам.

Задержка данных и работа с dataState 

GSC API имеет системную задержку обновления, которая составляет от 48 до 72 часов. Поэтому при ежедневной выгрузке важно различать предварительные и окончательные данные.

За это отвечает параметр dataState. У него есть два значения:

  • "final" (по умолчанию) — возвращает только полностью агрегированные и проверенные данные.

  • "all" — включает свежие данные, которые еще не прошли финальную обработку.

Из-за этого при построении пайплайна возникает выбор между оперативностью и точностью. Рассмотрим оба сценария.

  • Использование dataState: "final" (поведение по умолчанию). В этом режиме данные за последние сутки могут быть еще недоступны. Если ваш скрипт попытается выгрузить yesterday со значением по умолчанию, API вернет пустой массив. Необходимо ставить жесткое смещение current_date — 3 days.

  • Использование dataState: "all". Вы получите нужный массив за прошедшие 24 часа. Но Google предупреждает, что свежие данные являются предварительными. Система еще не свела все дубликаты, не отфильтровала спам-ботов и не пересчитала аномалии. Через 2–3 дня эти цифры изменятся на серверах самого Google.

Как это может повлиять на архитектуру хранилища: если ваш Python-скрипт просто добавляет сырые свежие данные в BigQuery, ваша историческая база будет искажена. Записывая «свежие» метрики, вы сохраняете черновик, который никогда не совпадет с финальными отчетами в интерфейсе GSC.

Поэтому для оперативной аналитики лучше использовать двухэтапную схему:

  1. Выгружать данные за предыдущий день с dataState: "all".

  2. Одновременно с этим скрипт должен делать повторную выгрузку за current_date — 4 days с параметром dataState: "final".

  3. В BigQuery вместо простого добавления (Append) используйте оператор MERGE (или Upsert-логику). Скрипт должен находить в базе предварительные данные четырехдневной давности и перезаписывать их финальными, консолидированными значениями.

Такой подход позволяет одновременно видеть свежие показатели на дашборде и сохранять корректную историческую базу после финальной обработки данных.

Лимиты API и экспоненциальная задержка

GSC API ограничивает количество запросов, чтобы защищать инфраструктуру от чрезмерной нагрузки. Для GSC API действуют строгие квоты: 50 запросов в секунду (QPS) и 1 200 запросов в минуту (QPM) на один проект. Поэтому при массовой выгрузке данных эти ограничения необходимо учитывать заранее.

Проблема особенно заметна, когда данные приходится разбивать на сотни сегментов для обхода лимита в 50 000 строк. Чтобы ускорить процесс, разработчики часто используют асинхронные запросы (asyncio) или пулы потоков (ThreadPoolExecutor). Но так 50 QPS быстро исчерпываются, и API начинает возвращать ошибки 429 Too Many Requests или 503 Service Unavailable.

Простая задержка через time.sleep() здесь работает не лучшим образом. Если несколько параллельных потоков одновременно получают ошибку и затем засыпают на одинаковое время, они почти одновременно возобновят работу и снова создадут пиковую нагрузку.

Правильная архитектура скрипта должна включать паттерн экспоненциальной задержки с добавлением случайного шума (Jitter). Так интервал между повторными запросами будет постепенно увеличиваться. Все потоки не будут повторять запросы одновременно и меньше шанс, что они превысят лимиты.

В Python эту логику не обязательно реализовывать вручную: можно использовать декораторы из библиотеки tenacity.

Сбор SEO-данных для поддоменов и языковых папок

После учета лимитов и задержек GSC API следующий важный вопрос — как именно организован мультиязычный сайт. Структура проекта напрямую влияет на логику выгрузки, нормализации и объединения данных. 

В мультиязычном SEO существует два полярных подхода к структуре сайта: национальные поддомены и языковые папки. Для пользователя разница минимальна, но для формирования выгрузки разная структура может полностью поменять подход.

Поддомены и отдельные домены

Если языковые версии размещены на отдельных доменах (site.de, site.fr) или поддоменах (de.site.com, fr.site.com), данные по ним приходится собирать как по отдельным ресурсам.

Зачем это бизнесу? Изоляция регионов позволяет жестко контролировать краулинговый бюджет. Поисковик не будет тратить лимиты немецкого бота на сканирование французской версии сайта. С точки зрения SEO это самый безопасный путь для масштабирования.

Для аналитического пайплайна это создает две проблемы:

  • Больше точек подключения. Если у проекта 10 языковых версий, скрипту необходимо последовательно или параллельно обращаться к нескольким ресурсам GSC. Чем больше таких источников, тем важнее учитывать квоты API, обработку ошибок и устойчивость всей схемы выгрузки.

  • Сложность нормализации URL (склейка данных). Одинаковые по назначению страницы на разных доменах будут иметь разные адреса — например, site.de/product и site.fr/product. Чтобы сравнивать их показатели как одну сущность, URL нужно привести к общему виду.

В библиотеке Pandas (Python) эта нормализация выглядит так:

import pandas as pd
from urllib.parse import urlparse

# Оставляем только путь (Path) для склейки метрик разных стран
df['normalized_url'] = df['page'].apply(lambda x: urlparse(x).path) 
# Результат: /product

Без такой нормализации показатели разных локализаций останутся разделены между отдельными URL. Это затруднит расчет общей эффективности одной и той же страницы или шаблона на разных языках.

Языковые папки и сегментация данных

Если языковые версии размещены в папках — например, site.com/de/ и site.com/fr/ — весь проект остается в рамках одного домена. Это упрощает сбор данных: вместо отдельных обращений к нескольким ресурсам можно работать с одним профилем Domain Property в Google Search Console. 

Вместо 10 разных запросов можно делать одну массивную выгрузку (с применением фильтрации для обхода лимита в 50 000 строк). Так вы экономите квоты API Google и снижаете нагрузку на сеть.

Крупную выгрузку все равно приходится делить на сегменты. Но сама архитектура становится проще: меньше точек подключения, меньше запросов и ниже нагрузка на API.

Поскольку API отдает нам сплошной поток URL, скрипт должен самостоятельно разметить строки маркерами стран. Это делается с помощью регулярных выражений (RegEx).

Если брать библиотеку Pandas, мы извлекаем маркер языка прямо из URL:

df['language_market'] = df['page'].str.extract(r'\.com/([a-z]{2})/')
# Обработка исключений: если RegEx вернуло NaN, значит, это основная версия сайта
df['language_market'].fillna('en', inplace=True)

Так из URL вида site.com/de/product можно получить маркер de и использовать его при дальнейшем анализе.

Основное ограничение этого подхода — зависимость от структуры URL. Регулярное выражение должно точно соответствовать правилам формирования языковых версий. Если часть страниц использует другой шаблон, например site.com/category-de/product, такие URL могут быть определены неверно или вообще не попасть в нужный сегмент.

Поэтому перед настройкой RegEx важно проверить все варианты формирования языковых URL и отдельно обработать исключения.

Трансформация данных и расчет метрик в Pandas

После сбора и нормализации данные необходимо объединить и подготовить к анализу. Для этого удобно использовать Pandas: библиотека позволяет работать с большими таблицами, объединять источники и рассчитывать метрики на уровне строк и групп.

Объединение данных GSC и GA4 по URL

Google Search Console отображает поисковые метрики — показы, клики, CTR и позиции. GA4 дополняет их поведенческими и бизнес-показателями, например сессиями и конверсиями.

Чтобы получить более полную картину эффективности SEO-трафика, данные из GSC и GA4 можно объединить по общему ключу — нормализованному URL посадочной страницы.

В Pandas это делается через объединение таблиц по общему ключу — нормализованному URL:

import pandas as pd

# df_gsc выгрузка из Search Console
# df_ga4 выгрузка из GA4 (Sessions, Conversions)

# Объединяем данные по посадочной странице (Left Join, чтобы не потерять страницы без трафика)
merged_df = pd.merge(df_gsc, df_ga4, how='left', left_on='landing_page', right_on='page_path')

# Теперь мы можем рассчитать конверсию конкретного SEO-кластера:
merged_df['seo_conversion_rate'] = (merged_df['conversions'] / merged_df['clicks']) * 100

Корректный расчет CTR и средней позиции

При объединении данных нескольких языковых версий нельзя рассчитывать CTR и среднюю позицию через обычное среднее арифметическое. Такой подход искажает результат, потому что не учитывает разный объем показов.

Например:

  • французский поддомен: 2 клика из 4 показов, CTR = 50%;

  • немецкий поддомен: 20 кликов из 1 000 показов, CTR = 2%.

Если просто усреднить значения CTR, получится:

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

Но фактический CTR по двум поддоменам равен:

22 клика / 1004 показа = 2,19%

Поэтому при агрегации данных разных локализаций метрики нужно пересчитывать на основе исходных значений:

  • CTR рассчитывается как отношение суммарного количества кликов к суммарному количеству показов.

  • Средняя позиция должна быть взвешенной по показам: позиция каждой строки умножается на количество показов, после чего сумма этих значений делится на общее количество показов.

В Pandas это можно реализовать так:

# Группируем данные по поисковому запросу для всех стран сразу
def weighted_metrics(x):
    # Взвешенная средняя позиция = Сумма (Позиция * Показы) / Сумма показов
    weighted_pos = (x['position'] * x['impressions']).sum() / x['impressions'].sum()
    # Реальный CTR
    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
    })

# Применяем функцию к сгруппированному датафрейму
final_cluster_data = merged_df.groupby('query').apply(weighted_metrics)

Автоматизация мониторинга hreflang и каннибализации

Собственное хранилище данных можно использовать не только для отчетности, но и для автоматического поиска технических SEO-проблем. Для мультиязычных проектов особенно важны два типа ошибок: разорванные связи локализации и внутренняя конкуренция нескольких страниц за один и тот же поисковый запрос. 

Автоматический контроль hreflang 

Техническая SEO-оптимизация международных проектов опирается на консистентность и двунаправленность тегов локализации. Тег hreflang работает как строгая двунаправленная система перекрестных ссылок. Если, к примеру, французская страница ссылается на немецкую как на альтернативную, немецкая обязана содержать обратную ссылку. Разрыв этой цепи ломает весь кластер в глазах Google.

На крупном проекте вручную проверять такие связи невозможно, поэтому контроль лучше строить на сравнении хотя бы двух источников данных: 

  • Screaming Frog. Вы запускаете краулер по расписанию. Он сканирует фактическое наличие тегов в HTML-коде, валидирует коды языков (ISO 639-1) и стран (ISO 3166-1 Alpha 2). Результат выгружается в базу данных.

  • GSC API. API Search Console отдает отчет об индексации и показывает, как именно Google интерпретировал эти связи во время последнего обхода.

Результаты краулинга и данные из Google можно сохранять в одну базу и затем сопоставлять через SQL. Например, FULL OUTER JOIN позволяет находить критические баги в агрегированных данных: страницы, которые технически имеют правильные теги в коде, но проигнорированы поисковиком.

Причин этому может быть много, как вариант — рендеринг на стороне клиента: JavaScript-фреймворки (React, Vue) слишком долго рендерят теги в <head> или показатели скорости (Core Web Vitals) настолько низкие, что краулер Googlebot отваливается по тайм-ауту, не успев прочитать hreflang. Автоматика ловит эти моменты до того, как трафик начнет падать.

Каннибализация трафика и поиск конфликтующих URL

Вторая проблема мультиязычности — внутренняя конкуренция. Каннибализация возникает, когда поисковик путается в релевантности и начинает ранжировать, например, английскую версию страницы по запросу из Германии, хотя у вас есть посадочная страница на немецком языке.

В стандартном интерфейсе GSC такие пересечения сложно анализировать на больших объемах данных. Если же сырые данные хранятся в BigQuery, потенциальную каннибализацию можно выявлять автоматически с помощью SQL. 

Алгоритм выявления каннибализации такой:

  1. Группируем массив данных по двум параметрам: query и country.

  2. Подсчитываем количество уникальных URL (COUNT(DISTINCT page)), получающих показы по этой связке.

  3. Фильтруем результаты с помощью HAVING count > 1.

Если по одной связке query + country показы получают несколько страниц, это сигнал о возможном конфликте релевантности.

Данные GSC можно дополнить проверкой фактической поисковой выдачи по нужным регионам. Это особенно полезно в случаях, когда аналитика уже обнаружила аномалию, но по цифрам сложно понять, что именно видит пользователь и какую версию страницы Google показывает в конкретной стране.

Подробнее о способах автоматического сбора SERP мы рассказывали в отдельной статье. А если нужно вручную проверить отдельные запросы и локализации в разных региональных окружениях, используйте антидетект-браузер, такой как Octo Browser.

Как Octo Browser дополняет SEO-аналитику

GSC и BigQuery хорошо подходят для поиска проблем на больших объемах данных. С их помощью можно заметить, например, что немецкая страница начала терять показы, по запросам из определенной страны ранжируется не та локализация или несколько URL конкурируют между собой.

Но после такой находки обычно возникает вопрос: а что видит пользователь в поисковой выдаче?

Данные GSC помогают найти аномалию и понять ее масштаб. Для диагностики конкретного случая полезно посмотреть на выдачу из нужного региона и проверить, как ведет себя сайт.

Здесь пригодится Octo Browser. Для разных стран можно создать отдельные профили, подключить к ним прокси с нужным гео и проводить проверки в изолированных браузерных сессиях. Это удобно, когда приходится регулярно работать сразу с несколькими гео и не хочется смешивать куки, историю и другие данные между проверками.

Представим, что наш скрипт обнаружил: по запросам из Германии показы получает английский URL, хотя на сайте существует полноценная немецкая версия /de/. Это еще не означает, что проблема точно связана с локализацией. Сначала стоит посмотреть, что происходит в самой выдаче.

Открываем профиль Octo с немецким прокси и проверяем, какой URL Google показывает по нужному запросу. Заодно можно посмотреть, открывается ли правильная версия сайта, нет ли автоматического редиректа на другую локаль и соответствует ли контент страницы выбранному региону.

Таким же способом можно выборочно проверять:

  • появление неправильной языковой версии в SERP;

  • различия выдачи между несколькими регионами;

  • работу региональных редиректов;

  • локализацию контента, цен и других элементов страницы;

  • изменения после исправления hreflang, canonical или внутренней перелинковки.

Таким образом, GSC API и BigQuery помогут находить подозрительные случаи в масштабе всего проекта, а Octo Browser — разбирать отдельные аномалии, используя нужные гео в изолированном окружении.

Заключение

Перенос SEO-аналитики из веб-интерфейсов в собственную систему сбора и хранения данных — это переход управления проектом на качественно новый уровень.

На старте такая архитектура требует больше технической работы: нужно настроить авторизацию, обработку ошибок, нормализацию данных, регулярные выгрузки и управление процессами. Но в результате вы получаете систему, которая масштабируется вместе с проектом и не зависит от ограничений веб-интерфейсов.

Вместо ручного сбора отчетов появится единая историческая база, где можно анализировать все языковые версии, корректно пересчитывать метрики, находить технические проблемы и строить нужные срезы данных без потери детализации.

Следите за последними новостями Octo Browser

Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.

Следите за последними новостями Octo Browser

Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.

Следите за последними новостями Octo Browser

Нажимая кнопку, вы соглашаетесь с нашей политикой конфиденциальности.

Присоединяйтесь к Octo Browser сейчас

Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.

Присоединяйтесь к Octo Browser сейчас

Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.

Присоединяйтесь к Octo Browser сейчас

Вы можете обращаться за помощью к нашим специалистам службы поддержки в чате в любое время.

©

2026

Octo Browser

©

2026

Octo Browser

©

2026

Octo Browser