← Все статьи

SiteGuard12 мин чтения

JavaScript SEO: как проверить, видит ли Google содержимое SPA

Для JavaScript SEO важно доказать, что по конкретному URL Google получает нужный текст, рабочие ссылки и согласованные метаданные. Ответ HTTP 200, красивая страница в вашем браузере и установленный SSR по отдельности этого не подтверждают. Начните с одного проблемного адреса: сравните ответ сервера, DOM после выполнения JavaScript и результат проверки URL в Search Console. Затем распространите проверку на остальные шаблоны сайта.

1. Разделите загрузку, рендеринг и индексацию

Google способен выполнять JavaScript. В документации по JavaScript SEO обход, рендеринг и индексация описаны как отдельные этапы. Полученная страница может ожидать рендеринга; фиксированного срока, после которого любая SPA обязательно появится в поиске, нет. Поэтому утверждение «сайт отвечает, значит Google уже видит каталог» пропускает несколько проверок.

У диагностики должны быть разные результаты: документ получен, необходимое содержимое сформировано, индексирование разрешено, URL действительно проиндексирован. Первые три помогают устранить технические препятствия, но не гарантируют четвёртый. Пустой контейнер приложения в исходном HTML показывает зависимость от клиентского рендеринга, а не автоматически запрещённую для поиска архитектуру.

Сформулируйте наблюдение предметно: «В проверке карточки отсутствует описание товара», «После прямого открытия показывается главная», «В HTML Google canonical ведёт на другую категорию». Такая запись даёт разработчику воспроизводимую задачу. Фраза «Google не видит контент JavaScript» без URL, времени проверки и ожидаемого фрагмента слишком широка для исправления.

2. Подберите страницы с разными условиями загрузки

Проверка только главной не показывает, работает ли индексация SPA на вложенных маршрутах. Для учебного магазина на https://example.com возьмём шесть адресов. Первые пять в этом примере предназначены для поиска; последний заведомо не существует. Это тестовый набор, а не требование индексировать каждый фильтр реального магазина.

Тип страницыУчебный путьЧто должно получиться
Категория/catalog/chairsНазвание категории, описание, ссылки на товары
Товар/products/chair-42Нужная модель, характеристики, её собственные метаданные
Статья/guides/choose-chairПолный основной текст и тематические ссылки
Пагинация/catalog/chairs?page=2Именно вторая часть списка при прямом открытии
Посадочная фильтра/catalog/chairs/woodenСогласованная выборка и самостоятельное описание
Несуществующий товар/products/missing-999HTTP 404 и понятное сообщение посетителю

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

Добавьте дату выпуска, версию сборки и ответственного за шаблон. Владельцу сайта достаточно согласовать, что страница должна показывать покупателю. Разработчик фиксирует, откуда приходят эти сведения: из HTML, публичного API или предварительно сформированного файла. Этот небольшой реестр помогает сравнивать одинаковые условия до и после изменения.

3. Проверьте прямой вход и настоящий HTTP-статус

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

В Network выберите запрос основного документа и посмотрите статус, конечный адрес после перенаправлений и тело ответа. Не путайте его с запросом API. Ошибка 404 у API товара не превращает уже полученный документ 200 в HTTP 404. JavaScript способен поменять экран, но не исправить задним числом статус полученного ответа.

По правилам обработки HTTP-статусов Google, успешный код сам по себе не гарантирует индексирования, а ответ с сообщением об ошибке может оказаться soft 404. Для несуществующего маршрута настройте реальный 404 на сервере или пограничном слое; для намеренно окончательно удалённого ресурса уместен 410. Универсальная выдача оболочки приложения с кодом 200 маскирует различия между страницами.

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

4. Сравните исходный HTML с итоговым DOM

В ответе основного документа на вкладке Response найдите характерную фразу, которую заранее записали для страницы. Это исходный HTML конкретного запроса. Затем найдите её в Elements после загрузки приложения: здесь представлен текущий DOM, который JavaScript мог изменить. Сохраните оба результата, включая адрес и время.

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

Смотрите, где именно найдена фраза. Строка внутри JSON с начальными данными или встроенного сценария ещё не доказывает, что описание стало содержимым страницы. Нужный текст должен оказаться в соответствующих элементах, а ссылка — получить действительный адрес. Поиск одного слова во всём ответе легко даёт ложное подтверждение.

Отключение JavaScript помогает увидеть зависимость от него, но не воспроизводит работу Google. Аналогично запрос curl с заголовком User-Agent Googlebot получает HTTP-ответ и сам по себе не выполняет сценарии. Ни один из этих опытов не заменяет проверку результата рендеринга поисковым инструментом.

