プログラミング言語や環境設定を中心としたパソコン関連の技術メモです。
主にシステム開発中に調べたことをメモしています。TIPS的な位置付けで、気が向いたときにちまちま更新していきます。
JavaScriptを無効にしているホームページ閲覧者のアクセス数をカウントする。
結論から書くと

1.noscriptタグとiframeを組み合わせて取得する
(1)「<noscript>~</noscript>」タグの中に「<iframe></iframe>」を設定する
(2)「<iframe></iframe>」の中でアクセス数カウント用のスクリプトを呼び出す
(3)アクセス数カウント用のスクリプトでアクセス数を取れば、それがJavaScript無効者のアクセス数

2.noscriptタグとimgタグを組み合わせて取得する
(1)「<noscript>~</noscript>」タグの中に「<img src="~">」を設定する
(2)imgタグのsrcとしてアクセス数カウント用のスクリプトを指定する
(3)アクセス数カウント用のスクリプトでアクセス数を取れば、それがJavaScript無効者のアクセス数

3.全アクセス数とJavaScript有効者のアクセス数を取得して差を取る
(1)サーバサイドでアクセス数を取る(全ユーザのアクセス数)
(2)画面ロード時にJavaScriptの非同期処理でアクセス数カウント用のスクリプトを呼び出す
(3)アクセス数カウント用のスクリプトでアクセス数を取る(JavaScript有効者のアクセス数)
(4)「(1)」と「(3)」の差を取れば、それがJavaScript無効者のアクセス数

のどれかで良いんじゃないでしょうか。
個人的には「3.」が一番正統派な気はしますけどね。

それでは詳細を書いていきます。

とあるお客さまから「JavaScriptを無効にしてる人ってどれくらいいるんだろうね?」と訊かれました。
そのお客さまのWebサイトではGoogle アナリティクスを導入しているのですが、
JavaScriptを無効にしているとカウントされないことをどこかで耳にしたようです。

ちっ、余計な知恵をつけやがって(-。-)ぼそっ

雑談だったこともあり、話はそのまま別の話題に移ったのですが、
知的探究心がむくむくと湧きあがってきました。

