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

Расписание сканирований и изменения

Выполняйте полное SEO-сканирование по расписанию и смотрите, что изменилось с прошлого сканирования: какие проблемы появились, вернулись или были исправлены, с сортировкой по влиянию — в панели и, по желанию, в письме со сводкой.

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

Что изменилось с прошлого сканирования

Каждое завершённое сканирование фиксирует набор открытых проблем в небольшом снимке (seo_scan_run_issues). Сравнение снимков двух запусков даёт точное различие по трём категориям:

  • Новые — проблема не была открыта раньше, открыта сейчас и никогда не была открыта ни в одном более раннем сканировании: действительно первое обнаружение.
  • Вернувшиеся — проблема была исправлена, но появилась снова. (Не «стала серьёзнее»: серьёзность фиксирована для типа проблемы, поэтому значимая регрессия — её возвращение, то самое повторное открытие из жизненного цикла.)
  • Исправленные — проблема была открыта в более раннем сканировании, но теперь исчезла.

Каждая категория сортируется по влиянию, чтобы важное было первым.

Почему снимок, а не таблица проблем

Проблемы имеют жизненный цикл исправления и повторного открытия: одна строка обновляется между сканированиями (её scan_run_id каждый раз указывает на новый запуск, пока проблема открыта). Это удобно для долговременной истории, но текущая таблица не может сказать, какие проблемы были открыты в конце запуска N: сохраняющаяся проблема всегда указывает только на последний запуск.

Поэтому каждый запуск сохраняет снимок открытого набора с ключом — стабильным отпечатком проблемы, issue_type | target | field (ту же идентичность сравнивает отчёт под своим брендом). Изменения вычисляются обычными операциями над двумя зафиксированными наборами отпечатков и корректны для любых двух запусков, не только соседних.

Пограничные случаи без ложных выводов

  • Страница выпала из набора сканирования. Её открытые проблемы больше не проверяются, поэтому остаются открытыми и снова входят в снимок каждого запуска. Они показываются как всё ещё открытые, а не ложно «исправленные». (Мы не объявляем страницу исправленной только потому, что перестали на неё смотреть.)
  • Между сканированиями отключили проверку. Она перестаёт выдавать проблемы, жизненный цикл отмечает их исправленными, и они покидают открытый набор: отображаются как исправленные. Это соответствует текущему заключению сканера; на уровне проблемы нельзя отличить «вы исправили её» от «вы отключили проверку».
  • Первое сканирование после обновления. У запусков до появления этой функции нет снимков, поэтому они никогда не выбираются базой сравнения. Первое сканирование со снимком становится исходным (текущее состояние, без изменений), а не объявляет весь сайт «новым». Со второго сканирования со снимком сравнение работает.

В панели

Виджет «Что изменилось с последнего сканирования» в SEO-панели показывает число новых, вернувшихся и исправленных проблем и главные проблемы каждой категории по влиянию, сравнивая два последних завершённых сканирования. Пока нет двух снимков, он показывает короткое сообщение об исходном состоянии.

Сортировка по влиянию

Каждая категория изменений сортируется по показателю влияния, чтобы самые значимые проблемы были первыми:

