ここのところ、アメブロのPVや google ad planner の件で「ページビューって意外に大雑把な指標なんですよ」「ツールによって数字はまちまちです。でもそれは全部正しいんですよね」「PVの定義、ぶっちゃけ無い!」「ですよねー」...といった話が知られるようになってきたようだ。

PVなんて定義次第でなんとでもなるとか、アメブロの「PV」ってずるいよね、みたいな話はアクセスログの集計を業務でやったことがある人なら前からよく分かっていたはずのことではあるけど、こういった騒ぎでもなければ普通の人は「そんな細かいこと」をいちいち気にはしてくれないものだ。
せっかくなので、「そんな細かいこと」でどれくらいの違いが出て来るのか、実例を示してみたいと思う。

このブログだとアクセス数が少なすぎるので、ライブドアブログ開発日誌の、5月のある一日のwebサーバのログを例にとって話を進めたい。

2009年5月14日の「ライブドアブログ開発日誌」のPCのアクセス数は、14284 か 10732、もしくは 4127、ひょっとすると 926、あるいはこれらの数字の前後10%ぐらいの値のどれか、だ。

900から14000まで15倍もの開きが出て来るのは集計が不正確だからではない。
これらの数字はいずれも、5月14日(とその前後)の、このブログに関するすべてのサーバログを抜き出して厳密に集計した結果だ。10倍以上の値の違いは、「アクセス数」の定義の違いによるものだ。
※ちなみにライブドアブログのアクセスカウンタは、このうちもっとも低い「926」をアクセス数としている。なに、みんなもっと大きい値になる方が好き ?

以下の表に、「どのようなデータをアクセス数のカウント対象とするか」と、その場合のPCとモバイルの「アクセス数」がどうなるかを書き出してみた。

カウント対象PCmobileなんて呼ぶ?
1Webサーバへの全てのリクエスト238061471"HTTPリクエスト数"
21のうち,画像へのリクエストを除外177461316
32のうち,GETまたはPOSTリクエストのものに限定176451316
43のうち,ステータスが200番台または300番台のものに限定176301316
53のうち,ステータスが200番台または304のものに限定174401225
65のうち,ページ本体以外(.cssや.rdfなど)へのリクエストを除外142841225
76のうち、クローラ,botと思われるUserAgentのリクエストを除外10732113"page views"
"アクセス数"
8javascriptビーコンによるクライアントサイドカウント
(※モバイルの場合は,インライン画像ビーコン)
412788
98のうち,30分以内の同一IPからのリクエストを除外100086"visits"
"sessions"
"訪問数"
108のうち,30分以内の同一IP&UserAgentのリクエストを除外100486
118のうち,30分以内の同一クライアント(IP&UserAgentのほか,cookieや端末idも利用して推定)のリクエストを除外101084
128のうち,1日以内の同一IPからのリクエストを除外90777
138のうち,1日以内の同一IP&UserAgentのリクエストを除外92584
148のうち,1日以内の同一クライアント(IP&UserAgentのほか,cookieや端末idも利用して推定)のリクエストを除外92681
158のうち,同じ日の同一IPからのリクエストを除外96280"daily unique users"
"ユニーク訪問者数"
168のうち,同じ日の同一IP&UserAgentのリクエストを除外97585
178のうち,同じ日の同一クライアント(IP&UserAgentのほか,cookieや端末idも利用して推定)のリクエストを除外98081

webサーバのログから集計する場合のファクター (1〜7)

  • リクエストには GET, POST のほかに、更新チェッカが送ってくる HEAD リクエストなど、ページビューとは言い難いものも存在する。(3)
  • レスポンスが400番台あるいは500番台の場合はエラーなので、(404広告のインプレッション数を調べているのでなければ) カウントしないのが普通である。(4)
  • 300番台のレスポンスのうち、リダイレクトが発生するものをカウントしてしまうと二重カウントになる。304 (not modified) のみページビューと数えて、他は除外するのが妥当だろう。(5)
  • 画像, *.css, *.rdf など、「ページ」とは言えないリソースへのアクセスは通常除外する。拡張子や,レスポンスの content-type などを元に判定する方法がある。(6)
  • webサーバのログから、人間以外のアクセス (更新チェッカやクローラ) を除外するのは手間がかかる。"Googlebot", "Slurp" などは有名だが、botの UserAgent の種類は無数にある。UserAgent を偽装している bot も相当数あると思われ、メンテナンスの手間や誤判定のリスクは大きい。(7)

ビーコンを利用する場合のファクター (8)

