Представьте: сайт работает, страницы открываются, всё выглядит нормально. Но однажды вы запускаете краулер — и он находит 300+ битых ссылок. Все ведут на несуществующие адреса вроде /katalog/blog/, /product/blog/, /works/blog/category/.... Откуда взялся этот мусор, если ссылка на блог — вот она, в меню, работает?
Разбираю реальную ситуацию, которую встречаю на MODX-сайтах регулярно. Одна системная настройка — и навигация ломается на всех вложенных страницах.
Суть проблемы: относительные vs абсолютные ссылки
Браузер интерпретирует ссылки по-разному в зависимости от того, есть ли ведущий слеш:
href="/blog/"— абсолютный путь. Всегда ведёт наsite.ru/blog/, с какой бы страницы ни кликнулиhref="blog/"— относительный путь. Браузер дописывает его к текущему URL
Вот что происходит с относительной ссылкой href="blog/" в меню:
| Текущая страница | Куда ведёт ссылка | Результат |
|---|---|---|
/ (главная) | /blog/ | ✅ Работает |
/katalog/ | /katalog/blog/ | ❌ 404 |
/product/tovar-1/ | /product/tovar-1/blog/ | ❌ 404 |
/works/ | /works/blog/ | ❌ 404 |
На главной всё ок — потому что корень / + blog/ = /blog/. Но стоит зайти на любую вложенную страницу — и ссылка начинает вести в никуда.
Почему это происходит в MODX
В MODX Revolution есть системная настройка link_tag_scheme. Она определяет формат URL, который генерируется функциями makeUrl(), фильтром url в Fenom и сниппетами вроде pdoMenu, pdoCrumbs.
Возможные значения:
| Значение | Формат URL | Пример |
|---|---|---|
-1 | Относительный | blog/ |
0 или пусто | Относительно корня | /blog/ |
abs | Абсолютный от корня | /blog/ |
full | Полный URL | https://site.ru/blog/ |
https | HTTPS URL | https://site.ru/blog/ |
Значение -1 — это корень проблемы. При нём MODX генерирует URL относительно текущей страницы, без ведущего слеша. И любая ссылка в навигации, крошках, карточках товаров — начинает ломаться на вложенных уровнях.
Как это выглядит в шаблонах
Fenom-шаблон с фильтром url:
<a href="{242|url}">Блог</a>
При link_tag_scheme = -1 это рендерится как:
<a href="blog/">Блог</a>
pdoCrumbs без указания scheme:
{$_modx->runSnippet('pdoCrumbs', [])}
Хлебные крошки тоже получают относительные пути — и ведут в никуда на вложенных страницах.
Как найти проблему
1. Проверьте системную настройку
Зайдите в админку MODX → Настройки системы → найдите link_tag_scheme. Если стоит -1 — это оно.
2. Проверьте HTML вложенной страницы
Откройте любую страницу второго уровня (например, /katalog/) и посмотрите исходный код. Ищите ссылки без ведущего слеша:
curl -s https://site.ru/katalog/ | grep -oP 'href="[^/"h][^"]*"' | head -20
Если видите href="blog/", href="blog/category/..." — это относительные ссылки.
3. Прогоните краулер
Screaming Frog, Netpeak Spider или любой другой — фильтруйте по статусу 404. Если в списке десятки URL вида /katalog/blog/, /product/kontakty/, /works/uslugi/ — это массовая проблема относительных путей.
Как исправить
Шаг 1. Смените link_tag_scheme
В админке MODX → Настройки системы:
link_tag_scheme → abs
Это заставит все стандартные функции генерации URL возвращать абсолютные пути с ведущим /.
Шаг 2. Исправьте Fenom-шаблоны
Замените фильтр url на явный вызов makeUrl с параметром abs:
Было:
<a href="{242|url}" class="footer-nav__item">Блог</a>
Стало:
<a href="{$_modx->makeUrl(242, '', '', 'abs')}" class="footer-nav__item">Блог</a>
Параметры makeUrl:
242— ID ресурса''— контекст (пустая строка = текущий)''— параметры URL'abs'— схема (абсолютный путь)
Шаг 3. Исправьте pdoCrumbs
Добавьте параметр scheme в вызов:
Fenom-синтаксис:
{$_modx->runSnippet('pdoCrumbs', ['scheme' => 'abs'])}
MODX-тег:
[[pdoCrumbs? &scheme=`abs`]]
Шаг 4. Исправьте карточки и списки
Если в шаблонах карточек (товары, статьи) URL подставляется через {$uri}, замените на makeUrl:
Было:
<a href="{$uri}">{$pagetitle}</a>
Стало:
<a href="{$_modx->makeUrl($id, '', '', 'abs')}">{$pagetitle}</a>
Шаг 5. Проверьте хардкод
Иногда ссылки прописаны руками в чанках. Найдите все такие случаи через SSH:
grep -rn 'href="[^/"h#\{]' core/elements/ --include="*.tpl" --include="*.html"
Эта команда найдёт все href=, которые начинаются НЕ с /, НЕ с http, НЕ с # и НЕ с { — то есть потенциально относительные ссылки.
Шаг 6. Очистите кэш
Обязательно после всех правок:
# Через SSH
find core/cache -mindepth 1 -maxdepth 1 ! -name '.gitignore' -exec rm -rf {} +
Или через админку: Управление → Очистить кэш.
Чеклист: проверка после исправления
После применения фикса проверьте:
-
link_tag_scheme=absв системных настройках - На вложенной странице (
/katalog/) все ссылки в меню ведут правильно - Хлебные крошки показывают корректные абсолютные URL
- Карточки товаров/статей ведут на правильные страницы
- Повторный краулинг не находит 404 вида
/katalog/blog/ - Кэш MODX очищен
Почему это важно для SEO
Относительные ссылки в навигации — это не просто «не работают кнопки». Это серьёзная SEO-проблема:
Раздутый индекс. Поисковые боты ходят по всем ссылкам. Если на каждой из 50 страниц каталога есть относительная ссылка на блог — краулер найдёт 50 несуществующих URL. Умножьте на количество таких ссылок в навигации, футере, крошках — и получите сотни фантомных страниц.
Потерянный краулинговый бюджет. Поисковик тратит ресурсы на обход 404 вместо индексации реального контента.
Сигнал низкого качества. Массовые 404 — это сигнал поисковым системам, что сайт заброшен или плохо поддерживается.
Битые внутренние ссылки. PageRank не передаётся через 404. Страницы, на которые должны вести ссылки из навигации, теряют вес.
Как не допустить повторения
-
Не ставьте
link_tag_scheme = -1без веской причины. Значениеabs— безопасный дефолт. -
Используйте
makeUrlвместо хардкода. Ссылкаhref="/blog/"работает, но привязана к конкретному alias. Если alias изменится — ссылка сломается.makeUrl(ID)всегда вернёт актуальный URL. -
Всегда указывайте
schemeв pdoTools. По умолчанию pdoCrumbs и pdoMenu наследуютlink_tag_scheme. Если системная настройка вдруг изменится — ваши крошки сломаются. Явный&scheme=absстрахует от этого. -
Периодически прогоняйте краулер. Даже если всё работает — запускайте проверку раз в месяц. Битые ссылки могут появиться после обновления MODX, смены шаблона или редактирования чанков.
-
Добавьте правило в чанки комментарием:
{* ВАЖНО: всегда использовать makeUrl(..., 'abs') — НЕ фильтр |url *}
Это спасёт от ситуации, когда кто-то через полгода скопирует старый код с {ID|url} и вернёт проблему.
Итого
Одна настройка link_tag_scheme = -1 + навигация в шаблонах = сотни фантомных 404 на вложенных страницах. Проблема незаметна на главной, но ломает весь сайт для поисковых ботов и пользователей, которые кликают по меню не с корневой страницы.
Фикс занимает 15 минут: сменить системную настройку, пройтись по шаблонам, добавить abs в вызовы pdoTools, очистить кэш. Но если не знать, где искать — можно месяцами гадать, откуда берутся битые ссылки в Search Console.