※ パクレゼルヴではWeb開発エンジニアを大募集中!詳細はこちら
Home > PHP, システム, 携帯電話 > Google Analytics を携帯から使う

Google Analytics を携帯から使う  

2009/4/28 火曜日 21:49:21

こんばんは。
のびーにょです。

GoogleAnalyticsをケータイから使う

ためのクラス書きました。
探してもfunctionでしかなかったので。
あと、fopen()のタイプしかなかったので。
fopenだと繋がらなかった場合エラー出るんですよね。
なのでfsockopen()でソケット通信を利用。
繋がらなかったらそこで終了。
もしくはimgタグにして画像を読み込ませる感じでも利用できます。
参考にさせていただいたソースはfopenでPHP5で追加されたパラメータ使っています。
別に弊社もPHP5なんでかまわないんですけど、どうせなら4でも動くようにという感じにしておきました。
後色々機能追加しています。

使用サンプル

//クラス読み込み
include_once 'GoogleAnalytics.class.inc';
include_once 'googleAnalytics.conf.inc';
//Google AnalyticsのID
$GAM_id = GOOGLE_ANALYTICS_ID;
//サーバ名(ドメイン)
$domain = $_SERVER['SERVER_NAME'];
//セッションID 携帯では独自に引き継がないとできないので注意
$sess = session_id();
//ユーザ側で通知したい値
$md5_subid = md5('ユーザID等');
//GAMセット
$GAM = new GoogleAnalyticsMobile($GAM_id,$domain,$sess);
$res=$GAM->sendGoogle($md5_subid);
//IMGタグを利用する場合は以下も必要
//echo $res;

以上
googleAnalytics.conf.incには定数の定義があります。
内容は以下

設定例

//GoogleAnalyticsのID
define('GOOGLE_ANALYTICS_ID','UA-XXXXXXX-X');
//imgタグで画像を読ませるかどうか
define('GOOGLE_ANALYTICS_READIMG',FALSE);
//define('GOOGLE_ANALYTICS_READIMG',TRUE);
//ソケット通信で通信する場合のタイムアウトするまでの時間
define('GOOGLE_ANALYTICS_TIMEOUT',5);
//通信ポート
define('GOOGLE_ANALYTICS_SEND_PORT',80);
//GoogleAnalyticsへ通知するURL(変わったら変えてね)
define('GOOGLE_ANALYTICS_HOST','www.google-analytics.com');

設定はお好みでどうぞ。
GoogleAnalytics.class.incの中身は以下です。

GoogleAnalyticsMobile

/**
 * GoogleAnalytics を携帯でも利用するためのクラス
 * @auther のびーにょ
 */