JavaScriptを無効にしているホームページ閲覧者のアクセス数、どーやってカウントしようね(--?

ほんで、頭の体操代わりに考えてみて出てきた案が以下の3つです。

1.noscriptタグとiframeを組み合わせて取得する
2.noscriptタグとimgタグを組み合わせて取得する
3.全アクセス数とJavaScript有効者のアクセス数を取得して差を取る

一つずつ順番に見ていきましょう。

1.noscriptタグとiframeを組み合わせて取得する

具体的な手順は

(1)「<noscript>~</noscript>」タグの中に「<iframe></iframe>」を設定する
(2)「<iframe></iframe>」の中でアクセス数カウント用のスクリプトを呼び出す
(3)アクセス数カウント用のスクリプトでアクセス数を取れば、それがJavaScript無効者のアクセス数

です。

サンプルはこちらφ(--)

■test.html
<html>
<head></head>
<body>

ほげほげ、うんちゃらかんちゃら

<noscript>
    <iframe src="test_sub.php"></iframe>
</noscript>


</body>
</html>

■test_sub.php
<?php

    //アクセス数ファイル名
    $cntFileName = "cnt_nojs.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    $cnt++;

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

?>

JavaScript無効時には「<noscript>~</noscript>」の中が動いて
「test_sub.php」が呼ばれます。
JavaScriptを有効にしているときは「<noscript>~</noscript>」の中が解釈されないので
「test_sub.php」は呼ばれません。
あとは「test_sub.php」のアクセス数をカウントすれば、
それがJavaScriptを無効にしている人のアクセス数です。

ちなみに、サンプルなので排他制御だとかエラー処理だとかは一切気にしていません。
実際にお仕事でやる人は、いろいろ考えてあげてくださいね。

このやり方で、一応JavaScriptを無効にしてる人のアクセス数は取れました。

でも個人的にiframeを使うのって抵抗があるんですよね。
あまり良い話も聞かないし、一般公開するサービス向けでは無いかなぁ、と
試したあとにうだうだ考えていたところで、ふと気づきました。

別にiframeにしなくて、いーじゃん(-A-)

そんな経緯で生まれたのが

2.noscriptタグとimgタグを組み合わせて取得する

です。
具体的な手順は

(1)「<noscript>~</noscript>」タグの中に「<img src="~">」を設定する
(2)imgタグのsrcとしてアクセス数カウント用のスクリプトを指定する
(3)アクセス数カウント用のスクリプトでアクセス数を取れば、それがJavaScript無効者のアクセス数

となります。

ご存知の方も多いとは思いますが、画像を表示させるimgタグ、
あいつで指定できるファイルって別に画像ファイルである必要は無いのですよ。
その気になれば、.phpでも.txtでも.htmlでも指定はできます。指定はね。
アクセスログ記録用のスクリプトさえ呼び出せれば形はどーでも良いので
iframeじゃなくて、画像として呼び出してやろう。そっちの方がまだ気分的に抵抗は無いしね。

という経緯で作ったのがこちらφ(--)

■test2.html
<html>
<head></head>
<body>

ほげほげ、うんちゃらかんちゃら

<noscript>
    <img src="test2_sub.php">
</noscript>

</body>
</html>

■test2_sub.php
<?php

    //アクセス数ファイル名
    $cntFileName = "cnt_nojs.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    $cnt++;

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

    //画像の作成
    $img = imagecreatetruecolor(1, 1);
    $backGroundColor = imagecolorallocate($img, 255, 255, 255);
    imagefill($img , 0 , 0 , $backGroundColor);


    //画像出力
    header("Content-type: image/png");
    header("Cache-control: no-cache");
    imagepng($img);

    //後始末
    imagedestroy($img);
?>

「test2.html」では、画像として「test2_sub.php」を指定しています。
「test2_sub.php」では、アクセスログを記録したあと、縦横1ピクセルの白色画像を返します。
縦横1ピクセルの白色画像だとスパムっぽいですが、普通の画像を返すようにすれば
iframeよりは正統派っぽいのではないでしょうか。

これで良いかなーと思ったのですが、せっかくだからもう一個くらい考えてみよっかな~
「<noscript>~</noscript>」タグ無しでもできないかな~と考えていて思いついたのが

3.全アクセス数とJavaScript有効者のアクセス数を取得して差を取る

です。
具体的な手順は

(1)サーバサイドでアクセス数を取る(全ユーザのアクセス数)
(2)画面ロード時にJavaScriptの非同期処理でアクセス数カウント用のスクリプトを呼び出す
(3)アクセス数カウント用のスクリプトでアクセス数を取る(JavaScript有効者のアクセス数)
(4)「(1)」と「(3)」の差を取れば、それがJavaScript無効者のアクセス数

となります。

これは「パンが無いならケーキをお食べ」をヒントに生み出しました。ウソだけど。
「JavaScript無効者のアクセス数が取れないなら取らなければいーじゃん」な発想です。

全体のアクセス数はサーバ側で取れるでしょー
JavaScriptを有効にしている人のアクセス数はGoogleアナリティクスを使っても良いし
普通に自分で実装しても良いけど、余裕で取れるでしょー

じゃあ、その差を取ればJavaScript無効者のアクセス数になるじゃん(--)☆

というわけで、できあがったのがこちらφ(--)

■test3.php
<?php

    //アクセス数ファイル名
    $cntFileName = "cnt_all.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    $cnt++;

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

?>

<html>
<head>
    <script src="./jquery-1.7.2.min.js"></script>

    <script type="text/javascript">
    <!--
    $(document).ready(function(){
        $.ajax({
            url: "test3_sub.php",
            cache: false
        });
    });


    //-->
    </script>

</head>
<body>

<div id="result">ほげほげ、うんちゃらかんちゃら</div>

</body>
</html>

■test3_sub.php
<?php

    //アクセス数ファイル名
    $cntFileName = "cnt_js.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    $cnt++;

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

?>

まず「test3.php」で全体のアクセス数を「cnt_all.txt」に記録しています。
次に画面ロード時に

$.ajax({
    url: "test3_sub.php",
    cache: false
});

で「test3_sub.php」を呼び出しています。
最後に「test3_sub.php」でJavaScript有効者のアクセス数を「cnt_js.txt」に記録しています。
JavaScriptを無効にしている場合は、ロード時の処理が動かないので
「test3_sub.php」が呼び出されないってな理屈です。

あとは「cnt_all.txt」と「cnt_js.txt」の差を取れば、
JavaScript無効者のアクセス数が分かりますよ。

他にも考えればいろいろありそうですが、今回はここまでにしておきます。

そんな感じ\(--)/

※2014/07/13追記:クローラの除外方法
何人かの方から「クローラさんのことを考慮してあげないと……」とのご指摘をいただきました。

ふっ(--)☆
スーパーエンジニアの私がそんな初歩的なことを考慮していないとでも?

……(--)

全然考えていませんでした。
ご指摘ありがとうございますm(__)m

5分くらいで考えて間に合わせで追加したサンプルですが、
例えばこんな感じで如何でしょう?φ(--)

■util.php(クローラ判定用の関数)
<?php

class Util {
    /* クローラ判定 */
    static public function isBot(){
        //クローラな判定になるユーザエージェント
        //ここに除外対象を追加する
        $botList = array(
            'Googlebot',    //Google!
            'Slurp',        //Yahoo!
            'bingbot',        //bing!
            'Spider',        //なんかいろいろ
            'bot',            //なんかいろいろ
            'crawler',        //なんかいろいろ
        );

        //ユーザエージェント取得
        $ua = $_SERVER['HTTP_USER_AGENT'];

        //クローラ判定
        foreach($botList as $value){
            if(strpos($ua, $value) !== false){
                //botだよ
                return true;
            }
        }

        //botじゃないよ
        return false;
    }
}

1.noscriptタグとiframeを組み合わせて取得する
■test_sub.php
<?php

    //util.phpインクルード
    require_once(dirname(__FILE__) ."/util.php");


    //アクセス数ファイル名
    $cntFileName = "cnt_nojs.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    if(Util::isBot() === false){
        $cnt++;
    }

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