Не сравнивайте разные состояния случайно. Если сначала открыть карточку напрямую, затем выбрать другой товар без перезагрузки, ответ исходного документа останется прежним, а DOM уже изменится. Для базового сравнения заново загрузите нужный URL и не переходите с него. В протоколе разделяйте первоначальный вход и последующую клиентскую навигацию. Иначе исправный механизм переходов можно принять за несоответствие серверного ответа.

5. Посмотрите HTML в проверке URL Search Console

Откройте точный адрес в подтверждённом ресурсе Search Console. Сначала изучите сведения об индексированной версии и дату обхода. Затем запустите проверку опубликованной страницы. В разделе просмотра проверенной страницы изучите HTML, загруженные ресурсы и сообщения JavaScript; найдите основной текст, ссылки, title, canonical и robots. Скриншот полезен как дополнение, но не заменяет эти проверки.

Справка URL Inspection разделяет сведения из индекса и live-проверку. Успешный live-результат не означает, что URL уже проиндексирован. Он также не предсказывает выбранный Google canonical: этот показатель проверяют в данных индексированной версии. Нельзя принимать зелёный статус за подтверждение всех условий появления в поиске.

Сопоставляйте конкретные результаты: описание модели найдено или отсутствует, ссылка ведёт на нужный товар или главную, canonical совпадает с заданным или отличается. Если HTML недоступен в отчёте, отметьте проверку как незавершённую. Не подменяйте отсутствующее свидетельство предположением по скриншоту.

Сохраните небольшой протокол с версией выпуска и найденным расхождением. После исправления повторите тот же опыт. Старый отчёт об индексе и новый live-тест могут относиться к разным версиям сайта; расхождение между ними сначала нужно объяснить временем наблюдения.

6. Найдите ресурс, без которого пропадает содержимое

Проверьте JavaScript-файл маршрута и запрос, который приносит описание товара. Файл должен действительно содержать JavaScript, а API — данные нужного объекта. Код 200 с HTML страницы входа вместо JSON не подтверждает успешную загрузку. Сопоставьте ошибку консоли с отсутствующим блоком: сбой необязательной аналитики может не иметь отношения к пустому каталогу.

В инструкции Google по поисковым ошибкам JavaScript указано, что состояние cookies и хранилищ не сохраняется между загрузками WRS. Основное публичное содержимое не должно требовать предварительного визита, авторизации или разрешения пользователя. Это не повод раскрывать приватный API: для публичной страницы организуют отдельную безопасную выдачу разрешённых данных.

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

В учебном случае HTML новой сборки ссылается на файл, который при публикации ещё не появился на CDN. Браузер разработчика показывает старую сохранённую страницу, а свежая загрузка остаётся пустой. Исправление касается согласованной публикации HTML и ресурсов; очистка собственного браузера лишь помогает обнаружить зависимость.

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

7. Проверьте настоящие ссылки между маршрутами

Кнопка с обработчиком перехода может работать для посетителя, но не давать поисковику обычной ссылки. Google рекомендует элементы a с атрибутом href, содержащим доступный веб-адрес. Такие ссылки допустимо создавать JavaScript, если итоговая разметка сохраняет эту структуру.

Учебный пример ссылки на товар:

<a href="https://example.com/products/chair-42">Стул «Модель 42»</a>

Проверяйте итоговый DOM, а не название компонента в исходном коде проекта. Компонент RouterLink может сформировать правильный anchor, а внешне похожий элемент — остаться span с обработчиком. Попробуйте скопировать адрес ссылки и открыть его отдельно. Этот простой опыт одновременно обнаруживает зависимость от внутреннего состояния приложения.

Для самостоятельных индексируемых страниц используйте реальные маршруты вместо представлений вида https://example.com/#/products/chair-42. Клиентская навигация через History API должна сочетаться с прямой загрузкой этих адресов сервером. Навигационные ссылки категорий, пагинации и связанных товаров проверяйте так же, как основной контент.

8. Согласуйте метаданные и исключите исходный noindex

У карточки товара должны оставаться её title, описание и выбранная каноническая ссылка после прямой загрузки, обновления и перехода из каталога. Типовая ошибка SPA: название товара меняется на экране, а метаданные остаются от предыдущего маршрута. Проверьте также возврат назад, чтобы обнаружить неправильное восстановление состояния.

В рекомендациях по canonical Google предпочитает согласованный адрес в исходном HTML, который JavaScript не меняет на другой. Если корректный canonical нельзя сформировать заранее, его можно оставить отсутствующим в исходнике и добавить клиентским кодом. Не выдавайте сначала главную канонической для всех товаров, рассчитывая позже заменить значение. Избегайте конфликтующих canonical; сама аннотация остаётся сигналом, а не приказом Google.