class GoogleAnalyticsMobile {
  var $utmac;   //Google AnalyticsのID
  var $utmhn;   //ドメイン
  var $session;  //クッキー(セッション)
  var $random;  //ランダムな値
  var $utmn;    //ランダムな値(上のパラメータとは別の値が必要)
  var $today;   //日付
  var $header;  //送信するヘッダ
  var $res;      //送信後に取得した内容(おそらく必要なし)
  /**
   * CONSTRACTER
   * @param utmac GoogleAnalyticsのID
   * @param utmhn 測定するドメイン
   * @param session セッションID(一意に識別できるものなら何でも可)
   */
  function GoogleAnalyticsMobile($utmac,$utmhn,$session)
  {
    $this->utmac = $utmac;
    $this->utmhn = $utmhn;
    $this->session= $session;
    //intの最大値を超える数字を指定した乱数(float型になるのかな?)
    $this->utmn = rand(1000000000, 9999999999);
    //intの最大値までの乱数
    $this->random= rand(1000000000,2147483647);
    $this->set('today',time());
    $this->set('header');
  }
  /**
   * データ作成とデータ送信
   * @param uservar ユーザー識別子(カスタマID)
   * @param referer リファラ
   * @param utmp リクエストURI
   * @param utmdt ページタイトル
   * @param utmsr ディスプレイサイズ(横*縦)
   * @param utmfl Flashのバージョン
   * @param utmsc 色
   * @param utmcs 文字コード
   * @return IMGタグ OR なし
   */
  function sendGoogle($uservar=NULL
                      ,$referer=NULL
                      ,$utmp=NULL
                      ,$utmdt='-'
                      ,$utmsr='-'
                      ,$utmfl='-'
                      ,$utmsc='-'
                      ,$utmcs='UTF-8')
  {
    if(!$referer){
      $referer = $this->getReferer();
    }
    if(!$utmp){
      $utmp = $this->getRequestUri();
    }
    $today = $this->get('today');
    $host = GOOGLE_ANALYTICS_HOST;
    $sendPrm ='/__utm.gif?';
    $sendPrm.='utmwv=1'
      .'&utmn='.$this->utmn
      .'&utmhn='.$this->utmhn
      .'&utmcs='.$utmcs
      .'&utmsr='.$utmsr
      .'&utmsc='.$utmsc
      .'&utmul=ja'
      .'&utmje=0'
      .'&utmfl='.$utmfl
      .'&utmdt='.urlencode($utmdt)
      .'&utmhid=-'
      .'&utmr='.urlencode($referer)
      .'&utmp='.urlencode($utmp)
      .'&utmac='.$this->utmac
      .'&utmcc='
        .'__utma%3D'.$this->session.'.'
    .$this->random.'.'
    .$today.'.'
    .$today.'.'
    .$today.'.2%3B'
        .'%2B__utmb%3D'.$this->session.'%3B'
        .'%2B__utmc%3D'.$this->session.'%3B'
        .'%2B__utmz%3D'.$this->session.'.'
          .$today.'.2.2.'
          .'utmccn%3D(direct)%7Cutmcsr%3D(direct)'
            .'%7Cutmcmd%3D(none)%3B'
        .'%2B__utmv%3D'.$this->session.'.'
    .$uservar.'%3B';
    //IMGタグで設置する場合
    if(GOOGLE_ANALYTICS_READIMG){
      //EZWebの端末のキャッシュ対策に末尾にtimestampを付与(ランダム数字とクッキーがあるので不要かも)
      return '<img src = "http://' . $host.$sendPrm.'&'.$today.'" width="0" height="0"/>';
    }else{
      $header = $this->get('header');
      if(!$header){
        $header = $this->makeHeader();
      }
      $this->sendData($host,$sendPrm,$header);
      return ;
    }
  }
  /**
   * データ送信
   * @param host ホスト名 (example.com)
   * @param sendPrm リクエストパラメータ (/index.php?aaa=bbb)
   * @param header HTTPヘッダ(クエリ、Host、Content-Type、Content-Lengthは自動的に付与される)
   */
  function sendData($host,$sendPrm,$header)
  {
    $header = "GET ".str_replace(array("r","n"),"",$sendPrm)." HTTP/1.1\\r\\n".$header;
    $header .= "Host: ".$host."\\r\\n";
    $header .= "Connection: Keep-Alive\\r\\n\\r\\n";
    $errno='';
    $errstr='';
    //WEBサーバへ接続
    $fp = fsockopen($host
                    ,GOOGLE_ANALYTICS_SEND_PORT
                    ,$errno
                    ,$errstr
                    ,GOOGLE_ANALYTICS_TIMEOUT);
    //接続に失敗した時の処理
    if (!$fp){
      return FALSE;
    }
    //要求データ送信
    fputs($fp,$header."GET ".$sendPrm." HTTP/1.1\\r\\n");
    //応答データ受信
    $response = "";
    while (!feof($fp)){
      $response .= fgets($fp,4096);
    }
    $this->set('res',$response);
    //接続を終了
    fclose($fp);
  }
  /**
   * ヘッダ作成
   * @param lang 文字種別
   * @param ua ユーザエイジェント
   * @return header
   */
  function makeHeader($lang=null,$ua=null)
  {
    if($lang){
      $header = 'Accept-language: '.$lang."\\r\\n";
    }elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && $_SERVER['HTTP_ACCEPT_LANGUAGE']) {
      $header = 'Accept-language: '.$_SERVER['HTTP_ACCEPT_LANGUAGE']."\\r\\n";
    }else{
      $header = 'Accept-language: ja'."\\r\\n";
    }
    if($ua){
      $header .= 'User-Agent: '.$ua."\\r\\n";
    }elseif (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT']) {
      $header .= 'User-Agent: '.$_SERVER['HTTP_USER_AGENT']."\\r\\n";
    }else{
      $header .= 'User-Agent: Unknown'."\\r\\n";
    }
    return $header;
  }
  /**
   * リファラーがあれば返す。
   * @return リファラー(あれば)
   */
  function getReferer()
  {
    if(isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER']){
      return $_SERVER['HTTP_REFERER']; //referer url
    }else{
      return '-';
    }
  }
  /**
   * REQUEST_URIがあれば返す
   * @param  delPrmArr 削除するパラメータ配列
   * @return リクエストURI(あれば)
   * <pre>
   * 値までわかっている場合は配列で指定
   * EX: パラメータprmで値がvalとパラメータがprm2で値が分からない場合
   * ?prm=val&prm2=xxxxx のリクエストURI
   *   => array('prm'->'val','prm2'=>'')
   * </pre>
   */
  function getRequestUri($delPrmArr = array())
  {
    if(isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] && ($_SERVER['REQUEST_URI'] != '/')){
      $backData = $_SERVER['REQUEST_URI'];
      $flg = FALSE;
      //削除する
      foreach($delPrmArr as $key => $val){
        if($val){
          $backData = str_replace($key.'='.$val,'',$backData);
        }else{
          $backData = preg_replace("/".$key."=[^&]*&/",'&',$backData);
        }
        $flg = TRUE;
      }
      if($flg){
        $backData=str_replace('&&','&',$backData);
        $backData=str_replace('?&','?',$backData);
      }
      return $backData;
    }else{
      return '';
    }
  }
  /**
   * 自由にアクセスできるGETTER/SETTER
   * @param arg アクセスしたいパラメータ名
   * @return パラメータが保持している値
   */
  function get($arg = null)
  {
    if(!$arg){
      return null;
    }
    if(isset($this->$arg)){
      return $this->$arg;
    }else{
      return null;
    }
  }
  /**
   * SETTER
   * @param arg アクセスしたいメンバ変数名
   * @param val 格納したい値
   */
  function set($arg=null,$val=null)
  {
    $this->$arg = $val;
  }
}

