Что видит поиск без JS, и как один фальшивый lastmod выключил переобход карты
Поисковый робот и AI-краулер видят страницу не так, как вы в браузере. Проверять это надо не на глаз, а curl-ом — и тогда выясняются неприятные вещи: например, что карта сайта неделю никому не интересна, потому что вы сами её обесценили.
Исходная позиция
руИНН — около 2950 страниц: карточки компаний, каталог, справочные материалы. Домену четыре недели. Задача понятная: попасть в индекс Яндекса и Google, а заодно быть цитируемым в ответах AI-ассистентов — для сервиса проверки контрагентов это второй канал после поиска.
Первое, что нужно понять про робота: JavaScript он выполняет неохотно и не всегда. Googlebot умеет рендерить, но ставит такие страницы в отдельную очередь и приходит к ним позже. YandexBot с JS работает заметно хуже. AI-краулеры в массе своей не выполняют его вообще — берут HTML как есть. Если контент появляется только после fetch, для половины потребителей страница пуста.
Что отдаётся в HTML
Карточка компании рендерится на сервере целиком, и в исходном HTML лежит:
- Мета-теги под конкретную компанию — title, description, canonical, Open Graph. Дженерик-теги из шаблона перед этим удаляются, чтобы не было двух description на странице.
<noscript>с семью секциями: реквизиты, адрес, руководитель, учредители, ОКВЭД, контакты, финансы. С microdata-разметкой и таблицей отчётности по годам. Это то, что видит робот без JS.- Schema.org в
<head>, только там и без дублей:OrganizationилиPersonдля ИП,WebPageсdateModified,BreadcrumbList,FAQPage,Dataset. - Перелинковка обычными ссылками — «компании в городе N», «похожие по виду деятельности», учредители-юрлица. До этого карточка была листом: ни одной ссылки на другую компанию, и единственным путём робота к ней была пагинация каталога.
Отдельная история — данные для браузера. Раньше сервер отдавал HTML, а клиент тут же запрашивал ровно те же данные вторым запросом: посетитель смотрел на спиннер, хотя всё уже приехало. Теперь данные едут вместе со страницей в теге
<script type="application/json" id="preload">. Именно JSON-тегом, а не window.DATA = {...}: такой тег браузер не исполняет, это просто текст. Побочный, но важный эффект — на странице не осталось ни одного инлайнового скрипта, и из CSP удалось убрать unsafe-inline. На проде замер: страница Сбербанка 348 КБ, по сети 47 КБ в gzip — те же байты, что раньше, но на один сетевой круг меньше.
Файлы для AI
Кроме robots.txt и sitemap.xml сайт отдаёт два файла по спецификации llmstxt.org:
/llms.txt— краткий индекс для языковых моделей: что за сервис, как устроены адреса карточек, шесть примеров, разделы с описанием данных./llms-full.txt— все компании базы одним машиночитаемым списком: ИНН, тип, статус, город, вид деятельности.
Стоит это дёшево (оба собираются из того же кэша каталога, что и sitemap), а смысл в том, что модель, пришедшая за фактами, получает их в готовом виде, а не пытается разобрать вёрстку. В robots.txt при этом явно прописаны YandexBot и Mail.RU: в рунете основной AI-канал идёт через Яндекс.
Ещё один сигнал, который легко упустить, — возраст данных. На карточке стоит видимая строка «Данные ЕГРЮЛ ФНС на DD.MM.YYYY» и dateModified в разметке, обе — из времени изменения файла кэша. Без явного возраста краулер считает источник заброшенным.
И тут — фальшивый lastmod
29 июля плановая проверка индексации показала странное. В поиске Яндекса восемь страниц из 2956, это ожидаемо для молодого домена. А вот в разделе про карту сайта в Вебмастере:
last_access: 22 июля, urls_count: 80.
То есть робот не перечитывал карту неделю и считал, что в ней 80 адресов вместо 2956. Полез в код и нашёл:
const today = new Date().toISOString().split('T')[0];
// ...
xml += `<url><loc>${host}/company/${slug}</loc><lastmod>${today}</lastmod>…`;Во все <lastmod> подставлялась текущая дата. Карта каждый день заявляла, что изменились разом все 2955 страниц.
Для поисковика это не мелочь. lastmod — сигнал доверия: по нему решают, какие страницы перечитывать в первую очередь. Карта, которая ежедневно объявляет весь сайт обновлённым, не несёт информации, и обе крупные системы в таком случае поступают одинаково — перестают учитывать lastmod вообще. Не по отдельной странице, а по всему хосту.
Починка оказалась дешёвой, потому что настоящая дата уже была под рукой: карточки берут время изменения файла кэша (оно и так лежит в записи каталога, лишних чтений диска нет), справочные страницы — время изменения своего исходника, главная и каталог — самую свежую дату по базе. После деплоя карта выглядит так, как и должна: 2942 URL с датами 22–23 июля, когда наполнялась база, шесть страниц от 28-го, несколько от 29-го.
Заодно ушёл рассинхрон: раньше карта говорила «страница изменилась сегодня», а сама страница в dateModified — «22 июля». Два сигнала свежести противоречили друг другу, и верить в такой ситуации роботу было нечему.
Чем это проверять
Кабинеты вебмастеров показывают состояние, но не отвечают на вопрос «что именно видит робот». Практический набор:
curlбез JS — самое честное. Что пришло в HTML, то и увидит краулер.curl -s https://site/page | grep -c 'нужный текст'.- API Вебмастера Яндекса вместо кликов по интерфейсу: страниц в поиске, история обхода, журнал событий (появилась в поиске / исключена), состояние карты сайта, расход квоты переобхода. Всё это снимается скриптом и кладётся в мониторинг — тогда видно динамику, а не одно число на момент, когда вы решили посмотреть.
- Запрос
site:— не метрика. Google сам пишет, что число приблизительное. Считать по нему индексацию нельзя. - Логи обхода. Всплеск 5xx в окне деплоя видно только там — у нас, например, 26 ответов 5xx за минуту рестарта попали ровно в момент, когда робот шёл на 517 страниц в день.
Что забирать с собой
- Проверяйте страницу без JS, а не глазами в браузере. Половина потребителей контента — роботы, и у них другой рендер.
- Не подделывайте
lastmod. Дата «сегодня» у всех URL — не оптимизация, а способ выключить собственный сигнал. Берите время изменения источника; если его негде взять, лучше не ставить тег вовсе. - Сигналы свежести должны совпадать между собой — карта, разметка страницы и видимый текст. Расхождение хуже отсутствия.
- AI-краулеры — отдельная аудитория. Им нужны факты в машиночитаемом виде и явные даты, а не красивая вёрстка.