実践ガイド

AIブログの30日集計を4回比較:PVだけで改善を決めない手順

AIに記事を更新させると、公開できたかは確認しやすい一方、「読者に役立ったか」の判断は別に必要です。このブログでは2026年9月5日、13日、20日、22日の4回、同じ対象ホストの直近30日を取得しました。推定ページビューは140、130、120、110と並びましたが、これを下降傾向や記事品質の悪化とは判定しませんでした。

4つの30日窓は大きく重なり、値は10刻みの推定でした。さらに、検索結果の表示回数や検索語は取得していません。この記事で扱うのはアクセス増加の成功事例ではなく、数字をAIへ渡す前に「比較できる条件か」「何をまだ知らないか」を残し、判断を保留する手順です。

結論:4回とも取得できても、効果比較とは限らない

今回確認できたのは、ai-shinka.com に限定した完了済みUTC30日分を、同じ集計処理で4回取得できたことです。9月22日の結果は推定110PV・100 visitsでした。

一方、9月20日と22日の集計は30日のうち28日が同じです。新しく入る日と期間外へ出る日がそれぞれ2日しかないため、合計の差だけでは記事更新の効果、自然検索の増減、読者数の変化を切り分けられません。推定値の変動幅も別途考える必要があります。

したがって今回の判断は次の3点です。

  1. 110PVを110人とは書かない。
  2. 140から110への並びを減少トレンドとは書かない。
  3. Search Consoleでしか確認できない検索表示・クリック・クエリ・CTR・平均順位は「未確認」のまま残す。

検証条件:対象、期間、取得範囲を固定した

確認日は2026年9月22日、日本時間です。Windows、PowerShell、Python 3.14.2の既存環境で、Cloudflare Web Analyticsの集計処理を実行しました。新しい解析サービスの契約や認証変更は行っていません。費用は0円です。

対象は ai-shinka.com の完全一致だけです。www付きホスト、別サイト、Cloudflare Pagesの発行URLを合算していません。期間は完了済みのUTC日だけを使い、開始日を含み、終了日を含まない30日間です。日本時間の暦日30日とは一致しません。

取得したのは日別、ページ別、国別、端末別、参照元別の集計です。各内訳は上位50行までで、個々の訪問者を追うログではありません。実際に標本化されたイベント件数は今回の出力にないため、nullのまま保存しました。

Cloudflareの公式資料では、GraphQLの問い合わせはアカウントまたはゾーンの範囲、データセット、フィールドで構成され、ノードごとに期間や返却件数などの制限があります。また、サンプリング対象のデータでは標本から推定した値が返る場合があります。これは公式仕様の確認であり、以下の数値は当サイトで実行した結果です。

4回の結果:数字より先に窓の重なりを見る

4回の保存済み出力から、比較に必要な項目だけを並べました。PVとvisitsはいずれも推定値です。

取得日 UTC期間(終了は含まない) 推定PV 推定visits 最大の日別平均sample interval
9月5日 8月6日〜9月5日 140 100 10
9月13日 8月14日〜9月13日 130 120 10
9月20日 8月21日〜9月20日 120 110 10
9月22日 8月23日〜9月22日 110 100 10

表だけを見るとPVが毎回10ずつ減っています。しかし、同じ30日が移動する集計では、取得日ごとに入る日と抜ける日が変わります。9月5日と22日も13日間が重なります。独立した4群を同条件で比較した実験ではありません。

また、sample interval 10 は今回の処理が返した日別平均の最大値です。全期間の平均でも、実イベント数でもありません。合計を10で割って「11件を実測した」と復元することはしませんでした。

再現手順:まず出力条件を読み、次にテストする

このサイトでは、リポジトリのルートから次のコマンドで30日分を取得しました。認証情報は出力や記事に含めません。

python tools/fetch_analytics.py --days 30 --json

別の環境で同じコードをそのまま使えることを保証する手順ではありません。対象サイトを読む権限と利用可能なデータセットが必要です。認証エラーや対象ホスト不一致が出た場合に、フィルターを外して成功扱いにしないことを優先しています。

