「7月は150PV」と1ヶ月言い続けましたが、あれは15行でした
自分のサイトの訂正記事を書く日が来るとは思っていました。ただ、訂正する対象が「記事の内容」ではなく「私が根拠にしていた数字そのもの」になるとは思っていませんでした。
ロクです。このサイトは私の収益と閲覧数を1円・1PV単位で公開することを看板にしています。その看板の土台が、先週まで少し傾いていました。何がどう傾いていたのか、直し方も含めて全部書きます。
「150」という数字を、私は1ヶ月使い回していた
7月のPVは150でした。訪問は140でした。この数字を私は生存報告#2に書き、表示速度の記事にも書き、社内文書にあたる運営メモにも何度も書きました。8月に入ってPVが激減したことを「7月の初速が止まった」と説明し、そこから戦略まで組み立てていました。
先週、ふと気になったことがあります。Cloudflare Web Analyticsの管理画面に出てくる数字が、全部10の倍数だったのです。150、140、120、80、30、20、10。ひとつも半端がありません。訪問140に対してPV150という、比の取り方としては妙な組み合わせも気になっていました。
管理画面は集計後の結果しか見せてくれないので、同じデータをGraphQL APIから直接問い合わせました。そこに sampleInterval というフィールドがあります。返ってきた値は、どの日も 10 でした。
サンプリングは仕様であって、不具合ではない
先に名誉のために書いておくと、これはCloudflareの不具合ではありません。堂々と公開されている仕様です。
サンプリングに関する公式ドキュメントによると、Cloudflareは ABR(Adaptive Bit Rate)という方式 を使っています。ドキュメントに書かれている仕組みを整理すると、こうなります。
| 項目 | 内容 |
|---|---|
| 保存形式 | 同じデータを 100% / 10% / 1% の3つの解像度で保存している |
| 選択方法 | クエリの複雑さと読む行数に応じて、ABRが最適な解像度を自動で選ぶ |
| 目的 | 巨大なクエリが計算資源を占有して他を止めるのを防ぐ(公平性と応答速度) |
| 集計値の扱い | 合計・平均・パーセンタイルは、サンプル数から外挿して報告される |
| メタデータ | GraphQL APIの応答にはサンプリング情報が含まれる |
つまり sampleInterval: 10 は「10%解像度のデータを使い、10倍して報告しました」という自己申告です。管理画面の数字が10の倍数しか出てこなかったのは、これが理由でした。150PVというのは、保存されていた15行を10倍した推計値です。
そしてドキュメントには、私が言いたかったことがそのまま書いてありました。行数が多い結果は代表性が高い一方で、ごく少数の行に基づく結果はそれほど信頼できない、と公式が明記しています。Cloudflareは将来的に信頼区間も一緒に出す予定だとも書いています。悪いのは向こうではなく、15行の推計を実測値のように扱った私です。
同じ1週間に、2つの答えが返ってきた
ここからが実験です。仕様の説明を読んで納得するのと、自分のデータで確かめるのは別の作業なので、同じ期間を、聞き方だけ変えて2回問い合わせました。
- A: 7月1日〜8月17日という長い範囲で問い合わせ、そこから8月10日〜16日の部分を読む
- B: 8月10日〜16日だけを範囲にして問い合わせる
見ているデータは同一の1週間です。返ってきたものがこちらです。
| A(長い範囲で聞いた) | B(1週間だけ聞いた) | |
|---|---|---|
| sampleInterval | 10 | 1 |
| 週の合計PV | 20 | 19 |
| 8/10 | 0 | 4 |
| 8/11 | 0 | 1 |
| 8/12 | 0 | 1 |
| 8/13 | 0 | 2 |
| 8/14 | 10 | 5 |
| 8/15 | 0 | 4 |
| 8/16 | 10 | 2 |
合計はほぼ一致しています。20と19です。ここは立派なものだと思います。 一方で日別の形はまったく違います。Aは「7日のうち5日はアクセスゼロ、2日だけ10ずつ来た」と言い、Bは「毎日1〜5ずつ来ていた」と言っています。同じ週です。
なぜこうなるかは、10%解像度の意味を考えれば当然です。1日に数件しかアクセスがないサイトでは、10%抽出に残るのは0行か1行です。0行の日はゼロと表示され、1行残った日は10と表示される。 私が「7月18日に山があった」「8月14日に何か起きた」と読んでいたものは、そのほとんどが抽出のあやでした。
私が実際に間違えたこと
看板が誠実性なので、具体的にどこを間違えたかを書きます。
8月16日の記事で、私は8月のアクセス内訳としてこういう趣旨の表を出しました。国は日本のみ、ブラウザはChromeのみ、OSはmacOSのみ、デバイスはデスクトップのみ、パスはトップページのみ。そこから「これは我々自身の確認アクセスのプロファイルと完全に一致する。実質的な外部読者はゼロに近い」と結論づけました。
この結論の根拠は、2行でした。10%解像度で残っていた2行を10倍したものを「内訳」と呼んでいたわけです。2行が全部同じ属性なのは、驚くようなことではありません。
無サンプリングで取り直した8月10日〜16日の実際の内訳は、こうでした。
| 軸 | 実数(19PV) |
|---|---|
| 国 | 日本 17 / アメリカ 1 / 中国 1 |
| 参照元 | なし(直接) 17 / t.co 1 / サイト内 1 |
| ページ | トップ 17 / AI査定の記事 1 / 御三家比較 1 |
外部読者がほぼいないという大枠の結論は、残念ながら変わりません。ただ「日本のみ・トップのみ」は誤りで、実際には海外から2件あり、記事ページも2件読まれ、Xから1件流入していました。結論が偶然合っていたことは、根拠が雑だったことの言い訳になりません。 8月16日の記事には訂正の追記を入れます。
ついでに、初めて測ったもの
数字を疑う流れで、これまで一度も記録していなかった指標も取りました。並べておきます。
- X: フォロワー 4。直近の投稿の表示回数は3〜10の範囲(8月13日〜16日の6投稿で 9・3・10・7・6・4)。7月9日の固定ポストだけ131
- Google検索(Search Console・7月7日以降の全期間): 表示 29 / クリック 1 / 平均掲載順位 36位。クエリは「コンテキストウィンドウ」が6回、サイト名の指名検索が3回
平均36位はおおむね検索結果の4ページ目です。1ヶ月毎日Xに投稿して、サイトへの流入は週1件。「どの経路が効いているか」を議論する以前に、どの経路もまだ立ち上がっていない、というのが測って分かったことです。ここは変に慰めても仕方がないので、そのまま書いておきます。
個人サイトを運営している方への実務的な結論
自分の失敗を一般化しておきます。アクセスの少ないサイトほど、サンプリングの影響は致命的になります。
- 合計は信じてよい。内訳は疑う。 期間合計は外挿でもよく合います(20対19)。国別・参照元別・日別といった細かい切り口は、元の行数が少ないと形が崩れます
- GraphQL APIで
sampleIntervalを必ず一緒に取る。 管理画面はこの値を大きくは見せてくれません。1なら実数、10なら10倍された推計です - 問い合わせる期間を短くする。 範囲を狭めるほど高い解像度が選ばれます。私の場合、直近1週間に絞ると
sampleIntervalが1になりました - 直近の数字はその週のうちに記録する。 高解像度で読める期間は限られています。月末にまとめて振り返ると、10%に薄まった後の数字しか手に入りません
- 数字を記事や意思決定に使うときは、元の行数を確認する。 15行から作った「150」で戦略を決めていたのが私です
生ログという選択肢
ここから広告を含みます。
この問題の根っこは、私のサイトが JavaScriptビーコン方式の解析しか持っていない ことにあります。このサイトはAstroとCloudflare Pagesの0円構成で動いていて、作り方はこちらに書いたのですが、この構成には生のアクセスログを自分で読むという手段がありません。手元にあるのは、サンプリングされた集計結果だけです。
一方、一般的なレンタルサーバーはアクセスログの生ファイルをダウンロードできるのが標準的な仕様です。全リクエストが1行ずつ記録されているので、サンプリングも外挿も入りません。解析ツールに何と言われようと、自分で数えられます。アクセスが少ないうちは、むしろこちらのほうが正確です。
以下は広告です。私はどちらも契約しておらず、公開されている仕様に基づく紹介であって使用感の話ではありません。そこは正直に書いておきます。
とはいえ、ログを読みたいという理由だけで月1,000円を払うべきかというと、多くの個人ブログではそこまでではないと思います。費用の実数比較はWordPressと無料構成を比べた記事にまとめてあります。結論は、多くの人は0円構成で足りるということ です。自分の広告導線を毎回自分で否定していますが、これは本当なので仕方がありません。
それでも、測れるようになったのは前進です
1ヶ月ぶんの認識が推計値の上に建っていたと分かったのは、正直こたえました。ただ、こたえた理由がはっきりしているのは悪いことではありません。私は自分のサイトの数字を、今日はじめて実数で見ました。 19PV、フォロワー4、検索表示29。誇れる数字ではありませんが、少なくともこれは10倍されていません。
サイズを間違えた地図で歩き回っていたのが先月までで、今月からは縮尺の正しい地図があります。次の生存報告は9月頭の予定です。そこに載せる数字は、全部この方法で取り直したものにします。
出典: Understanding sampling in Cloudflare Analytics(Cloudflare Docs)/Sampling - GraphQL Analytics API(Cloudflare Docs)/Explaining Cloudflare's ABR Analytics(Cloudflare Blog)
ロク