ビーコンという名称はここを参考にした。(ロボットではなく) 人による通常の閲覧方法でページが実際に表示された時にのみ、javascript によって (モバイルの場合は埋め込み画像によって) カウンタサーバにアクセスが送られる方式を指す。

  • javascriptのエラーやjavascriptオフの設定などでカウントが漏れる場合がある。
  • ページの表示に時間がかかっている場合、ビーコンの発火前にユーザがページを閉じてしまう場合がある。
  • 現状たまたまうまくいっているだけで、今後クローラも javascript を実行するのが当たり前になっていったりすれば別の方法を考えなければならなくなる。(現在でも、マウス操作の自動化ソフトを使って実際にブラウザを操作しているような場合はカウントされてしまう)

いまのところ、一般の人が「PV」「アクセス数」と聞いた場合の感覚と一番近いのはこの 8 の数値だと思われる。上表の 1〜6 までは PV というよりは「サーバへのリクエスト数」と呼ぶのが妥当なのではないだろうか。

サーバのアクセスログベースでPVを算出するとだいたい 6〜7 の数値の範囲に収まるはずだが、これには UserAgent では除外できなかった bot アクセスがまだ多数含まれるようで、ビーコンベースの 8 の値とは相当の開きがある。(一方で、8 の値には javascript オフのユーザや javascript のエラーによる数え落としが多少含まれているかもしれない。)

ちなみに、話題になったアメブロの界王拳は、RSSへのアクセスやクローラによるアクセスもカウントするという情報からすると上表の 5 あたりと推測される。一般的に言うPV値の4倍という指摘ともだいたい辻褄が合う。

セッション数を算出する際のファクター (9〜15)

同じユーザの一連のアクセスを session または visit と呼ぶ。「同じユーザの」「一連の」とさらっと一言で言っているが、これほど面倒で定義がぶれやすいものはない。
  • ログイン必須の会員制サイトであれば,「同じユーザ」からのアクセスを見分けるのは難しくないかもしれない。
  • そうでない場合はアクセス元のIP、UserAgent などを元に「同じユーザ」を推定する必要がある。
  • 企業のゲートウェイやモバイル端末の場合、多数のユーザが同じIPを共有していることがある。逆に、(外出中のノートPCからのアクセスなど) 同じユーザが複数の異なるIPから接続してくることもある。(9, 12)
  • セットアップ済みの市販PCなどの場合、皆がほとんど同じ UserAgent になる。ただ、IPとUserAgent を組み合わせるだけでも意外と正確な値が得られるようだ。(10, 13)
  • モバイルの場合は端末ID、PCの場合はサーバで専用のクッキーを発行する mod_usertrack など、ユーザ同定の精度を上げる方法はほかにもいくつかある。 (11, 14)
  • あるページにアクセスしたユーザが10秒後に別のページにアクセスすればそれは「一連の」セッションと考えるべきで、同じユーザが24時間後にまたアクセスしてきたらそれは「別の」セッションと考えるのが普通だ。この「一連の」と「別の」の閾値をどこにおくかは、決めの問題でしかない。数十分から数時間の間が空いたら「別の」セッションになると考えるのが妥当なところだろうか。google ad planner では30分としているようだ
  • 当然、この閾値を短くすればするほど見かけのセッション数は多くなる。30分と24時間では一割ほどの差がでる。(9〜11 & 12〜14)
  • リファラをみてセッションを判定する方法もある。ページAへのアクセスのあと、リファラがページAになっているアクセスがあればそれは連続したセッションであると考えられる。ただ、ブラウザがリファラを送らないこともあるし、精度の割には集計処理が複雑になるため、コストに見合わないかも。
  • また、javascriptを用いて、リンクを踏んだ瞬間 (あるいはページがアンロードされる瞬間) に「次にどのページに遷移するか」の情報をサーバへ送る手法もある。この方法だとサイト外への離脱先や、離脱の時刻まで取得できるメリットがあるが、後で述べるように「そこまでしてユーザの行動を監視するべきか」どうかも考慮する余地があるだろう。

ユニークユーザ数を算出する際のファクター (15〜17)

  • ユニークユーザ数は単純に合算できない。例えば一日目の訪問者が3人 (Aさん、Bさん、Cさん) 、二日目が2人 (Aさん、Dさん) だった場合、二日間通してのユニーク訪問者数は 3+2=5人ではなく Aさん、Bさん、Cさん、Dさんの 4人である。
  • そのため、日別ユニークユーザ数、月別ユニークユーザ数、あるページのユニークユーザ数、サイト全体のユーザ数 ... などが必要な場合はすべて別々に集計する必要がある。(日別のUUやページ別のUUを単純に加算して全体のUUとしてしまっている資料は意外に多いのではないかと思われる。)
  • 12〜14の「1日以内の同一クライアントからのリクエストを除外する」と、15〜17の「同じ日の同一クライアントからのリクエストを除外する」は、ぱっと見どちらも同じ日別UUを指しているように見えるが、実は違う。例えば同じユーザが 1日の 14:00 と2日の 08:00 にアクセスしてきた場合、前者の定義だと二度目のアクセスはカウントされないが、後者の定義だとカウントされる。(こんなちょっとした定義の差でも値が5〜6%は変わることに注目。)

