10月 29

アクセス解析の実態

ネット業界では、ページビュー数(以下PV)やユニークユーザー数が企業やサービスの指標にされる一方で、そのアクセスを計測する方法が業界内で統一されておらず、ロボットやRSSへのアクセスもPVに加える上場企業があったり、酷いところでは画像やCSSのロード(アクセス)までをもPVに加えて水増し、バリューがあるかのように見せかけてるケースもあります(気をつけて!)。

Google Analyticsで測る

そんな中、Google Analyticsは導入が簡単・高性能、しかも無料ということでPCサイトのアクセス解析ではもはや業界標準になっていると思います。多くの人が使っているということは、例え計測方法がブラックボックスだったとしても「Google Analyticsで計測した値」同士を比較することで、相対的な数字として信頼のできる結果を導くことができます。

内部アクセスの排除

ところが、簡単に導入できる反面Google Analyticsでも設定を行わないと正確な値を取ることができません。それは、自分たちの内部アクセスを排除する設定です。

設定を知らないのか、少しでもPVを稼ぎたいのか、内部アクセスを含めてしまっているケースを多々見かけるので、啓蒙を兼ねて設定方法を書きたいと思います。

正しい戦略は正しい数字から。正しい数字は正しい設定から。

参考サイト

上記参考サイトの通りなのですが、ヘルプなのに全然優しくないのがGoogleっぽいです。

フィルタ マネージャを設定する

Google Analyticsで解析方法をカスタマイズするには、フィルタ マネージャでフィルタを設定します。トップページ右下の「フィルタ マネージャ」をクリックします。(クリックで拡大)
ga_setting01

次に「フィルタを追加」をクリックします。(クリックで拡大)
ga_setting02

以下、順次フィルタ追加画面でフィルタを設定していきます。

IPアドレスで除外する

社内からなどの内部アクセス元のIPアドレスが固定の場合や、開発環境・テスト環境のアクセス元IP
アドレスがあらかじめ分かっている場合に設定しておく方法です。

既定のフィルタ > IPアドレスからのトラフィック を設定します(クリックで拡大)
ga_setting03

上の設定画面ではIPアドレスをサブネットマスクなどを使って範囲で指定することができないので、その場合はカスタムフィルタ(ユーザーのIPアドレス)を使って正規表現で頑張る必要があります。

例えばアクセス元のIPアドレスが192.168.0.0/24だった場合は、
^192\.168\.0\.([1-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-4]))$
となります。

この正規表現を生成してくれるツールはGoogleのヘルプにあるので、それを利用しましょう。

カスタムフィルタ > ユーザーのIPアドレス を設定します(クリックで拡大)
ga_setting05

開発環境やテスト環境でのアクセスを除外する方法は、IPアドレス以外にもドメイン名でルールを決めたり(テスト環境のホスト名にはtest.example.comなどのように必ずtest.を付けるとか)、アプリケーション内でGoogle Analyticsコードを出力しないようにプログラマーが頑張ったりする方法もありますが、Google Analyticsを管理する部門と開発部門が同じとも限りませんし、変更が少なく管理が分離しやすいアクセス元IPアドレスで処理する方法がいいと思います。

クッキーで除外する

これは管理が煩雑でお勧めはできません。
アクセス元IPアドレスで除外しきれいないアクセス数が全体から見て無視できる程少なければ、IP
アドレスだけでいいと思います。

完璧主義の人や、出先の無線LANスポットやイーモバイル、iPhoneなどから無視できない程頻繁に中の人がアクセスする場合は、クッキーを利用して除外します。

原理としては、除外したいクライアント(ブラウザー)に目印となる保存期間の長いクッキーを送信しておき、そのクッキーを持っているクライアントからアクセスがあった場合に除外をします。

まず目印となるキーワードを「ユーザー定義」というフィールドに設定しておきます。ここではキーワードを「self_access」としておきます。(クリックで拡大)
ga_setting04

次にクッキーを送信する方法を用意します。

Googleのヘルプには、

<body onLoad="javascript:pageTracker._setVar('self_access');">

とbodyタグにJavascriptを埋め込んだコードを書き、除外対象と同じドメインにアップロードしてアクセスするように説明があります。