Особенно опасен исходный noindex с расчётом удалить его после успешного API-запроса. Как поясняет документация JavaScript SEO выше, Google может пропустить рендеринг, встретив этот запрет. Тогда сценарий удаления не выполнит свою задачу. Для предназначенной к индексированию страницы устраните ошибочный запрет в начальном ответе, включая соответствующий HTTP-заголовок.

Не переносите это правило на личный кабинет или закрытые материалы. Сначала владелец определяет назначение страницы, затем команда проверяет согласованность ответа и клиентского состояния.

9. Убедитесь, что содержимое не требует действий посетителя

В документации Google о lazy loading указано: поиск не взаимодействует со страницей как пользователь. Нельзя рассчитывать, что он нажмёт «Показать описание» или прокрутит каталог ради загрузки важных данных. Отложенная загрузка сама по себе допустима, но её результат нужно проверять в отрисованном HTML.

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

Для бесконечного списка предусмотрите отдельные постоянные адреса частей и последовательные ссылки. Прямое открытие https://example.com/catalog/chairs?page=2 должно выдавать вторую часть без предварительной прокрутки первой. Приёмка проверяет содержимое каждого такого адреса; наличие общей кнопки «Ещё» не подтверждает обнаруживаемость остальных товаров.

10. Выберите SSR, CSR или предварительный рендеринг по причине сбоя

Вопрос «SSR или CSR для SEO» полезнее решать после диагностики. Разбор способов рендеринга на web.dev различает формирование HTML сервером, построение DOM в браузере и предварительное получение HTML при сборке. Каждый вариант переносит работу и ответственность за актуальность данных в другое место.

ПодходЧто проверить перед выбором
CSRСтабильно ли формируются текст, ссылки и метаданные после загрузки необходимых ресурсов
SSRДоступны ли данные серверу, выдерживает ли он нагрузку, согласованы ли кеш и клиентское продолжение
Предварительный рендерингИзвестны ли публикуемые URL и когда обновится HTML после изменения содержимого

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

Переход на SSR не исправляет неверный canonical или отсутствие ссылок автоматически. Сохранение CSR тоже не означает невозможности SEO. Выбирайте изменение, которое устраняет подтверждённую причину, и сохраняйте одинаковое основное содержание для обычных посетителей и поискового рендеринга.

11. Проверьте, что гидратация сохраняет результат

При SSR полезно наблюдать страницу дважды: сразу по ответу сервера и после запуска клиентского приложения. В учебном дефекте сервер отдаёт карточку «Модель 42», но клиент начинает с пустого состояния и заменяет её экраном загрузки, который остаётся навсегда. Наличие описания в исходнике ещё не закрывает такую неисправность.

Документация React hydrateRoot требует согласованности серверного и клиентского содержимого. Отдельно описан случай раннего вызова root.render: до завершения гидратации он очищает серверный HTML и переводит корень на клиентский рендеринг. Это конкретный пример того, почему проверка должна охватывать весь запуск, а не только первый ответ.

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

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

12. Зафиксируйте измеримую приёмку исправления

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

  • У всех шести URL подтверждён предусмотренный статус: пять существующих страниц отвечают 200, несуществующий товар — 404.
  • На пяти публичных страницах после прямого входа и обновления найдены заранее выбранные текстовые фрагменты и обязательные ссылки.
  • На этих же страницах согласованы метаданные, отсутствуют ошибочный исходный noindex и конфликтующие canonical.
  • После клиентского перехода и завершения запуска содержимое соответствует выбранному маршруту.
  • В доступных live-проверках Google подтверждены текст, ссылки и метаданные; недоступные результаты отмечены как непроверенные.

Разделите ответственность: разработчик исправляет доставку и рендеринг, владелец подтверждает правильность содержания, специалист по поиску позже сверяет индексированную версию и выбранный canonical. Результат приёмки — устранённое наблюдаемое препятствие. Появление страницы в индексе проверяется отдельно, без обещаний конкретной даты.

Карточка исправления может быть короткой: точный URL, версия сборки, ожидаемый фрагмент, место его исчезновения, причина и результат повторной проверки. Приложите только нужные выдержки HTML и сведения о проблемном ресурсе. Например, в учебном дефекте карточки описание отсутствовало после ошибки загрузки файла маршрута; после согласованной публикации ресурсов оно найдено в DOM браузера и HTML live-проверки. Такой результат подтверждает именно устранённую неисправность, а последующее индексирование остаётся отдельным наблюдением.

Подключите SiteGuard для внешнего контроля HTTP-доступности важных страниц. Рендеринг SPA и наличие содержимого у Google проверяйте отдельно описанным способом.