集計処理の回帰確認は次のコマンドで行いました。

python -m unittest discover -s tools -p 'test_analytics_audit.py' -v

2026年9月22日は9テストが0.276秒で合格しました。対象ホストと期間が5つの集計軸すべてに入ること、違うホストやホスト欠落で停止すること、APIエラーを空の成功結果にしないこと、UTC境界、上位件数制限、実イベント数未取得、WindowsでのUTF-8出力を確認しています。

最初はリポジトリルートからモジュール名を直接指定し、fetch_analytics を見つけられず1件のImportErrorになりました。これは集計処理の失敗ではなく、テストの探索起点が違ったことが原因です。上記のdiscover形式で再実行して9件の成功を確認しました。失敗した呼び出しをPASSには数えていません。

実務での使い方:AIへ渡す前の5手順

集計サービスが違っても、次の順番なら同じ誤読を減らせます。

  1. 対象を読む。 ホスト、プロパティ、フィルターを確認する。複数サイトの合計を1サイトの実績へ置き換えない。
  2. 期間を読む。 開始・終了・タイムゾーン、当日途中を含むかを残す。「30日」という長さだけで同条件とみなさない。
  3. 数字の種類を読む。 PV、visits、人数、検索表示、検索クリックを別々の欄にする。推定値には印を付ける。
  4. 取得範囲を読む。 全件か上位だけか、空欄はゼロか未取得かを分ける。分からない項目は未確認のまま渡す。
  5. 判断を一つに絞る。 変更するなら、何を観測すれば効果を確認できるかも同時に決める。

たとえば今回の事実欄には「モバイル20PVが返った」、判断欄には「スマホ表示の検収を続ける」、未確認欄には「端末別の読了率」と書けます。「モバイル読者が少ないからスマホ対応は不要」とは判断できません。

週次レビューで使う12欄の判断票

空欄をAIに想像で埋めさせず、取得結果か未確認のどちらかを残します。

対象サイトとフィルター:
開始日時(含む):
終了日時(含まない):
タイムゾーン/当日途中の扱い:
取得元と確認日:
取得した指標・値・単位:
推定の有無/上位件数の制限:
未取得・未確認の項目:
今回確認できた事実:
次に点検・変更すること(1件):
この数字だけでは言わないこと:
次回、効果を見るために必要な追加情報:

今回なら「次に点検すること」はSearch Consoleの完了済み30日エクスポートです。クエリとページ別の表示・クリック・CTR・平均順位を、Cloudflareの推定閲覧値と混ぜずに確認します。取得できるまでは、検索流入の改善を完了扱いにしません。

限界:集計の正しさと記事の有用性は別

9テストが保証するのは、用意した入力に対する集計処理の振る舞いです。Cloudflare側の全データの完全性、訪問者の意図、記事の読了、広告審査の結果までは保証しません。

今回の集計には運営者自身の公開後確認が混ざる可能性があります。上位50行に現れないページを0閲覧とも扱えません。推定値が10刻みで並んだ理由も独立に検証していないため、10PVの差を改善・悪化の閾値にはしません。

アイキャッチは本稿用に作成済みの概念イラストで、管理画面や生ログの証拠ではありません。独自の証拠は、保存した4回の条件付き集計、9テスト、判断票です。

公開工程そのものの失敗と生成物の確認は、Astro + Cloudflare Pagesの公開前確認に分けています。生成後のリンク切れ検査は、静的HTMLの内部リンク検査を参照してください。

4回の数字をきれいな物語へ直すより、比較できない理由と次に必要な情報を残す方が、次の編集判断を再現できます。PVだけでは決めず、対象・期間・推定・未取得を一枚に分けることが今回の持ち帰りです。

一次情報・出典

  1. Cloudflare:GraphQL Analytics APIのサンプリング
  2. Cloudflare:GraphQL問い合わせの構造
  3. Cloudflare:GraphQL Analytics APIの制限