JavaScript и индексирование: что Google получает до и после рендеринга

JavaScript и индексирование: что Google получает до и после рендеринга

У JavaScript-страницы полезно различать как минимум два состояния: HTML, который сервер вернул в HTTP-ответе, и DOM после выполнения JavaScript. Они могут совпадать почти полностью, а могут отличаться радикально. Например, сервер отдаёт пустую оболочку с <div id="app">, а заголовок, текст, карточки, ссылки и метаданные появляются только после запросов к API.

Google умеет выполнять JavaScript и обрабатывает страницы через crawling, rendering и indexing. Но для диагностики этого недостаточно знать фразу «Google рендерит JS». Нужно проверить, что было в исходном ответе, что появилось после рендеринга и какие элементы действительно доступны в отрендеренном HTML. Именно сравнение этих состояний помогает отделить JavaScript-проблему от HTTP, robots, canonical или обычной ошибки данных.

Source HTML, DOM и rendered HTML — не одно и то же

Термины часто смешивают, хотя для отладки разница практическая.

Состояние Что это Что в нём искать
HTTP response HTML Тело HTML-документа, полученное от сервера Основной текст, title, canonical, robots, ссылки, точки подключения JS
DOM в браузере Текущее дерево документа после parsing и работы JavaScript Что добавил, изменил или удалил клиентский код
Rendered HTML Google Результат обработки страницы Web Rendering Service Контент и элементы, которые Google получил после своего рендеринга

DOM в вашем браузере тоже не является автоматическим доказательством того, что Google увидел ровно то же самое. Локальная сессия может иметь cookies, Local Storage, авторизацию, уже прогретый кэш или состояние после клика. Web Rendering Service работает в собственных условиях, а его фактический результат нужно проверять инструментами Google.

Как Google обрабатывает JavaScript-страницу

В текущей документации Search Central процесс разделён на три крупных этапа: crawling, rendering и indexing. Googlebot сначала получает URL, проверяет возможность обхода, делает HTTP-запрос и анализирует полученный ответ. Из доступного HTML он уже может извлечь обычные ссылки с href.

Если страница отвечает 200 и не содержит запрета на индексирование, она передаётся на рендеринг. Web Rendering Service выполняет JavaScript в Chromium и возвращает отрендерированный HTML на дальнейшую обработку. Google указывает, что страницы с 200 отправляются в очередь rendering даже тогда, когда JavaScript на них вообще нет.

Здесь нет полезной модели «HTML индексируется одним роботом, а JavaScript когда-нибудь потом другим». Для разработчика важнее другое: между исходным HTTP-ответом и результатом rendering существует отдельная техническая граница, на которой содержимое страницы может измениться.

Схема crawling, rendering и indexing JavaScript-страницы поисковым роботом

Самый простой тест: что исчезнет, если JavaScript не выполнится

Возьмём клиентское приложение, которое получает данные после загрузки:

<div id="product"></div>

<script>
fetch('/api/product/42')
  .then(r => r.json())
  .then(product => {
    document.querySelector('#product').innerHTML =
      `<h1>${product.name}</h1>
       <p>${product.description}</p>`;
  });
</script>

В response HTML нет ни названия товара, ни описания. Они возникают только после успешного HTTP-запроса к API и выполнения JavaScript.

Теперь диагностический вопрос становится конкретным: может ли renderer получить API-response, не падает ли скрипт, появляется ли основной контент в rendered HTML? Если да, Google способен обработать его. Если нет, проблема находится не в «JavaScript SEO» как абстракции, а в конкретной цепочке загрузки данных или рендеринга.

Критичный контент лучше не прятать за лишним условием

Не вся клиентская генерация сама по себе проблемна. Риск появляется, когда основной контент зависит от условий, которые crawler не воспроизводит.

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

button.addEventListener('click', async () => {
  const content = await fetch('/api/details').then(r => r.text());
  document.querySelector('#details').innerHTML = content;
});

