Зачем проверять рендеринг JavaScript-контента
Современные сайты всё активнее используют JavaScript для формирования контента: React, Vue, Angular, Next.js, Nuxt — фреймворки, которые рендерят страницу в браузере пользователя (Client-Side Rendering, CSR). Проблема в том, что поисковые роботы обрабатывают JavaScript иначе, чем браузер, — и могут видеть совсем не тот контент, который видит пользователь.
Яндекс умеет рендерить JavaScript, но делает это с задержкой и не всегда полностью. Робот Яндекса сначала скачивает HTML, и если контент формируется на клиенте, он может проиндексировать пустую страницу или страницу с шаблонными плейсхолдерами. Повторный визит для рендеринга JS может произойти через дни или недели — а может не произойти вовсе, если бюджет краулинга исчерпан.
Google (ограничен в РФ с 2022 года, но его робот всё ещё сканирует российские сайты) использует двухэтапный процесс: сначала индексирует HTML, потом ставит страницу в очередь на рендеринг через Chromium. Задержка между первым и вторым этапом может составлять часы, дни и даже недели — зависит от нагрузки.
Если ваш сайт генерирует ключевой контент через JavaScript — заголовки, описания товаров, цены, тексты статей, внутренние ссылки, структурированные данные — вы рискуете тем, что поисковик увидит пустую или неполную страницу. Результат: потеря позиций, отсутствие сниппетов, неработающая разметка Schema.org.
Пошаговая инструкция
Шаг 1. Определите, зависит ли ваш сайт от JavaScript
Не каждый сайт использует JS для формирования контента. Стандартный WordPress без headless-архитектуры отдаёт готовый HTML — JavaScript лишь добавляет интерактивность (слайдеры, формы, анимации). В таком случае проверка рендеринга — формальность.
Но проверить стоит, потому что JavaScript может влиять на контент неочевидно:
- Лейзилоуд контента: текст или блоки подгружаются через JS при скролле или по событию.
- Табы и аккордеоны: контент внутри скрытых табов может генерироваться динамически.
- Цены и наличие: подтягиваются через AJAX-запрос к API.
- Отзывы: загружаются через сторонние виджеты (JS).
- Меню и навигация: формируются через JavaScript.
- Schema.org: JSON-LD вставляется через JS, а не серверно.
Быстрый тест: откройте страницу в браузере, нажмите Ctrl+U (просмотр исходного кода). Если в HTML-коде вы видите свой контент (заголовки, тексты, ссылки) — контент рендерится на сервере. Если вместо контента пустые <div id="app"></div> и JS-скрипты — контент рендерится на клиенте.
Шаг 2. Сравните исходный HTML и отрендеренный DOM
Это ключевой шаг. Вам нужно сравнить два состояния страницы:
- Исходный HTML (source): то, что сервер отдаёт в ответ на запрос. Это видит робот при первом обращении.
- Отрендеренный DOM (rendered): то, что получается после выполнения JavaScript. Это видит пользователь в браузере.
Через DevTools:
- Откройте страницу, нажмите Ctrl+U — это исходный HTML.
- Нажмите F12 → вкладка «Elements» — это отрендеренный DOM.
- Сравните: есть ли в исходном HTML ваш контент (заголовки H1-H3, основной текст, ссылки)? Если в Elements контент есть, а в View Source — нет, значит, он генерируется JavaScript.
Через расширение View Rendered Source:
Расширение для Chrome «View Rendered Source» показывает отрендеренный HTML-код рядом с исходным и подсвечивает различия. Установите из Chrome Web Store и используйте для быстрого сравнения.
Через Screaming Frog:
- Просканируйте сайт в режиме «JavaScript Rendering»: Configuration → Spider → Rendering → JavaScript.
- Screaming Frog использует встроенный Chromium для рендеринга страниц.
- Сравните результаты: если при обычном сканировании (без JS) Title или H1 пустые, а при JS-рендеринге — заполнены, значит, контент зависит от JavaScript.
Шаг 3. Проверьте через Яндекс Вебмастер
В Яндекс Вебмастере есть инструмент для проверки того, как робот видит страницу:
- Перейдите в «Инструменты» → «Проверка ответа сервера».
- Введите URL и нажмите «Проверить».
- Вебмастер покажет HTML, который получил робот. Проверьте: есть ли в нём ваш контент.
Также используйте «Инструменты» → «Проверить URL» — это покажет, как Яндекс проиндексировал конкретную страницу: title, description, текст, ссылки. Если контент отсутствует или неполный — проблема с JS-рендерингом подтверждена.
Дополнительно: в разделе «Индексирование» → «Страницы в поиске» → «Исключённые страницы» ищите страницы с причиной «Пустая страница» или «Мало контента». Если эти страницы на самом деле содержат контент (видимый пользователю) — робот не смог его отрендерить.
Шаг 4. Проверьте через Google Search Console
В Google Search Console инструмент «Проверка URL» показывает отрендеренную версию страницы:
- Введите URL в строку проверки.
- Нажмите «Проверить действующий URL».
- В результатах нажмите «Посмотреть проверенную страницу» → «Скриншот» — увидите, как Googlebot отрендерил страницу.
- Вкладка «HTML» — покажет отрендеренный HTML-код после выполнения JavaScript.
Если скриншот показывает пустую или неполную страницу — Google не может отрендерить ваш JS-контент.
Шаг 5. Определите причину проблем с рендерингом
Если робот не видит контент, причин может быть несколько:
1. CSR (Client-Side Rendering) без SSR. Весь контент генерируется в браузере через JavaScript. Сервер отдаёт пустой HTML с загрузчиком. Решение — перейти на SSR (Server-Side Rendering) или SSG (Static Site Generation).
2. Блокировка JS-ресурсов. Если CSS или JS файлы, необходимые для рендеринга, закрыты в robots.txt — робот не сможет их загрузить и выполнить. Проверьте: не закрыты ли /wp-content/, /wp-includes/ или внешние CDN в robots.txt.
3. Ошибки в JavaScript. Робот использует для рендеринга не самый современный движок. Если ваш JS содержит синтаксис, который не поддерживается (экспериментальные API, зависимость от специфических браузерных API), рендеринг упадёт с ошибкой. Проверьте консоль DevTools на ошибки.
4. Тайм-аут. Робот ждёт завершения рендеринга ограниченное время (обычно 5-10 секунд). Если JS выполняется дольше (тяжёлые запросы к API, медленные сторонние скрипты) — контент не успеет отрендериться.
5. Зависимость от действий пользователя. Контент, который появляется только после клика, скролла или hover — робот не увидит. Робот не кликает и не скроллит (за исключением ограниченного скролла у Google). Контент должен быть доступен при загрузке страницы.
6. Зависимость от localStorage / cookies. Если контент формируется на основе данных из localStorage или cookies — робот его не увидит, потому что у него нет этих данных.
Шаг 6. Решите проблему рендеринга
В зависимости от ситуации:
Вариант 1: Server-Side Rendering (SSR). Сервер генерирует полный HTML с контентом и отдаёт его роботу (и пользователю). JavaScript затем «подхватывает» страницу и добавляет интерактивность (гидрация). Это стандартный подход для Next.js (React) и Nuxt (Vue). Для WordPress с headless-архитектурой — используйте Next.js с WordPress REST API или GraphQL.
Вариант 2: Static Site Generation (SSG). Страницы генерируются заранее (при сборке) и раздаются как статический HTML. Идеально для сайтов, где контент не меняется при каждом запросе: блоги, каталоги услуг, информационные сайты. Next.js, Nuxt, Gatsby поддерживают SSG.
Вариант 3: Hybrid Rendering. Часть страниц рендерится на сервере (SSR), часть — заранее (SSG), часть — на клиенте (CSR). Современные фреймворки поддерживают такой подход: для каждого роута можно выбрать стратегию рендеринга.
Вариант 4: Dynamic Rendering. Сервер определяет, кто запрашивает страницу: если робот (по User-Agent) — отдаёт предварительно отрендеренный HTML; если пользователь — стандартный CSR. Это компромиссное решение, которое Яндекс и Google официально поддерживают, хотя предпочитают SSR. Инструменты: Rendertron, Prerender.io.
Вариант 5: Для WordPress без headless — исправить конкретные проблемы. Если стандартный WordPress отдаёт HTML, но отдельные блоки формируются через JS (цены, отзывы, Schema.org) — перенесите эти данные на серверную сторону. Выводите цены через PHP, Schema.org — через wp_head, отзывы — через шаблон, а не AJAX.
Шаг 7. Проверьте Schema.org разметку
Структурированные данные (JSON-LD) часто вставляются через JavaScript. Если робот не рендерит JS — он не увидит разметку, и расширенные сниппеты не появятся в выдаче.
Проверьте:
- Откройте исходный HTML (Ctrl+U) и найдите
<script type="application/ld+json">. Если разметка есть в исходном коде — всё в порядке. - Если разметки нет в исходном коде, но есть в DOM (F12 → Elements) — она вставляется через JavaScript и может быть невидима для робота.
- Проверьте через Schema Markup Validator — он покажет разметку, найденную в исходном HTML. Если разметка не обнаружена — перенесите JSON-LD на серверную сторону.
В WordPress JSON-LD лучше выводить через хук wp_head или через плагин (Yoast SEO, Rank Math) — они генерируют разметку серверно, без зависимости от JS.
Шаг 8. Настройте мониторинг
Проблемы с JS-рендерингом могут появиться после обновления фреймворка, добавления новых библиотек, изменения API-эндпоинтов. Настройте регулярные проверки:
- Еженедельно: проверяйте в Яндекс Вебмастере «Исключённые страницы» на предмет «пустых» или «тонких» страниц, которые на самом деле содержат контент.
- При каждом деплое: проверяйте ключевые страницы через Ctrl+U — убедитесь, что контент присутствует в HTML.
- Ежемесячно: сканируйте сайт Screaming Frog в двух режимах (с JS и без) и сравнивайте данные: Title, H1, количество слов на странице, количество внутренних ссылок. Расхождения — сигнал проблемы.
Типичные ошибки
- Считать, что поисковики полностью рендерят JS. Яндекс и Google умеют выполнять JavaScript, но с ограничениями: задержки, тайм-ауты, неполная поддержка API. Полагаться на JS-рендеринг со стороны поисковика — рискованная стратегия. Серверный рендеринг всегда надёжнее.
- Блокировать JS-файлы в robots.txt. Если робот не может загрузить JavaScript-файлы, он не сможет отрендерить страницу. Не закрывайте CSS и JS в robots.txt. Проверьте:
/wp-content/themes/и/wp-content/plugins/должны быть открыты для сканирования. - Использовать lazy load для контента выше первого экрана. Ленивая загрузка изображений и контента ниже fold — правильно. Но если основной текст страницы загружается лениво — робот может не увидеть его при первом рендере. Контент первого экрана должен быть доступен без дополнительных событий.
- Зависеть от сторонних API. Если контент подгружается через внешний API (отзывы с Google, цены из CRM, данные из PIM), и API не отвечает — страница останется пустой. Кешируйте данные внешних API на сервере и отдавайте из кеша при рендере.
- Не проверять рендеринг после обновлений. Обновили React с 17 до 18, поменяли API-endpoint, добавили новый сторонний скрипт — любое из этих изменений может сломать рендеринг для робота. Включите проверку рендеринга в чеклист деплоя.
- Dynamic Rendering = cloaking. Нет. Яндекс и Google официально поддерживают dynamic rendering — показ предварительно отрендеренного HTML роботам и CSR пользователям. Это не клоакинг, если контент идентичен. Клоакинг — это когда роботу показывают другой контент, чем пользователю.
- Забывать про meta-теги. Title, description, canonical, og:tags — если они вставляются через JavaScript, робот может их не увидеть при первом проходе. Мета-теги всегда должны быть в серверном HTML. В Next.js используйте
<Head>компонент, в Nuxt —useHead()илиuseSeoMeta().
Что проверить в итоге
- Основной контент страницы (H1, текст, ключевые ссылки) присутствует в исходном HTML (Ctrl+U), а не только в отрендеренном DOM.
- Title, description, canonical и og:tags находятся в серверном HTML, не зависят от JavaScript.
- JSON-LD разметка Schema.org выводится в исходном HTML через серверный рендеринг.
- CSS и JS файлы, необходимые для рендеринга, не заблокированы в robots.txt.
- Консоль DevTools (F12 → Console) не показывает критических JS-ошибок на ключевых страницах.
- Проверка в Яндекс Вебмастере («Проверить URL») показывает полный контент страницы.
- Screaming Frog при сканировании без JS и с JS показывает одинаковые Title, H1 и сопоставимое количество слов на странице.
- Контент первого экрана доступен без скролла, клика или других пользовательских действий.
- Данные от внешних API кешируются на сервере — страница не зависит от доступности сторонних сервисов в момент рендеринга.
- В «Исключённых страницах» Яндекс Вебмастера нет страниц с причиной «Пустая страница» или «Мало контента», которые на самом деле содержат контент.