携帯電話利用する場合、素直にREQUEST_URI送ってしまうと、セッションIDも送信されてしまい、正確なページ単位の集計ができません。
さらに、DoCoMoの端末のみ”guid=on”のパラメータが付いているサイトなどもあるでしょう。
また、広告コードが付与されて送信されてくるパターンもあります。
そういう場合にはgetRequestUri()メソッドを利用してREQUEST_URIを改変してセットします。
また、sendGoogle()メソッドには上記見てもわかるように色々引数を追加できます。
それも追加してみましょう。
また、makeHeader()メソッドでHTTP_USER_AGENTやHTTP_ACCEPT_LANGUAGEも変更できます。
しない場合はコールしなくても、勝手にコールされます。

以下サンプル

//クラス読み込み
include_once 'GoogleAnalytics.class.inc';
include_once 'googleAnalytics.conf.inc';
//Google AnalyticsのID
$GAM_id = GOOGLE_ANALYTICS_ID;
//サーバ名(ドメイン)
$domain = $_SERVER['SERVER_NAME'];
//セッションID 携帯では独自に引き継がないとできないので注意
$sess = session_id();
//ユーザ側で通知したい値
$md5_subid = md5('ユーザID等');

//GAMセット
$GAM = new GoogleAnalyticsMobile($GAM_id,$domain,$sess);
//リファラ取得
$ref = $GAM->getReferer();
//REQUEST_URI取得(guid,ses_id,ad_idを削除)
$reqi = $GAM->getRequestUri(array('guid'=>'ON'
                                 ,'ses_id'=>$ses_id
                                 ,'ad_id'=>''));
//ページタイトルを設定
$title = 'タイトル';
//画面幅(横*縦)
$bSize = '240*320';
//Flashのバージョン
$flash = '-';
//表示可能色数
$color=$LIB_ARR_MP['color'];
//送信データ生成&送信
$res=$GAM->sendGoogle($md5_subid
                        ,$ref
                        ,$reqi
                        ,$title
                        ,$bSize
                        ,$flash
                        ,$color);
//IMGタグを利用する場合は以下も必要
//echo $res;

これでOK
サイトの共通ファイルや、コントローラ、もしくは共通ヘッダ、共通フッタ等にセットすれば、GoogleAnalyticsがケータイでも利用できます。
ただ、注意点としては画像読み込みで利用される場合(GOOGLE_ANALYTICS_READIMG定数がTRUE)、
画像をフッターに表示させようとすると、ページ全体を読み込むまで通知されない可能性があるので、
極力ヘッダに記述した方がいいと思います。

ですが、HTMLが開始される前に表示するのは厳禁ですよ!

ただ、こちらも難点としてはDoCoMoの端末は画像が表示されるまで次の行を表示しようとしないのです。(データは取得している模様)
あまりにGoogleへの通知に時間がかかる場合等はユーザが戻る操作等を行う可能性があります。

ソケットで通知する際は定数にて接続を切る時間が設定できるので(GOOGLE_ANALYTICS_TIMEOUT定数)、ユーザーがせっかちな場合等はここを1秒等に設定すればましかもしれません。

のびーにょ PHP, システム, 携帯電話