要は解析用のコードで実行している_gat._getTracker()で取り出したオブジェクト「pageTracker」内の_setVar()にキーワードを渡して実行すると、setCookie()が実行される仕組みです。
ちなみにこのクッキーは「__utmv」という名前で2年間の有効期限で発行されます。

管理が大変だというのは、除外対象のドメインごとにクッキーを発行する仕組みを用意して、さらにクライアントにアクセスさせないといけないというところです。

実践しようしたら、中の人が必ずアクセスする管理ページなどにiframeで除外対象の各ドメインにおいてあるクッキーを発行するURLを読み込ませるなどの力技になってしまいそうです。

間違って一般のユーザーがアクセスできるページでこのクッキーを発行してしまうと、アクセス数がゼロになるので慎重に。

番外編:Apacheのアクセスログで応用する

アクセス元IPアドレスやクッキーで解析結果から除外する方法は、Apacheのアクセスログにも応用できます。

この設定をすることで、access_logには内部アクセスのログは書き込まれず、内部アクセスのログはlocal_access_logへ書き出されるようになります。

# 必要なモジュール
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule log_config_module modules/mod_log_config.so

<IfModule setenvif_module>
    # アクセス元IPアドレスで判断
    SetEnvIf Remote_Addr 127.0.0.1 local_log no_log
    SetEnvIf Remote_Addr 192.168.0. local_log no_log

    # Google Analyticsで設定したCookieで判断
    SetEnvIf Cookie "__utmv=[0-9]+\.self_access" local_log no_log

    # (番外)ロボット系もこの程度の設定でだいぶ省けるんですけどね
    SetEnvIf User-Agent "[bB]ot" no_log
    SetEnvIf User-Agent "[sS]pider" no_log
    SetEnvIf User-Agent "[cC]rawler" no_log
    SetEnvIf User-Agent "[rR][sS][sS]" no_log
    SetEnvIf User-Agent "[fF]eed" no_log
</IfModule>

<IfModule log_config_module>
    CustomLog logs/access_log combined env=!no_log
    CustomLog logs/local_access_log combined env=local_log
</IfModule>

サーバーのログを見ることが多い方はこっちの方が効果です。

Tagged with:
9月 12

クラウドのホスティングサービスは、一定リソースの時間極課金+通信トラフィックの従量課金が一般的です。

CPUやメモリなどのリソースは、1%しか使わなくても100%使っても時間内の料金は同じです。
一方で通信料は使った分だけGB単位などで段階的に課金される仕組みです。

この料金体系では、なるべくリソースを使い切って、且つ通信料を抑えることが最も費用対効果のある利用方法となります。

サーバーからクライアントへのレスポンス、特にブラウザーのロードとレンダリングを高速化させるために、Yahoo!のYSlowやGoogleのPage Speedを使ってチューニングを行うのと同じようなアプローチで、なるべくCPUに仕事をさせて、トラフィックを減らしてみたいと思います。

キャッシュ機能を最大限利用する

Expires

Apacheのmod_expiresを有効にすることで、レスポンスヘッダーにExpiresフィールドが出力され、最初のアクセス以降設定した期間が経過するまでブラウザーはローカルのキャッシュを利用し続けます。
この設定は強力で、ローカルのキャッシュがなくなるか、強制リロードをしない限り、サーバーへアクセスすらしません。
(逆に、更新をかける余地のあるファイルには設定しない方がいい項目です。)

LoadModule expires_module     modules/mod_expires.so
ExpiresActive On
ExpiresByType application/javascript "access plus 1 days"
ExpiresByType application/x-javascript "access plus 1 days"
ExpiresByType text/javascript "access plus 1 days"
ExpiresByType text/css "access plus 1 days"
ExpiresByType image/jpeg "access plus 3 days"
ExpiresByType image/png "access plus 3 days"
ExpiresByType image/gif "access plus 3 days"
ExpiresByType image/x-icon "access plus 3 days"

有効期間の設定には以下の単位も利用できます。

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

Last-Modified、Etag

次に、キャッシュが切れていよいよブラウザーがアクセスをしてきた時のための設定を施しておきます。

