Перейти к содержимому

Защита от индексации (страховка для окружений вне production) ​

Попадание staging или локальной копии сайта в Google — одна из самых распространённых и неприятных SEO-ошибок: дубликаты конкурируют с настоящими страницами, закрытое окружение оказывается в индексе, а очистка инструментом удаления URL занимает недели. Типичная причина — noindex только в .env, который забыли задать, или правило robots, перезаписанное при развёртывании.

Защита от индексации затрудняет такую ошибку на уровне устройства приложения. Привяжите возможность индексации к окружению Laravel вместо флага, о котором нужно помнить: если приложение работает вне списка разрешённых окружений, для каждой страницы принудительно задаётся noindex,nofollow, управляемый robots.txt запрещает обход всем роботам, а seo:audit явно сообщает об этом.

Это бесплатная функция ядра.

Что происходит при активной защите ​

Если app()->environment() не входит в seo.indexing_guard.allowed_environments и защита включена, автоматически выполняются четыре действия:

  1. Резолвер принудительно задаёт noindex,nofollow каждой странице. Это применяется выше всей цепочки приоритетов и переопределяет даже явное значение robots страницы, сохранённое в seo_meta.
  2. HTTP-заголовок X-Robots-Tag: noindex,nofollow отправляется с каждым ответом, проходящим через приложение. См. ответы не в HTML ниже.
  3. SEO::robotsTxt()->build() создаёт robots.txt с полным запретом обхода (и ai.txt): обычные User-agent: * / Disallow: /. Это охватывает команду seo:robots-txt и необязательный динамический маршрут.
  4. seo:audit выводит заметное сообщение, чтобы состояние «всё с noindex» не стало неожиданностью при чтении отчёта.

В разрешённых окружениях (по умолчанию production) защита полностью бездействует: вывод не меняется и побайтно идентичен.

Ответы не в HTML (PDF, ленты, изображения) ​

Принудительный метатег robots доступен только роботам, разбирающим HTML: у PDF, RSS/Atom-ленты, изображения и любого другого ответа не в HTML нет <head>. Поэтому активная защита также отправляет ту же директиву HTTP-заголовком через глобальный middleware:

http
X-Robots-Tag: noindex,nofollow

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

php
'indexing_guard' => [
    'send_header' => env('SEO_INDEXING_GUARD_HEADER', true),
],

Middleware регистрируется только при включённой защите, поэтому выключенная функция ничего не добавляет в стек.

Статические файлы обходят PHP

Файл, который веб-сервер напрямую отдаёт из public/, не попадает в Laravel и не может получить этот заголовок. Защитите такие файлы на внешнем уровне (конфигурация веб-сервера / CDN). Функция охватывает всё, что проходит через приложение.

Почему переопределяется явное значение robots ​

Во всех остальных случаях Rankbeam отдаёт приоритет явно сохранённому значению — в этом смысл цепочки приоритетов. Защита — намеренное исключение выше явного слоя, поскольку риск здесь односторонний:

  • База staging обычно скопирована из рабочего окружения, поэтому страница с сохранённым index,follow принесла бы эту директиву в staging и попросила индексацию.
  • Ошибочно индексировать staging опасно; ошибочно назначить ему noindex ничего не меняет. Поэтому защита задаёт границу, которую сохранённое значение не может обойти, именно в тех окружениях, где индексация никогда не нужна.

Включение ​

Защита поставляется выключенной, поэтому установка или обновление пакета не меняет вывод окружения вне production без вашего решения. Это та же политика побайтно неизменного вывода до явного включения, что у blank_is_unset резолвера и создаваемых OG-изображений. Включите одной строкой:

dotenv
SEO_INDEXING_GUARD=true

Со стандартным списком разрешённых production не затрагивается, поэтому защиту можно оставлять включённой в общей конфигурации. Проверьте, что список включает все окружения, которые вы хотите индексировать. Защита настоятельно рекомендуется и рассматривается для включения по умолчанию в Core 4.

Отключите такой же одной строкой:

dotenv
SEO_INDEXING_GUARD=false

Какие окружения могут индексироваться ​

По умолчанию разрешено только production. Переопределите список переменной окружения со значениями через запятую:

dotenv
# Let a public preview environment index too
SEO_INDEXING_GUARD_ALLOWED="production,prod-eu"

Или в config/seo.php:

php
'indexing_guard' => [
    'enabled' => env('SEO_INDEXING_GUARD', false),
    'allowed_environments' => ['production', 'prod-eu'],
],

Записи сопоставляются через Str::is(), поэтому работают шаблоны с подстановочными знаками: 'prod*' соответствует production и prod-eu:

php
'allowed_environments' => ['prod*'],

Пустой список означает, что ни одно окружение не может индексироваться: защита активна везде (безопасное направление отказа). При этом пустое или состоящее из пробелов значение переменной SEO_INDEXING_GUARD_ALLOWED использует ['production'] как резервное, чтобы опечатка не могла незаметно запретить индексацию рабочего сайта. Если действительно нужно «везде», явно задайте [] в конфигурации.

Проверка ​

seo:audit показывает сообщение, а в --json передаёт машиночитаемое состояние:

bash
php artisan seo:audit --json
json
{
    "indexing_guard": {
        "active": true,
        "environment": "staging",
        "allowed_environments": ["production"],
        "directive": "noindex,nofollow"
    },
    "pages": [ /* ... */ ]
}

Отдаваемый/созданный robots.txt в защищённом окружении:

# robots.txt — managed by Rankbeam
# Indexing guard ACTIVE: this app is running in the "staging" environment,
# which is not in seo.indexing_guard.allowed_environments. Every crawler is
# disallowed so this non-production site stays out of search results.
# https://rankbeam.dev/guide/indexing-guard

User-agent: *
Disallow: /

Область действия ​

Защита управляет директивами индексации: метатегом robots, заголовком X-Robots-Tag и robots.txt. Она не меняет заголовки страниц, описания, канонические URL или schema.org и независима от политики вывода robots (seo.robots.emit_default): поскольку noindex,nofollow отличается от значения сайта по умолчанию, тег выводится всегда.

rankbeam/laravel-seo распространяется под лицензией MIT.