impact = severity_weight × page_importance
  • severity_weight использует опубликованную методику оценки: critical имеет вес 40, warning — 15, notice — 5. Серьёзность выражает заявленную продуктом значимость дефекта, поэтому сортировка читает её, а не создаёт вторую шкалу.

  • page_importance определяется реальным поисковым спросом — числом показов страницы в Search Console, поскольку этот сигнал действительно отличает страницы друг от друга:

    page_importance = 1 + demand_weight·demand + priority_weight·priority
    demand   = log1p(page impressions) / log1p(busiest page's impressions)   ∈ [0,1]
    priority = the page's configured per-class sitemap priority              ∈ [0,1]

    Показы масштабируются логарифмически (страница с трафиком в 10× больше не становится в 10× важнее) и нормализуются относительно самой востребованной страницы. Поэтому формула одинаково работает для небольшого блога и крупного каталога. <priority> карты сайта — лишь слабый дополнительный сигнал: по умолчанию он не задан и даже при задании часто одинаков для всех страниц, поэтому не может определять сортировку; он немного влияет, если в seo.sitemap.models настроены приоритеты типов.

Без Search Console всё работает. Если нет синхронизированной истории GSC и настроенных приоритетов, page_importance равно 1 для всех страниц, а влияние — просто сортировка по серьёзности: разумное значение по умолчанию, а не выдуманные данные. Синхронизируйте историю GSC (seo-pro:gsc-sync), чтобы учитывать спрос.

Настраивайте веса и окно в seo-pro.scan.delta.impact.

Планирование сканирования

Пакет ничего не планирует по умолчанию. Включите:

php
// config/seo-pro.php
'schedule' => [
    'enabled' => true,          // env SEO_PRO_SCHEDULE_ENABLED
    'frequency' => 'weekly',    // daily | weekly | monthly | hourly
    'time' => '03:00',          // for daily/weekly/monthly
    'timezone' => null,         // null = app timezone
    // ...
],

Или задайте полное cron-выражение для точного управления (оно имеет приоритет над frequency):

php
'cron' => '0 3 * * 1',   // env SEO_PRO_SCHEDULE_CRON

Готово: пакет регистрирует seo-pro:scan в планировщике Laravel с withoutOverlapping, предотвращающим одновременное выполнение запланированной команды. Эта блокировка планировщика не охватывает весь срок работы заданий очереди. Регистрация выполняется только в контексте планировщика/консоли, поэтому не добавляет накладных расходов веб-запросам.

Нужен работающий планировщик

Расписание пакета ничего не делает, пока не работает планировщик Laravel: стандартная строка cron (* * * * * php artisan schedule:run) или php artisan schedule:work при разработке. См. настройку рабочего окружения.

Предпочитаете подключить сами? Оставьте schedule.enabled выключенным и запланируйте команду в своём консольном ядре: изменения и сводка продолжат работать:

php
$schedule->command('seo-pro:scan --notify')->weekly();

--sync выполняет сканирование синхронно вместо постановки одного задания на каждую цель (подходит небольшому сайту без воркера; в рабочем окружении оставьте выключенным).

Письмо со сводкой

Включите письмо «что изменилось с прошлого сканирования» после завершения запланированного сканирования: HTML-сводку под вашим брендом с новыми, вернувшимися и исправленными проблемами по влиянию:

php
'schedule' => [
    // ...
    'notify' => [
        'enabled' => true,                       // env SEO_PRO_SCHEDULE_NOTIFY
        'recipients' => ['seo@agency.test'],     // falls back to reports.recipients
        'subject' => 'SEO scan summary',
        'only_on_change' => true,                // skip when nothing changed
    ],
],

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

Сводка отправляется только для запуска с --notify (планировщик добавляет его автоматически при включённом notify.enabled). Разовый seo-pro:scan без --notify никому не отправляет письмо.

Нужен другой канал?

Хотите Slack, вебхук или собственную сводку вместо email? Подпишитесь на событие Rankbeam\Seo\Pro\Events\SeoScanCompleted: оно вызывается один раз для завершённого запуска и содержит сам запуск, поэтому можно получить изменения через Rankbeam\Seo\Pro\Scanning\Delta\ScanRunDelta и направить их куда нужно.

Срок хранения

Снимки удаляются каскадно вместе с запуском, поэтому seo-pro:scan-prune автоматически удаляет устаревшие: новое расписание не нужно. Запуск очищается, только когда не содержит открытых проблем, поэтому снимок недавнего запуска всегда доступен для сравнения.

Полностью отключите снимки (без изменений и сводок) через seo-pro.scan.delta.snapshot => false.

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