Google Search не взаимодействует со страницей как обычный пользователь: не кликает, не вводит текст и не прокручивает интерфейс ради того, чтобы открыть спрятанный материал. Поэтому lazy-loading основного контента не должен зависеть от пользовательского действия. Если блок должен быть индексируемым, он должен становиться доступным при обычной загрузке или при попадании в viewport без обязательного клика.

Это особенно заметно в интерфейсах с «показать ещё», accordion-компонентами, бесконечной лентой и кастомными виджетами. Сам визуальный паттерн не запрещён; значение имеет способ появления содержимого.

Ссылки после JavaScript тоже должны оставаться ссылками

JavaScript может добавлять навигацию в DOM, и Google способен находить такие URL. Но для crawlable navigation всё равно нужен нормальный элемент <a> с href.

Например, такой вариант понятен как ссылка:

<a href="/catalog/chairs/">Стулья</a>

А обработчик клика на произвольном <div> не создаёт такой же явной связи между документами:

<div onclick="location.href='/catalog/chairs/'">Стулья</div>

Для сайта это уже выходит за пределы одной JavaScript-страницы: способ построения ссылок определяет, как crawler обнаруживает соседние URL. Поэтому следующий уровень этой темы — внутренние ссылки и orphan pages.

Canonical можно добавить JavaScript-ом, но лучше не создавать две версии истины

Google умеет обрабатывать rel="canonical", добавленный во время рендеринга. Однако Search Central рекомендует по возможности задавать canonical в HTML и не менять его JavaScript-ом на другой URL.

Сценарий, который стоит считать подозрительным:

Source HTML:
<link rel="canonical" href="https://example.com/page-a/">

Rendered DOM:
<link rel="canonical" href="https://example.com/page-b/">

Здесь приложение создаёт два последовательных утверждения о главной версии документа. Если canonical нельзя сформировать на сервере, разумнее не класть в исходный HTML фиктивное значение, а добавить один корректный URL при рендеринге.

Для отладки важна не технология генерации тега сама по себе, а отсутствие противоречия между source и rendered state.

С noindex ситуация асимметрична

JavaScript может добавить noindex после получения данных. Например, SPA загрузила карточку товара, API сообщил, что объект удалён, и приложение добавило robots meta tag.

Но рассчитывать на противоположный сценарий опасно:

Source HTML:
<meta name="robots" content="noindex">

JavaScript:
удаляет noindex после загрузки данных

Google указывает, что после обнаружения noindex может пропустить rendering и выполнение JavaScript. Тогда скрипт, который должен снять запрет, вообще не получит шанс изменить документ. Если страница должна индексироваться, исходный HTML не должен начинаться с такого запрета.

SPA часто маскирует ошибку ответом 200

У client-side router есть неприятная особенность: веб-сервер может возвращать одну HTML-оболочку для любого пути.

GET /products/42       → 200 app shell
GET /products/missing  → 200 app shell
GET /anything          → 200 app shell

После запуска JavaScript первый URL превращается в реальный товар, второй — в сообщение «не найдено». Но на HTTP-уровне оба ответа одинаковые.

Так возникает soft 404: сервер сообщил об успехе, хотя итоговый документ фактически является страницей ошибки. Google рекомендует для SPA либо направлять пользователя на URL, где сервер действительно возвращает 404, либо добавлять noindex для ошибочного состояния.

Здесь особенно полезно не смешивать два наблюдения: «приложение красиво показало 404-screen» и «HTTP-запрос получил 404». Это не одно и то же.

CSR, SSR и prerendering: вопрос не сводится к «что лучше ранжируется»

Client-side rendering строит значительную часть HTML в браузере. Server-side rendering возвращает уже сформированную разметку в HTTP-ответе. Prerendering создаёт HTML заранее, например на этапе сборки.

Google способен работать с JavaScript-контентом, поэтому CSR сам по себе не означает «страница не индексируется». Но SSR или предварительная отрисовка уменьшают количество условий между запросом URL и появлением основного содержимого. Search Central рекомендует по возможности использовать server-side rendering или prerendering; кроме того, не все роботы вообще выполняют JavaScript.