特段設定をしないとApacheはLast-ModifiedEtagフィールドをセットしたヘッダーを送信します。
この値を受け取っているブラウザーは、Last-Modifiedの値をIf-Modified-Sinceに、Etagの値をIf-None-Matchに含めてリクエストを送信します。
受け取ったサーバーは値を比較して変更が無ければコンテンツの中身は返さず、304 Not Modifiedを応答します。

コンテンツを返さない分トラフィックは抑えられるわけですが、この二つのフィールドはコンテンツを返すか、返さないかを判断するという意味では同じで、解釈の仕様によって動きが変わってきます。

Apacheにおいては、If-Modified-SinceよりもIf-None-Matchが優先されます。
If-Modified-SinceはIf-None-Matchがない場合にだけ利用され、If-Modified-Sinceの値が同じでも、If-None-Matchの値が変更されていた場合には、コンテンツを返します。

これだけ優先されるIf-None-Matchなので、ETagの値を間違ってセットするとサーバーが毎回コンテンツを返してしまいます。
この辺りでよく問題にされるのは、負荷分散環境下で複数のサーバーが同一コンテンツを返しているような場合です。
クラウドのホスティングサービスを選択するようなケースでは、スケールアウトする仕組みが期待されることが多いので、あらかじめ設定しておくべき項目です。

Apacheがデフォルトで出力するETagが「ファイルの inode番号、ファイルサイズ、更新時刻」を元に生成するので、inode番号がサーバーによって変わってしまう環境では、せっかくIf-None-Matchを送っていても受け取るサーバーごとで比較するETagが違い、毎回無駄にコンテンツを返してしまいます。

以下のサイトに解説や実例があります。

これを回避するために、ETag自体を出力しない方法と、ETagの生成にinode番号を利用しないようにする方法と2通りあります。

ETag自体の出力をしない

FileETag None

ETagの生成にinode番号を利用しない

FileETag MTime Size

どちらにせよ、これらの設定では「最終更新日」が重要な要素になってきます。
ETagを出力しない場合はLast-Modified(最終更新日)での判定が有効になり、inode番号を利用しない場合はファイルサイズと最終更新日がベースとなったEtagでの判定になるからです。

最終更新日が全てのサーバーで同じになるように、ファイルをコピーする時、同じタイムスタンプになるように注意してコピーしなければなりません。rsyncであれば-tオプションを付けてコピーします。

ETagを出力しない場合は、内容に変更があったファイルでもタイムスタンプが同じであれば同一ファイルと見なされるリスクがあります。
inode番号を利用しないでETagを出力した場合は、その分リクエスト・レスポンスヘッダーともに微増し、トラフィックに若干影響があります。

トラフィックを抑えることが最優先であれば出力しない、ファイルの管理を厳密に行いたいのであれば出力する、ETagの設定をどちらにするかは状況によって変わってくると思います。
今回の趣旨では、ETagは出力しない方がいいということになります。

コンテンツは基本、圧縮

mod_deflateモジュールを有効にすると、設定に従ってレスポンスをgzipで圧縮して送信してくれます。
Deflateによる圧縮はCPUに働かせ、トラフィックを減らす、クラウド環境にもってこいの設定です。

LoadModule deflate_module modules/mod_deflate.so
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/javascript

Webで利用される画像フォーマットはそもそも圧縮されている場合が多いので、圧縮効率の高いテキストファイルを対象にします。(WordPressの場合、WP Super Cacheを使うことで、記事自体もgzip圧縮して送信できるようになります。)

使える外部リソースを使う

これは番外編です。
RSS、各種APIなどのWebサービスからOpenIDやOAuthなどのリモート認証、Webは外部のリソースと協調する方向へと進んでいますから、利用できるリソースをどんどん活用するのもトラフィック節約になります。
flickrYouTubeなどをホスティング的に利用するのはもちろん、JavaScriptのライブラリはGoogleのAJAX Libraries API、アバターアイコンはGravatarなど、目的に合わせて使える外部リソースを使っていきましょう。

もちろん外部リソースに依存することはリスクでもあるので、いい面ばかりでもありません。1ページに複数ドメインへのリソースがあると、名前解決に時間がかかりページのロードが遅くなるなどの問題もあります。

ご利用は計画的に。

Tagged with:
preload preload preload