На небольшом сайте Sitemap выглядит просто.
Есть десять страниц:
/
/services
/prices
/about
/contacts
/expert/article-1
/expert/article-2
...Разработчик один раз создаёт:
/sitemap.xmlи практически забывает о нём.
На динамическом сайте эта модель перестаёт работать.
Сегодня в редакционной системе:
35 статей.Через полгода:
300.Появляются:
новые материалы;
рубрики;
кейсы;
страницы услуг;
архивы;
пагинация;
старые slug;
фильтры;
запланированные публикации;
удалённые страницы.Часть URL должна индексироваться.
Часть существует только технически.
Часть перенаправляет на новый адрес.
Часть доступна пользователю, но имеет:
<meta name="robots" content="noindex">Часть вообще находится за авторизацией.
Если просто выгрузить в Sitemap все маршруты приложения или все записи базы данных, получится файл, который начинает противоречить самому сайту.
Например:
sitemap.xml:
https://example.ru/expert/old-article
HTTP:
410 Goneили:
sitemap.xml:
https://example.ru/search?q=crm
meta robots:
noindexили:
sitemap.xml:
https://example.ru/expert/article?utm_source=telegram
canonical:
https://example.ru/expert/articleВо всех трёх случаях Sitemap сообщает поисковой системе:
Этот URL важен и его стоит рассматривать для поиска.
А сам сайт одновременно говорит:
Нет, не стоит.
Поэтому правильный Sitemap динамического проекта начинается не с XML.
Он начинается с определения:
какие URL мы действительно хотим видеть в поисковом индексе?
Что вообще делает Sitemap
Sitemap — это файл, который сообщает поисковой системе о значимых URL сайта и помогает их обнаруживать.
Например:
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
>
<url>
<loc>
https://example.ru/expert/api-versioning
</loc>
<lastmod>
2026-10-07
</lastmod>
</url>
</urlset>Но Sitemap не является командой:
Добавить страницу в индекс.
Google прямо рекомендует включать в Sitemap URL, которые вы хотите видеть в результатах поиска, и в случае дублирующихся адресов указывать прежде всего канонические варианты. При этом наличие URL в Sitemap остаётся сигналом для crawling, а не гарантией индексирования.
Яндекс описывает Sitemap похожим образом: файл сообщает поисковику о текущей структуре сайта, но наличие URL в нём не гарантирует появление страницы в поисковой выдаче.
То есть правильная модель:
Sitemap
↓
поисковик узнаёт URL
↓
crawler может его посетить
↓
анализирует HTTP,
robots, canonical,
контент
↓
принимает решение
об индексированииНе:
URL в Sitemap
=
URL в поискеSitemap — это не список всех URL сайта
Это одна из самых важных мыслей.
Представим приложение имеет:
/public
/admin
/account
/api
/search
/expert
/servicesТехнически все они являются URL.
Но Sitemap не должен превращаться в:
полный дамп routing table.Например:
/adminвообще не предназначен поисковому роботу.
/account/projectsявляется личным кабинетом.
/api/projectsявляется API.
/search?q=crmможет быть внутренней поисковой страницей.
А:
/expert/postgresql-queue— полноценной публичной статьёй.
Следовательно, Sitemap должен описывать поисковую поверхность продукта, а не техническую поверхность приложения.
Удобнее считать Sitemap представлением данных
В динамическом продукте можно мыслить так:
Database
↓
Publication state
↓
SEO policy
↓
Canonical URL
↓
Sitemap projectionТо есть Sitemap — это почти обычный database view.
Например в базе есть:
article_id
slug
status
published_at
updated_at
seo_indexable
deleted_atВ Sitemap попадают только записи, соответствующие определённым условиям.
Условно:
status = PUBLISHED
AND seo_indexable = true
AND deleted_at IS NULL
AND public_url existsНо этого ещё недостаточно.
Финальный URL должен соответствовать реальному HTTP и canonical policy.
Какая страница должна попадать в Sitemap
Для обычной публичной SEO-страницы хорошая картина выглядит так:
URL:
https://example.ru/expert/article
HTTP:
200 OK
robots:
crawl allowed
meta robots:
index allowed
canonical:
https://example.ru/expert/article
Sitemap:
https://example.ru/expert/articleВсе сигналы показывают на один документ.
Именно такие страницы являются хорошими кандидатами
Например:
главная;
страницы услуг;
цены;
публичные кейсы;
экспертные статьи;
публичные категории;
важные информационные страницы.При условии, что бизнес действительно хочет получать на них поисковый трафик.
Главный принцип
В Sitemap стоит добавлять канонический URL страницы, которую мы действительно хотим видеть в поиске.
Google прямо рекомендует помещать в Sitemap полные абсолютные URL и при наличии нескольких адресов одного содержимого включать предпочтительный canonical.
Яндекс перед созданием Sitemap также рекомендует сначала определить канонические URL страниц.
Значит tracking URL не нужен
Есть:
https://example.ru/expert/articleи:
https://example.ru/expert/article
?utm_source=telegramа также:
https://example.ru/expert/article
?utm_source=yandexЕсли это один материал, Sitemap должен содержать:
https://example.ru/expert/articleНе три адреса.
То же относится к ref, gclid, yclid и другим служебным параметрам
Если параметр не меняет самостоятельный поисковый документ:
не включаем его вариант
как отдельный URL.Иначе один материал может породить:
/article
/article?utm_source=yandex
/article?utm_source=telegram
/article?ref=partnerчетыре строки в Sitemap.
Хотя поисковая сущность всего одна.
Sitemap должен совпадать с canonical
Представим Sitemap содержит:
/article?ref=partnerНо страница говорит:
<link
rel="canonical"
href="https://example.ru/article"
>Сайт одновременно сообщает:
Sitemap:
важен /article?ref=partnerи:
Canonical:
основной /articleЛучше не создавать такой конфликт.
Поэтому можно сформулировать invariant
Для обычной индексируемой страницы:
sitemap URL
=
canonical URL
=
финальный URL после redirect
=
URL внутренних ссылокЧем чаще выполняется это правило, тем проще поисковой системе понимать структуру сайта.
Что точно не стоит добавлять
Первая большая категория — страницы:
noindex.Если документ возвращает:
<meta
name="robots"
content="noindex"
>или:
X-Robots-Tag: noindexнет смысла одновременно помещать его в список URL, которые мы хотим видеть в поиске.
Google прямо рекомендует не включать в Sitemap адреса, которые владелец сайта не хочет видеть в результатах поиска.
Например
/thank-youнужна пользователю после формы.
Но поисковая landing page из неё не требуется.
Если policy:
noindexто в Sitemap:
не включаем.Не включаем личные кабинеты
Например:
/account
/account/projects
/account/filesВо-первых, такие страницы обычно защищены авторизацией.
Во-вторых, поисковому роботу они не представляют публичной информационной ценности.
Sitemap не должен быть списком интерфейсов приложения.
Не включаем admin
/admin
/admin/articles
/admin/projectsне имеют отношения к органическому поиску.
Не включаем API endpoints
/api/projects
/api/articles
/api/healthSitemap описывает индексируемые ресурсы сайта, а не весь HTTP API.
Не включаем 404
Страница:
/expert/nonexistentвозвращает:
404 Not Found.Её не должно быть в Sitemap.
Не включаем 410
Если статья удалена окончательно:
/expert/old
→ 410 Goneона должна исчезнуть и из Sitemap.
Не включаем URL с permanent redirect
Например:
/expert/old-api
→ 301
/expert/api-versioningВ Sitemap должен находиться:
/expert/api-versioningа не старый адрес.
Это особенно важно после изменения slug
Было:
/expert/webhook-oldСтало:
/expert/webhook-signature-replayПравильная модель:
old URL
→ 301 new URL
new URL
→ 200
Sitemap
→ new URL onlyНе нужно хранить старый URL в Sitemap «ради SEO-веса»
Для этого существует redirect.
Sitemap описывает актуальную структуру сайта, а не историю его маршрутов.
Черновики тоже не нужны
В CMS есть:
DRAFT
SCHEDULED
PUBLISHED
ARCHIVED
DELETEDЧерновик:
DRAFTне должен попадать в Sitemap только потому, что запись уже существует в базе.
То же относится к отложенной публикации
Статья запланирована:
publish_at =
2026-10-10 10:00Сегодня:
2026-10-07.Она ещё не является публичной страницей.
Следовательно:
Sitemap:
нет.После фактической публикации:
Sitemap:
да.Иначе поисковик узнаёт URL раньше пользователя
Это может создать:
404;
preview;
пустую страницу;
неожиданный noindex.Никакой пользы здесь нет.
Динамический Sitemap должен учитывать lifecycle контента
Например:
DRAFT
↓
SCHEDULED
↓
PUBLISHED
↓
ARCHIVED
↓
DELETEDДля каждого состояния нужна понятная SEO-policy.
DRAFT
→ нет public URL
→ нет SitemapSCHEDULED
→ нет SitemapPUBLISHED + INDEXABLE
→ SitemapPUBLISHED + NOINDEX
→ нет SitemapDELETED
→ нет Sitemap
→ 404/410Так Sitemap автоматически следует жизненному циклу продукта.
А что делать с архивными статьями
Слово:
ARCHIVEDсамо по себе не должно автоматически означать:
noindex.Например старая техническая статья может по-прежнему быть полезной пользователям.
Если она:
доступна;
актуальна;
имеет самостоятельный URL;
должна участвовать в поиске,она может остаться в Sitemap.
Архивный статус бизнеса и индексная политика — разные вещи.
Это хороший пример того, почему SEO-policy лучше хранить отдельно
Например:
content_status = ARCHIVED
seo_indexable = trueили:
content_status = ARCHIVED
seo_indexable = falseРешение становится явным.
Как быть с пагинацией
Например:
/expert
/expert?page=2
/expert?page=3Здесь нет универсального правила:
Всегда добавлять.
или:
Никогда не добавлять.
Нужно сначала решить индексную архитектуру пагинации.
Если страницы пагинации самостоятельны и indexable
Например:
/expert?page=2возвращает:
200;
crawl allowed;
index allowed;
self-canonical.Тогда она может быть включена в Sitemap.
Если pagination pages имеют noindex
Тогда:
в Sitemap их быть не должно.Главное — не создавать противоречие
Плохо:
sitemap:
?page=2и:
?page=2:
noindex.И не нужно автоматически склеивать всю пагинацию canonical на первую страницу
Если page 2 содержит другой набор статей, это не точная копия page 1.
Политика пагинации должна быть спроектирована отдельно.
Sitemap просто следует ей.
Что делать с фильтрами
Представим каталог:
/catalogимеет:
?brand=apple
?color=black
?sort=price
?ram=16Если автоматически добавить все комбинации, Sitemap быстро превратится в:
десятки тысяч технических URL.Но некоторые фильтры могут быть полезными SEO-страницами
Например:
/catalog/laptops/appleили даже осознанно нормализованный:
/catalog?brand=appleимеет:
отдельный поисковый спрос;
уникальный H1;
отдельный текст;
самостоятельный набор товаров;
self-canonical.Если бизнес действительно считает страницу поисковой landing page, её можно включить.
А сортировка — обычно другое
/catalog?sort=priceпоказывает те же товары в другом порядке.
Это гораздо больше похоже на техническое представление одной категории.
Обычно такой URL не нужен в Sitemap.
Значит правило снова одно
Не:
В Sitemap добавляем все URL без ?.И не:
Все URL с ? исключаем.А:
в Sitemap добавляем самостоятельные канонические документы, предназначенные для поиска.
Внутренний поиск обычно исключаем
Например:
/search?q=postgresqlпользователю полезен.
Но бесконечное число поисковых запросов может создавать практически бесконечное пространство URL.
Если такие страницы не являются частью SEO-стратегии:
не добавляем их в Sitemap.Что делать с категориями
Например:
/expert/api-integrationsявляется полноценной страницей рубрики.
Если она имеет:
H1;
описание;
ссылки на материалы;
self-canonical;
indexable policy,её вполне можно включить в Sitemap.
Но пустая рубрика — вопрос
Представим категория создана:
/background-jobsно материалов:
0.Страница показывает:
Пока нет публикаций.
Нужно ли её индексировать?
Это уже продуктовое решение.
Очень часто правильнее:
не публиковать пустую SEO-страницудо появления содержимого.
Sitemap не должен искусственно создавать поисковую поверхность раньше контента.
То же относится к автоматически созданным тегам
CMS может создать:
/tag/api
/tag/backend
/tag/http
/tag/json
/tag/developmentпосле первой статьи.
Это не означает, что каждый tag page автоматически заслуживает:
index + sitemap.Иначе десятки статей быстро порождают сотни слабых архивных страниц.
Sitemap не должен становиться отражением database cardinality
Наличие сущности:
Tagв базе не означает:
TagPageв поиске.
Какие поля нужны XML Sitemap
Минимальный элемент:
<url>
<loc>
https://example.ru/expert/article
</loc>
</url>loc является основой.
Самое полезное дополнительное поле — lastmod
Например:
<url>
<loc>
https://example.ru/expert/article
</loc>
<lastmod>
2026-10-07
</lastmod>
</url>Но только если дата правдивая.
lastmod — не дата генерации Sitemap
Это одна из самых частых ошибок.
Плохой generator:
lastmod = new Date();Для каждой страницы при каждом построении файла.
Сегодня:
100 статей
→ lastmod = сегодня.Завтра:
те же 100 статей
→ lastmod = завтра.Хотя ни одна статья не изменилась.
Что мы в таком случае говорим crawler
Все сто документов изменяются каждый день.
Но это неправда.
Google прямо подчёркивает, что lastmod полезен только тогда, когда соответствует реальности; если сайт постоянно указывает ложные даты обновления, поисковая система со временем может перестать доверять такому сигналу. Google рекомендует менять lastmod при существенных изменениях основного контента, структурированных данных или значимых ссылок, но не из-за, например, ежегодного изменения copyright в footer.
Поэтому lastmod должен идти из данных страницы
Например статья имеет:
published_at
content_updated_at
seo_updated_atМожно определить:
lastmod =
max(
content_updated_at,
seo_significant_updated_at
)Но не любое обновление записи является изменением страницы
Представим admin открыл статью и система обновила:
last_viewed_by_adminили:
internal_note_updated_at.Публичный HTML не изменился.
Значит lastmod страницы меняться не должен.
Это ещё одна причина разделять внутренние timestamps
Плохо:
updated_atизменяется от любого SQL UPDATE.
А Sitemap воспринимает его как:
public page modified.Лучше иметь понятную семантику
Например:
content_updated_atили:
public_updated_at.Что считать значимым изменением статьи
Например:
изменён основной текст;
добавлен раздел;
исправлена важная техническая информация;
изменён H1;
обновлены структурированные данные;
значимо изменена перелинковка.А что обычно не требует нового lastmod
Например:
поменялся copyright;
обновился счётчик просмотров;
сменился CSRF token;
изменилась внутренняя аналитика;
перестроился случайный блок рекомендаций.Категории сложнее
Страница:
/expertсама по себе может не иметь поля:
updated_at.Но сегодня опубликована новая статья.
Содержимое /expert действительно изменилось.
Можно вычислять:
lastmod(category) =
max(
category_content_updated_at,
latest_visible_article_change
)если это действительно соответствует rendered page.
Но не обязательно изобретать дату, которой вы не доверяете
Google прямо указывает, что lastmod можно вообще не указывать на тех страницах, для которых система не умеет достоверно определить дату существенного изменения — например на некоторых агрегирующих страницах.
Лучше:
нет lastmodчем:
всегда сегодняшняя дата.А что с changefreq
Протокол Sitemap позволяет указывать:
<changefreq>
weekly
</changefreq>Но Google сейчас прямо указывает, что changefreq вообще не используется. То же относится к priority.
У Яндекса ситуация отличается
Актуальная документация Яндекса по XML Sitemap по-прежнему описывает:
lastmod;
changefreq;
priorityкак поддерживаемые элементы; для priority Яндекс описывает коэффициент относительной важности URL от 0.0 до 1.0.
Нужно ли поэтому строить сложную priority-систему
Для большинства обычных проектов я бы не делал из этого большую архитектуру.
Главное:
правильный loc;
правильный набор URL;
честный lastmod.Это намного важнее попытки вручную назначить:
0.9
0.8
0.73каждой статье.
Порядок URL в Sitemap тоже не является способом расставить приоритет Google
Google прямо указывает, что порядок URL внутри Sitemap для него значения не имеет.
То есть:
главную поставить первойможно для человеческого удобства.
Но это не делает её автоматически:
SEO priority №1.Когда обновлять Sitemap
Правильный ответ:
когда изменяется набор индексируемых URL или значимое состояние уже включённой страницы.
Опубликовали новую статью
Было:
/article-a
/article-bПоявилась:
/article-c.После публикации Sitemap должен начать содержать:
/article-c.Изменили существующую статью
URL остаётся тем же.
Но значимо изменён контент.
Обновляем:
lastmod.Изменили slug
Было:
/article-oldСтало:
/article-new.Sitemap:
remove /article-old
add /article-newСервер:
/article-old
→ 301 /article-new.Удалили статью
remove URL from Sitemapи сервер возвращает:
404/410либо:
301если существует настоящая замена.
Поставили noindex
Если было принято осознанное решение исключить страницу из поиска:
remove from Sitemap.Вернули страницу в index
Когда:
noindex
→ indexableи URL снова соответствует всей SEO-policy:
добавляем обратно.Опубликованный материал переведён в draft
Он перестаёт быть публичной SEO-страницей.
Следовательно:
удаляем из Sitemap.И отдельно корректно решаем HTTP lifecycle самого URL.
Нужно ли пересобирать весь XML после каждого изменения
На небольшом и среднем динамическом сайте это совершенно нормально.
Например:
500;
5000;
20 000URL можно получить из базы и быстро сформировать заново.
Но необязательно выполнять тяжёлый SQL на каждый crawler request:
GET /sitemap.xml
↓
читать всю БД
↓
рендерить 30 000 URLкаждый раз.
Лучше отделить обновление данных от отдачи файла
Например:
Publish article
↓
Invalidate sitemap cache
↓
Generate sitemap
↓
Store cached XML
↓
GET /sitemap.xml
↓
fast responseИли lazy cache
content changed
↓
sitemap_revision++При следующем request:
cache stale?
│
├── no → return
│
└── yes → regenerateДля Sitemap важна надёжность, а не realtime в миллисекундах
Если статья опубликована в:
12:00:00не обязательно, чтобы Sitemap изменился:
12:00:00.001.Но он должен обновляться предсказуемо и достаточно быстро.
Например:
сразу при публикации;или:
фоновым job в течение нескольких минут.Не нужно генерировать новый lastmod просто потому, что XML пересобран
Это снова важное различие.
Sitemap file generated_atи:
page lastmod— разные timestamps.
Нужно ли каждый раз заново отправлять Sitemap в Google
Нет.
Если Sitemap находится по постоянному адресу:
https://example.ru/sitemap.xmlего не нужно после каждого изменения удалять и добавлять заново.
Google рекомендует предоставить Sitemap через Search Console и/или ссылку в robots.txt. Старый unauthenticated sitemap ping endpoint уже отключён; Google также отдельно советует не отправлять один и тот же неизменившийся Sitemap много раз в день.
Яндекс тоже регулярно проверяет уже добавленный файл
Яндекс Вебмастер прямо указывает: при обновлении добавленного Sitemap не нужно удалять его и загружать заново — робот периодически проверяет файл. При необходимости в Вебмастере можно вручную сообщить, что файл обновился.
Значит архитектура должна иметь стабильный URL Sitemap
Например:
/sitemap.xmlили для большого сайта:
/sitemap-index.xml.И указать его в robots.txt
Например:
Sitemap: https://example.ru/sitemap.xmlЯндекс официально поддерживает такую директиву; Google также принимает Sitemap через robots.txt.
Что делать, когда URL становится много
Один Sitemap ограничен.
И Google, и Яндекс указывают лимит:
50 000 URLна один файл и:
50 MBв несжатом виде. Если лимит превышен, Sitemap нужно разбивать и при необходимости объединять через Sitemap index.
Вместо:
/sitemap.xmlможно получить:
/sitemap-index.xmlкоторый содержит:
/sitemap-pages.xml
/sitemap-services.xml
/sitemap-expert-1.xml
/sitemap-expert-2.xml
/sitemap-portfolio.xmlSitemap index
Пример:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
>
<sitemap>
<loc>
https://example.ru/sitemap-pages.xml
</loc>
</sitemap>
<sitemap>
<loc>
https://example.ru/sitemap-expert.xml
</loc>
</sitemap>
</sitemapindex>Разделять стоит не только ради лимита
Даже сайт на:
5000 URLможет получить пользу от логического разделения.
Например:
sitemap-static.xml
sitemap-expert.xml
sitemap-services.xml
sitemap-portfolio.xmlТак проще диагностировать:
Почему статьи плохо индексируются?
Можно отдельно анализировать:
expert sitemap.Google прямо отмечает, что отдельные Sitemap могут быть полезны для отслеживания поисковой производительности разных групп URL в Search Console.
Это особенно полезно для редакционной системы
Например:
sitemap-expert.xmlстановится точным отражением:
всех опубликованных
indexable статей.А не смешивается с
услугами;
портфолио;
юридическими страницами;
каталогом.Как разделять большой Sitemap
Хороший вариант — по типу сущности.
Например:
articles;
services;
products;
categories.Другой вариант — по времени
Если:
миллионы публикаций,можно иметь:
articles-2025.xml
articles-2026-01.xml
articles-2026-02.xmlНо такая схема оправдана только при реальном масштабе.
Для нескольких сотен материалов она создаст лишнюю сложность.
Не проектируйте Sitemap как Kubernetes
Если на сайте:
60 страниц,одного:
sitemap.xmlобычно достаточно.
Архитектура Sitemap должна соответствовать размеру продукта.
Что должен возвращать сам Sitemap
У Яндекса требования прямо включают:
HTTP 200 OKдля URL Sitemap, UTF-8, максимум 50 000 ссылок и 50 MB без сжатия.
Не нужно перенаправлять /sitemap.xml без причины
Плохо:
/sitemap.xml
↓ 301
/new-sitemap.xmlесли можно сразу использовать стабильный конечный адрес.
Особенно неприятная ошибка
/sitemap.xml
→ 500после deployment.
Сайт для пользователей работает.
Но поисковый робот теряет источник структуры.
Поэтому Sitemap нужен в readiness/smoke checks
Например после deployment:
GET /sitemap.xmlожидаем:
200;
application/xml;
valid XML;
не пустой.Но синтаксически правильный XML ещё не означает правильный Sitemap
Можно получить идеально валидный:
<urlset>
...
</urlset>внутри которого:
200 URLи половина:
404.XML validator скажет:
PASS.SEO-система должна сказать:
FAIL.Поэтому нужна семантическая валидация
Для каждого URL можно проверять:
HTTP status;
canonical;
robots/indexability;
domain;Sitemap содержит:
https://example.ru/expert/articleProduction test делает request.
Ожидает:
HTTP 200и:
canonical =
https://example.ru/expert/article.Если получил 301
Ошибка Sitemap.
Он должен содержать уже target.
Если получил 404
Ошибка Sitemap.
Если получил noindex
Конфликт SEO-policy.
Если canonical другой
Тоже конфликт.
Например:
Sitemap:
/expert/article-a
Canonical:
/expert/article-bНужно понять:
Почему мы просим поисковик рассматривать A, одновременно утверждая, что основной документ B?
Можно сделать автоматический Sitemap audit
Условно:
for url in sitemap:
assert sameProductionHost(url)
assert httpStatus(url) == 200
assert robotsAllows(url)
assert pageIsIndexable(url)
assert canonical(url) == urlЭто уже мощный SEO regression test.
А затем проверить обратную сторону
Не только:
Все Sitemap URL корректны?
Но и:
Все опубликованные indexable страницы присутствуют в Sitemap?
Например база содержит
237 published + indexable articles.А Sitemap:
236.Одна статья потерялась.
Это может произойти из-за:
неправильного slug;
ошибки категории;
null published_at;
ошибки генератора;Поэтому полезен invariant:
INDEXABLE PUBLIC ENTITIES
=
SITEMAP ENTITIESс учётом типов страниц и осознанных исключений.
Sitemap должен строиться из того же source of truth, что и публичный сайт
Плохая архитектура:
Public site:
читает PostgreSQL
Sitemap:
читает старый JSON-файлЧерез месяц они неизбежно расходятся.
Лучше
PostgreSQL
│
├── public article renderer
│
└── sitemap generatorОдна публикационная модель.
Одна SEO-policy.
Например функция
getPublicIndexableArticles()может использоваться:
Экспертным центром;
Sitemap generator;
SEO audit.Не три разных определения:
Что считается опубликованной статьёй?
Но не нужно превращать Sitemap в способ навигации
Sitemap помогает поисковику обнаруживать URL.
Он не заменяет внутренние ссылки.
Статья не должна существовать только так:
есть в sitemap.xmlно:
ни одна HTML-страница
на неё не ссылается.У здорового сайта есть оба механизма
Internal links
+
SitemapЯндекс прямо отмечает, что робот узнаёт страницы через внутренние и внешние ссылки, а Sitemap особенно полезен для большого сайта, глубоко вложенных страниц или URL, которые иначе можно пропустить.
Google тоже рассматривает Sitemap как помощь обнаружению, а не замену crawlable ссылкам.
Поэтому новая статья после публикации должна появляться не только в XML
Но и:
/expert;
рубрике;
релевантной внутренней перелинковке.Sitemap не исправляет orphan pages автоматически
Он помогает поисковой системе узнать URL.
Но внутренняя архитектура сайта всё равно сообщает, насколько документ встроен в продукт.
Что делать с главной страницей
Конечно:
/может быть в Sitemap.
Но с lastmod нужно быть осторожнее.
Если главная автоматически показывает:
последние статьи;
последние кейсы;
счётчик проектов;она может меняться достаточно часто.
Не ставьте lastmod = now на каждый request
Можно:
lastmod =
дата последнего значимого изменения
главной страницыили, если точную семантику определить трудно:
lastmod вообще не указывать.Это лучше ложного сигнала.
То же для страниц категорий
lastmod можно вычислять на основе:
изменения самой категории;
новой публикации, реально отображаемой на этой странице.Но только если модель действительно соответствует контенту.
Нужно ли менять lastmod при исправлении одной опечатки
Зависит от существенности.
Не нужно превращать это в бухгалтерию каждого символа.
Google формулирует критерий как significant modification.
«PostgreSQLl»
→
«PostgreSQL»в одном месте статьи — вряд ли причина строить сложный специальный механизм.
А вот
переписано 30% статьи;
добавлен новый раздел;
исправлена устаревшая архитектура;
обновлена schema;явно является существенным изменением.
Не используйте publish date вместо lastmod навсегда
При первой публикации:
lastmod = published_atлогично.
Но после редактирования:
lastmodдолжен отражать новое существенное изменение.
И не подменяйте lastmod датой просмотра
Например:
page_viewed_atвообще не относится к изменению содержимого.
Что делать при массовом обновлении шаблона
Например обновили:
header;
footer;
цвет кнопок.Нужно ли менять lastmod у:
5000 статей?Обычно нет, если основное содержимое документов не изменилось значимо.
А если изменили structured data у всех статей
Например исправили:
Article JSON-LDна всех страницах.
Google прямо относит изменение structured data к примерам существенных изменений, для которых корректный lastmod может быть обновлён.
Тогда массовое изменение дат уже имеет основание.
Нужно ли включать изображения в обычный Sitemap
Можно расширять XML информацией об изображениях, видео и локализованных версиях.
Google поддерживает соответствующие extensions, а Яндекс также позволяет передавать через Sitemap дополнительную информацию для некоторых типов содержимого.
Но обычному корпоративному или экспертному сайту не нужно усложнять файл только потому, что возможность существует.
Начните с качественной карты страниц
loc
+
достоверный lastmodуже решают основную задачу.
Что делать с мультиязычным сайтом
Например:
/ru/article
/en/article
/de/articleЕсли каждая языковая страница:
публичная;
indexable;
self-canonical,каждая является самостоятельным URL и может присутствовать в Sitemap.
Для языковых связей уже используется:
hreflangв соответствующей реализации.
Не нужно помещать в Sitemap только русскую версию и надеяться, что остальные обязательно найдутся сами.
Но again: canonical policy должна быть правильной
Если:
/en/articleошибочно имеет:
canonical → /ru/article,Sitemap не должен маскировать архитектурную ошибку.
Сначала исправляется canonical.
Потом Sitemap.
Sitemap должен следовать SEO-истине сайта, а не создавать её
Это очень важная мысль.
Не нужно пытаться:
Если добавим URL в Sitemap, поисковик поймёт, что он главный.
Если сама страница говорит:
canonical → другой URL,сначала нужно исправить страницу.
Что делать при миграции домена
Было:
old.example.ruСтало:
example.ru.После полноценной миграции новый Sitemap должен содержать:
новые canonical URLsна новом host.
Не смесь:
old + new.То же при www → без www
Выбрано:
https://example.ruSitemap должен содержать именно этот host.
Не:
https://www.example.ruесли он уже:
301 → example.ru.Google требует абсолютные URL
Не:
<loc>
/expert/article
</loc>а:
<loc>
https://example.ru/expert/article
</loc>Это прямо указано в актуальных рекомендациях Google.
Production base URL должен быть конфигурацией
Например:
PUBLIC_BASE_URL=https://example.ruИ Sitemap generator использует его.
Но его обязательно нужно валидировать
Иначе deployment с:
PUBLIC_BASE_URL=http://localhost:4173может сгенерировать:
<loc>
http://localhost:4173/expert/article
</loc>Это идеальный случай для fail-fast
Production запускается только если:
scheme = https
host = expected production hostТо же для staging
Staging вообще не должен случайно использовать production Sitemap как собственный список индексируемых URL.
Лучше иметь отдельную environment policy.
Как может выглядеть sitemap generator
Не буквально, а концептуально:
getIndexablePages()
↓
normalizeCanonicalUrl()
↓
filter:
public
indexable
not deleted
not redirected
↓
calculateReliableLastmod()
↓
sort for deterministic output
↓
render XML
↓
validate
↓
cacheПочему deterministic output полезен
Если содержимое не изменилось, Sitemap должен оставаться практически тем же.
Не нужно при каждой генерации:
хаотично менять порядок;
переписывать даты;
создавать новый XML,
отличающийся целиком.Так легче:
тестировать;
diff'ить;
кэшировать;
расследовать.Хороший sitemap generator должен уметь сказать, почему URL попал в файл
Например для статьи:
URL:
https://example.ru/expert/webhook
Source:
article #1842
Status:
PUBLISHED
Indexability:
INDEX
Canonical:
SELF
Lastmod source:
content_updated_atЭто значительно облегчает диагностику.
И желательно уметь сказать, почему URL исключён
Например:
article #1944
excluded:
status = DRAFTили:
article #1960
excluded:
seo_indexable = falseили:
old slug
excluded:
301 redirectТогда Sitemap становится наблюдаемой системой
Не чёрным XML-файлом:
Почему этой статьи здесь нет?
Особенно полезно это в админ-панели
Возле статьи можно показывать:
Поиск:
INDEXABLE
Sitemap:
INCLUDED
Canonical:
SELF
Lastmod:
07.10.2026Или:
Поиск:
NOINDEX
Sitemap:
EXCLUDEDТеперь редактор понимает состояние публикации
Не только:
Опубликовано.Но и:
Опубликовано для пользователей
и доступно поисковым системам.Нужно ли вручную добавлять Sitemap после каждой статьи в Яндекс Вебмастер
Нет.
Если URL файла не изменился, Sitemap просто обновляется.
Яндекс периодически проверяет уже добавленный файл; удалять и загружать его заново после каждого изменения не требуется.
То же концептуально относится к Google
Стабильный Sitemap подаётся один раз через:
Search Console;
robots.txt.После этого поисковая система возвращается к нему.
И это ещё один аргумент за динамический постоянный endpoint
Например:
/sitemap.xmlа не:
/sitemap-2026-10-07-final-v2.xml.Когда IndexNow или переобход полезны
Механизмы ускоренного уведомления поисковых систем могут дополнять Sitemap.
Но они не заменяют его архитектурную функцию.
Sitemap отвечает:
Какие канонические публичные URL составляют сайт?
Уведомление об обновлении отвечает:
Вот конкретный URL, который недавно изменился.
Это разные задачи.
Даже если после публикации есть автоматическая отправка URL поисковой системе
Sitemap всё равно должен обновиться.
Иначе:
notification:
новая статья существуета:
Sitemap:
её нет.Сигналы снова расходятся.
Когда Sitemap становится плохим
Не только когда XML содержит syntax error.
Плохой Sitemap может быть технически абсолютно валидным.
Например:
20% → 301
10% → 404
15% → noindex
30% → canonical на другой URLXML validator:
PASS.SEO architecture:
FAIL.Поэтому качество Sitemap измеряется согласованностью
Например:
URLs total:
1000
200 OK:
1000
self-canonical:
1000
indexable:
1000
redirects:
0
404/410:
0Такой отчёт намного полезнее:
XML valid = yes.Можно даже считать sitemap health
Например:
Healthy URLs:
99.8%
Canonical conflicts:
2
HTTP errors:
0
Noindex conflicts:
0
Missing indexable pages:
3И делать release gate
Если:
canonical conflicts > 0или:
Sitemap URL → 404релиз не считается полностью успешным.
Особенно полезно тестировать изменения редакционной системы
Например новая версия CMS изменила:
правила slug.Вместо ожидаемых:
/expert/articlegenerator начал создавать:
/expert//article.Один автоматический Sitemap audit обнаружит дефект сразу на сотнях материалов.
Или изменился status mapping
Было:
PUBLISHED
→ Sitemap.После рефакторинга enum:
publishedбольше не совпадает со старой проверкой.
Sitemap внезапно:
0 URLs.Поэтому размер Sitemap тоже стоит мониторить
Например:
вчера:
237 expert URLs
сегодня:
12.Это почти наверняка не естественное изменение контента.
Или наоборот
вчера:
237
сегодня:
184 000.Возможно generator внезапно начал включать:
search;
filters;
parameters.Очень полезен release anomaly detection
Например:
URL count change > 20%
→ warningесли deployment не предполагал массовое изменение страниц.
Это особенно важно при SEO-генераторах
Система может случайно создать:
100 000 landing pagesза один deploy.
Sitemap станет первым местом, где масштаб проблемы хорошо виден.
Нельзя автоматически считать больше URL = лучше SEO
Например:
100 качественных страницне становятся слабее только потому, что Sitemap маленький.
И:
100 000 шаблонных страницне получают ценность от присутствия в XML.
Sitemap помогает поисковой системе обнаружить страницу
Но не создаёт причину её индексировать.
Эту причину создаёт сам документ.
Правильная архитектура динамического Sitemap
Если собрать всё вместе:
Database
│
▼
Content lifecycle
│
▼
SEO policy
│
┌──────────┴──────────┐
│ │
▼ ▼
Public renderer Sitemap generator
│ │
▼ ▼
HTTP / canonical canonical URLs
robots / content + honest lastmod
│ │
└──────────┬──────────┘
▼
Validation
│
▼
sitemap.xml
│
┌────────┴────────┐
▼ ▼
Google YandexОбе ветви должны исходить из одной истины.
Практический checklist динамического Sitemap
Перед production полезно проверять:
- в Sitemap находятся только публичные URL, предназначенные для поиска;
- каждый URL абсолютный и использует production HTTPS-host;
- каждый URL возвращает
200 OK; - Sitemap не содержит
301,302,404или410; - Sitemap не содержит
noindexстраниц; - каждый обычный индексируемый URL совпадает со своим canonical;
- tracking и служебные параметры не создают отдельные записи;
- старые slug удаляются из Sitemap после настройки redirect;
- draft и scheduled материалы появляются только после реальной публикации;
- удалённые материалы исчезают из Sitemap;
lastmodотражает существенное изменение страницы, а не время генерации XML;- Sitemap обновляется автоматически при изменении lifecycle контента;
- внутренний поиск, admin, API и личные кабинеты не попадают в публичный Sitemap;
- фильтры и pagination включаются только согласно явной SEO-policy;
- количество URL контролируется после deployment;
- XML валиден, доступен crawler и возвращает
200; - при превышении 50 000 URL или 50 MB используется несколько Sitemap и Sitemap index;
- опубликованные indexable страницы не теряются из Sitemap;
- Sitemap указан в robots.txt и подключён в инструментах поисковых систем.
Самый полезный вопрос при генерации каждой строки
Не:
Такой URL существует?
А:
Хотим ли мы, чтобы именно этот канонический URL рассматривался поисковой системой как самостоятельная публичная страница?
Если ответ:
да,он хороший кандидат.
Если ответ:
нет;
не знаю;
это технический URL;
это дубль;
это redirect;
это noindex,он, скорее всего, не должен находиться в Sitemap.
Второй вопрос
Если crawler прямо сейчас откроет URL из Sitemap, подтвердит ли сама страница обещание Sitemap?
То есть получит:
200;
indexable;
self-canonical;
полезный контент.Если нет — нужно исправлять конфликт.
Третий вопрос
Если статья изменится или исчезнет завтра, обновится ли Sitemap автоматически?
Если процесс:
редактор публикует статью
↓
потом разработчик вручную правит sitemap.xml,он рано или поздно сломается.
Для динамического продукта Sitemap тоже должен быть динамическим
Но не в смысле:
каждый request генерирует
случайно новый XML.А в смысле:
он автоматически отражает реальное актуальное состояние публикационной системы.
Вместо вывода
Sitemap.xml часто воспринимают как файл:
со всеми страницами сайта.
Для динамического веб-продукта это слишком грубое определение.
Правильнее:
Sitemap — это машинное представление той части публичного сайта, которую владелец считает канонической и предназначенной для поискового обнаружения.
Именно поэтому хороший Sitemap не содержит всё подряд.
Он содержит:
актуальные;
публичные;
индексируемые;
канонические
URL.И исключает:
draft;
scheduled до публикации;
noindex;
личные кабинеты;
admin;
API;
технический поиск;
tracking-дубли;
redirects;
404;
410;
устаревшие slug.При изменении содержимого Sitemap должен изменяться вместе с ним:
Publish
→ добавить URL
Significant update
→ обновить lastmod
Slug changed
→ удалить old,
добавить new,
old → 301
Noindex
→ убрать URL
Delete
→ убрать URL
и вернуть 404/410А lastmod должен отвечать не на вопрос:
Когда мы последний раз генерировали XML?
а:
Когда содержимое этой конкретной публичной страницы действительно существенно изменилось?
На больших сайтах Sitemap разбивается на несколько файлов и объединяется индексом; и Google, и Яндекс устанавливают лимит одного Sitemap в 50 000 URL и 50 MB без сжатия.
Но даже идеально сформированный XML остаётся только одним звеном.
Поисковику всё равно нужны:
нормальные внутренние ссылки;
правильный HTTP;
robots;
canonical;
доступный контент;
самостоятельная ценность страницы.Поэтому сильная SEO-архитектура выглядит не так:
URL существует
→ добавить в Sitemap.А так:
URL существует
↓
Он публичный?
↓
Он предназначен для поиска?
↓
Он возвращает 200?
↓
Он indexable?
↓
Он canonical?
↓
Это именно основной URL?
↓
Да
↓
SitemapИ когда эта логика является частью кода и редакционной системы, Sitemap перестаёт быть файлом, который разработчик вспоминает проверить после публикации.
Он становится автоматическим индексным реестром сайта, всегда синхронизированным с реальным состоянием продукта.