?>

2.noscriptタグとimgタグを組み合わせて取得する
■test2_sub.php
<?php

    //util.phpインクルード
    require_once(dirname(__FILE__) ."/util.php");


    //アクセス数ファイル名
    $cntFileName = "cnt_nojs.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    if(Util::isBot() === false){
        $cnt++;
    }

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

    //画像の作成
    $img = imagecreatetruecolor(1, 1);
    $backGroundColor = imagecolorallocate($img, 255, 255, 255);
    imagefill($img , 0 , 0 , $backGroundColor);


    //画像出力
    header("Content-type: image/png");
    header("Cache-control: no-cache");
    imagepng($img);

    //後始末
    imagedestroy($img);
?>

3.全アクセス数とJavaScript有効者のアクセス数を取得して差を取る
■test3.php
<?php

    //util.phpインクルード
    require_once(dirname(__FILE__) ."/util.php");


    //アクセス数ファイル名
    $cntFileName = "cnt_all.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    if(Util::isBot() === false){
        $cnt++;
    }

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);

?>

<html>
<head>
    <script src="./jquery-1.7.2.min.js"></script>

    <script type="text/javascript">
    <!--
    $(document).ready(function(){
        $.ajax({
            url: "test3_sub.php",
            cache: false
        });
    });

    //-->
    </script>

</head>
<body>

<div id="result">ほげほげ、うんちゃらかんちゃら</div>

</body>
</html>

■test3_sub.php
<?php

    //util.phpインクルード
    require_once(dirname(__FILE__) ."/util.php");


    //アクセス数ファイル名
    $cntFileName = "cnt_js.txt";

    //アクセス数ファイルがあれば前回数値取得。無ければ0
    if(file_exists($cntFileName)){
        $cnt = file_get_contents($cntFileName);
    }else{
        $cnt = 0;
    }

    //アクセス数カウントアップ
    if(Util::isBot() === false){
        $cnt++;
    }

    //アクセス数保存
    file_put_contents($cntFileName, $cnt);
?>

util.phpに書いたUtilクラス内の関数「isBot()」でクローラかどうかの判定をしています。
ぶっちゃけ、ただユーザエージェントを比較してクローラと合致したらはじいてるだけです。
IPアドレスとかブラウザの種類とか、比較対象はお好みでどうぞ。
きっちりやりたいなら、IPアドレスとユーザエージェントの複合ですかね(--?

カッコつけて処理を外部ファイルに分けて書きましたが、
これくらいの規模なら、ベタ書きでも問題無いカモしれません。

取りあえずは、これでクローラさんを除外できるんじゃないかな~と思っていますが、
考慮漏れとかあったら、ごめんなさいm(__)m
スポンサーリンク
 
このエントリーをはてなブックマークに追加 

category:● PHP  thema:パソコンな日々 - genre:コンピュータ  Posted by ササキマコト 

  関連記事