上記以外のさまざまな要因

  • 「○○を除外する」と「○○のみをカウントする」の定義の違いが意外と大きな誤差の元になる。(例えば、画像へのアクセスを除外したい場合に「拡張子が.jpg .jpeg .bmp .gif .png のものを除く」と定義するか「拡張子が .html .txt 以外のものを除く」と定義するかによって集計値は変わる。前者であれば画像ファイル「test.tiff」が除外されないし、後者だと「test.shtml」ページのカウントが漏れる。)
  • 上と関連するが、PV集計の大きな誤差の要因のひとつは、バグや負荷によるトラブルである。100台のサーバに分散しているログの1つだけを取り損なったり、大量のログの負荷でバッチがこけていたり、正規表現で "\.html" と記述すべきところが ".html" になっていたり。「集計の結果100万PVでした」と言われて、その100万行の内訳をじっくりチェックする人はあまりいないので、そういった間違いは長いこと気づかれないことがある。そして数字だけが一人歩きする。
    ※実はライブドアブログについているアクセスカウンタ(javascriptビーコン)も、深夜帯のDB高負荷時にたまに数え落としが起きている。近々修正予定なので、ライブドアブログの人はPVが少し増えるかもしれない。
  • そしてやはり、最も大きな誤差要因はクローラやツールによるアクセスである。機械だけに短時間に大量の処理が可能で、誤ってカウントに含めてしまった場合のインパクトが大きい。しかも、ツールを使う側としてはなるべく普通のアクセスと区別してほしくない (ツールの種類によっては使う側にやましいところがあることも少なくない。そうでなくても、ツールとバレるとアクセスを拒否されることはしばしばある) ため、PVカウントから bot を除外する処理はいたちごっこの様相を呈する。
    たとえば、アナログな手法で人間っぽいアクセスを大量に繰り返す人達がいて、こういうのがけっこう面倒だ (「トラフィックエクスチェンジ オートサーフ」とかで検索すると色々でてくる。)
    しかし、サービス提供者としては集計スクリプトのメンテナンスにそこまでこまめに手間がかけられないのが実情だろう。気がついたら新手の bot を大量にカウントしていた ! → 媒体資料に数字書いちゃったのでいまさら訂正できません>< みたいなことはアメブロじゃなくても普通に起こり得ることだ。
  • そして、ツールによるアクセスと人間によるアクセスは、本質的にはあまり違いがない。 ブラウザだってツールだし。ユーザエクスペリエンスを忠実にデータ化したいと願うなら、サーチエンジンは javascript も flash も埋め込み画像も普通と同じように再生する方向に進化するだろう。

そもそも、サーバサイドにいる我々に分かるのは「ユーザの動向」そのものではなく、サーバへのリクエストを通して間接的に見えるユーザの痕跡だけだ。ブラウザのキャッシュやgoogleのキャッシュからページが表示された場合など、webサーバにはまったく手がかりが残らないこともある。

そして、サーバにリクエストを送って来るのはユーザ自身ではなく、あくまでブラウザや中間のキャッシュサーバなどの代理人(proxy)である。同一ユーザが別のブラウザで別の場所から (あるいはケータイとPCの両方で) アクセスした場合にそれを 2UU と数えるのか、家族で同じパソコンを交代で利用していたらそれは 1UU なのか、など、代理人越しには見えづらいことが多々ある。

ただ、まさにそのことが訪問者の匿名性の保証であり、安心感の根拠になっているのであれば、無理に深入りしないほうがお互いのためかもしれない。

そして最後にひとつ。
これだけの手間をかけなければ「正しい」PVを算出することはできないのだ。特に、サーバのアクセスログベースの集計の精度 (7) をjavascriptビーコンベースの精度 (8) に近づけるのは大変難しい。
しかも基本的に、手間をかければかけるほど、「正しい」数字に近づけば近づくほど、PV値は少なくなるのだ。わざわざ少ない値を算出するメリットが誰にもなければ「PV」は今後もいい加減な指標のままだろう。