При этом из выбора SSR нельзя выводить гарантированный рост позиций. Это архитектурное решение, которое влияет на доступность разметки, производительность и сложность системы. Ранжирование — уже другой вопрос.

Dynamic rendering, где crawler и пользователь получают разные технические версии через отдельный renderer, Google сейчас описывает как workaround, а не как долгосрочное рекомендуемое решение. Для новых проектов обычно рациональнее решить задачу на уровне нормальной стратегии rendering.

Не полагайтесь на состояние браузера, которое crawler не сохраняет

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

Google отдельно предупреждает, что Web Rendering Service не сохраняет Local Storage, Session Storage и cookies между загрузками страниц. Если важный контент появляется лишь после того, как пользователь уже однажды посетил другой URL, crawler способен получить совсем другое состояние.

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

Как сравнить source и rendered state без догадок

Для одной страницы я бы сохранял два снимка и один контрольный результат.

Проверка Source HTML Rendered HTML Что ищем
Основной текст Есть / нет Есть / нет Не исчезает ли главный смысл страницы
H1 и ключевые блоки Есть / нет Есть / нет Успешно ли загрузились данные
Внутренние ссылки Список URL Список URL Какие связи появляются только после JS
Canonical URL или отсутствует URL или отсутствует Нет ли смены на другой target
Robots meta Значение Значение Не возник ли noindex и не пытается ли JS его снять
Error state HTTP + shell Финальный экран Не маскируется ли soft 404

После локального сравнения нужен контроль со стороны Google. В URL Inspection и Rich Results Test можно посмотреть загруженные ресурсы, JavaScript errors и rendered DOM. Для indexability это полезнее, чем скриншот браузера: проверяется не внешний вид, а фактическое состояние документа после обработки.

Сравнение Source HTML и Rendered DOM при диагностике JavaScript-страницы

Диагностический порядок для JavaScript-страницы

  1. Проверить HTTP. Какой статус возвращает URL до выполнения JavaScript?
  2. Сохранить response HTML. Есть ли в нём основной контент, title, robots, canonical и ссылки?
  3. Проверить доступность ресурсов. Получаются ли JS, CSS и API-запросы, нужные для основного документа?
  4. Отрендерить страницу. Появился ли ожидаемый контент без кликов и разрешений?
  5. Сравнить DOM. Что JS добавил, удалил или поменял?
  6. Проверить error routes. Не возвращает ли SPA 200 там, где ресурс отсутствует?
  7. Проверить ссылки. Являются ли переходы настоящими <a href>?
  8. Сверить canonical и robots. Не конфликтуют ли source и rendered values?
  9. Проверить результат Google. Сопоставить свои наблюдения с rendered HTML в инструментах Search Console.

Такой порядок не пытается обвинить JavaScript первым. Иногда проблема обнаруживается уже на первом шаге: сервер вернул ошибку, robots.txt закрыл URL или исходный HTML содержит noindex. Тогда renderer здесь вообще не первопричина.

Где заканчивается JavaScript-диагностика

Если основной контент присутствует в rendered HTML, HTTP-состояние корректно, robots directives не запрещают индексирование, canonical не меняется на неожиданный URL, а нужные ссылки доступны crawler, JavaScript-слой можно считать проверенным на своём уровне. Это ещё не обещание индексации и тем более не обещание позиции.

Для важной страницы дальше нужен уже общий технический контекст: HTTP, crawlability, indexability, canonical, rendering и внутренняя связность рассматриваются вместе в проверке технической готовности страницы.

Практически это и есть полезная граница: не спрашивать «любит ли Google JavaScript», а сравнить два документа — что сервер отдал и что поисковый renderer в итоге смог получить.

Источники

Источники проверены 19 августа 2026 года. Для поведения Google использована актуальная официальная документация Search Central; для моделей rendering — документация web.dev.