コンテンツへ移動

スキャンの定期実行と差分

完全なSEOスキャンを定期実行し、前回のスキャンから何が変わったかを確認できます。新規、再発、修正済みの問題を影響度順に並べ、ダッシュボードと、任意で有効にする概要メールに表示します。

2つの機能を同じページで扱うのは、組み合わせて使うからです。差分があることで、定期スキャンの結果を受け取る意味が生まれます。

前回のスキャンからの変更

各スキャンの完了時に、未解決問題の集合を軽量なスナップショット(seo_scan_run_issues)に固定します。2回の実行のスナップショットを比較すると、次の3種類の正確な差分が得られます。

  • 新規 — 前回は未解決でなく、今回は未解決で、さらに過去のどのスキャンでも未解決になったことがない問題です。初めて見つかった問題を指します。
  • 再発 — 修正されていた問題が再び現れた状態です。「重大度が上がった」という意味ではありません。重大度は問題の種類ごとに固定されています。ここで意味のある後退は再発であり、問題のライフサイクルでいう再オープンです。
  • 修正済み — 以前のスキャンでは未解決で、今回はなくなった問題です。

各グループは影響度順に並ぶため、重要なものから確認できます。

問題テーブルではなくスナップショットを使う理由

問題には修正・再オープンのライフサイクルがあります。同じ行をスキャンごとに更新し、未解決のままであればscan_run_idを最新の実行に付け直します。問題の履歴を維持するには便利ですが、現在のテーブルだけでは実行Nの終了時点で何が未解決だったかは分かりません。継続する問題が指すのは、常に最新の実行だけだからです。

そのため各実行では、安定した問題のフィンガープリントissue_type | target | fieldをキーに、未解決の集合を保存します。ホワイトラベルレポートが差分に使うものと同じ識別方法です。差分は、固定された2つのフィンガープリント集合の演算になります。連続する実行だけでなく、任意の2回の実行に対して正しく比較できます。

例外的な状況の扱い

  • ページがスキャン対象から外れた場合。 その未解決の問題は再検査されないため、未解決のまま各実行のスナップショットに再記録されます。未解決のままと表示し、誤って「修正済み」にはしません。確認しなくなっただけで、ページが直ったとは判断しません。
  • スキャンの間に検査を無効にした場合。 その問題は出力されなくなり、ライフサイクルが修正済みとして扱い、未解決の集合から外れます。そのため、修正済みと表示します。これはスキャナーの現在の判定を反映していますが、問題単位で「修正した」と「検査を無効にした」を区別することはできません。
  • アップグレード後の最初のスキャン。 この機能がなかった時期の実行にはスナップショットがないため、比較基準には選びません。最初にスナップショットを保存したスキャンは比較基準となり、現在の状態だけを表示して差分は出しません。サイト全体を「新規」と報告することはありません。スナップショットを持つ2回目のスキャンから差分を表示します。

ダッシュボードでの表示

SEOダッシュボード前回スキャンからの変更ウィジェットは、直近2回の完了済みスキャンを比較し、新規・再発・修正済みの件数と、各グループの主な問題を影響度順に表示します。2回のスナップショットが揃うまでは、比較基準であることを短く案内します。

影響度順の並び替え

差分の各グループは、重要な問題が先に来るよう、影響度スコアで並べます。

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_importance1となり、影響度は純粋な重大度順になります。データを作り上げず、妥当な初期動作を使います。需要に応じた重み付けを有効にするには、seo-pro:gsc-syncGSC履歴を同期してください。

重みと対象期間は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式を設定して制御できます。cron式はfrequencyより優先されます。

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

これでパッケージがLaravelスケジューラーにseo-pro:scanを登録します。withoutOverlappingにより、定期実行するコマンドの重複実行を防ぎます。このスケジューラーロックは、キュージョブの実行期間全体を保護するものではありません。登録はスケジューラー・コンソールのコンテキストだけで行うため、Webリクエストの追加負荷はありません

スケジューラーを動かす必要があります

Laravelスケジューラーが動いていなければ、パッケージの定期実行も動きません。標準の1行のcron(* * * * * php artisan schedule:run)を使うか、開発環境ではphp artisan schedule:workを使ってください。本番環境の設定を参照してください。

自分で設定する場合は、schedule.enabledを無効のままにして、独自のコンソールカーネルからコマンドを定期実行してください。差分と概要は引き続き使えます。

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

--syncは、対象ごとに1つのジョブをキューに入れる代わりに、その場でスキャンを実行します。キューワーカーのない小さなサイトには使えますが、本番では使わないでください。

概要メール

明示的に有効にすると、定期スキャンの完了時に前回スキャンからの変更メールを受け取れます。新規・再発・修正済みの問題を影響度順に並べた、ブランドを反映する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、Webhook、独自のダイジェストを使うには、Rankbeam\Seo\Pro\Events\SeoScanCompletedイベントを購読してください。完了した実行ごとに1回発火し、実行情報を持ちます。Rankbeam\Seo\Pro\Scanning\Delta\ScanRunDeltaで差分を作り、任意の通知先に送れます。

保持期間

スナップショットは実行とともに連鎖削除されるため、seo-pro:scan-pruneが期限切れのものを自動で削除します。新しい定期処理を追加する必要はありません。実行は未解決の問題を持たなくなってから削除されるため、最近の実行のスナップショットは差分比較に使えます。

seo-pro.scan.delta.snapshot => falseでスナップショット保存を完全に無効にできます。その場合、差分も概要もありません。

rankbeam/laravel-seoはMITライセンスで公開されています。