WordPress から Google APIs Client Library for PHP を使用してアナリティクスデータへアクセスする方法

WordPressで人気記事ランキングを表示するためにアナリティクスデータへアクセスするプログラムについて紹介します

このプログラは以前作成した GA-PVcounter プラグインのコードを一部修正して、Celtis-one テーマに組み込んだものです

2014/11/18 追記

Celtis-one テーマに機能を持たせていたのですが、現在はプラグイン化して celtispack プラグインへ機能を移しています

プログラムも一部修正していますので参考程度で御覧ください

ちなみに、プラグインへ移したコードは、WordPress Plugin : Celtispack ページからダウンロードすることが出来ますので、modules/GA-popular-posts フォルダのファイルを参照して下さい

 

Oauth認証やアナリティクスデータへのアクセスについて下記のような記事も以前に書いていますので合わせて参考にして頂ければと思います (^^)

 一部内容が重複しますが、ポイントを整理しながら紹介して行きます

ライブラリ取得

Google APIs Client Library for PHP リンク先ページに移動してライブラリファイルを取得します

取得したライブラリを解凍して、celtisone テーマの include フォルダの下に配置しました

GoogleAPIsClientLibrary

アナリティクスデータアクセス

Webアプリケーションがデータ・アクセスするには認証を受ける必要があります

アナリティクスデータアクセスに必要なコード

  • クライアントID
  • クライアントシークレット
  • リダイレクトURI

クライアントID,クライアントシークレットは、Webアプリケーションがアクセス許可を受けるためのユーザー名とパスワードに相当し、Google Cloud Console から作成します

手順は Google Analytics データを使ったページビューと人気記事ランキング を参照して下さい

 

リダイレクト URI は、google でのOAuth 認証後にリダイレクトして表示されるページを指定するので、ここでは、テーマ設定画面 admin_url(‘themes.php?page=theme_options’) としています

これらのコードを使って OAuth 認証が成功すれば、アクセストークンを取得することが出来ます

アクセストークンを用いて、アナリティクスのビューIDを取得し、そのビューIDを使って様々なアナリティクスデータへアクセスすることが出来るようになります

プログラムについて

今回作成したプログラムについて紹介していきます

構成

  • Oauth認証開始
  • Oauth 認証アクセストークン取得
  • アナリティクスのビューID取得
  • Oauth 認証アクセストークン更新
  • アナリティクスデータ取得
  • Oauth 認証アクセストークン解除

 Oauth認証開始

今回は jQuery の Dialog, Ajax を使い入力されたクライアントID,クライアントシークレットを取得します

ダイアログのフォーム

テーマ設定用処理ファイル(theme-options.php)にダイアログ用のフォームを用意します

    <div id="login-dialog" title="Google Analytics アクセス認証" style="display : none;">
        <form>
            <div  style="margin: 20px;">
                <p><?php _e( '認証準備 : WordPress からアナリティクスデータへのアクセスは、クライアントIDを作成して認証を行う必要があります', 'celtisone' ); ?></p>
                <table class="form-table">
                    <tr valign="top">
                        <td><?php _e('Step1', 'celtisone'); ?></td>
                        <td><?php _e('<a href="https://cloud.google.com/console" target="_blank">Google Cloud Console </a> サイトをブラウザの新しいウィンドウで開きます ', 'celtisone'); ?></td>
                    </tr>
                    <tr valign="top">
                        <td><?php _e('Step2', 'celtisone'); ?></td>
                        <td><?php _e('プロジェクトを作成します。(Ref. <a href="https://developers.google.com/console/help/new/" target="_blank">Google Developers Console Help</a>)', 'celtisone');  ?>
                            <p><?php _e('SMSの確認画面が表示された場合は、携帯のメールで確認処理を行います', 'celtisone'); ?></P>
                        </td>
                    </tr>
                    <tr valign="top">
                        <td><?php _e('Step3', 'celtisone'); ?></td>
                        <td><?php _e('API と認証 [API] 画面を開き、Analytics API Service の Status を ON に設定します', 'celtisone'); ?></td>
                    </tr>
                    <tr valign="top">
                        <td><?php _e('Step4', 'celtisone'); ?></td>
                        <td><?php _e('API と認証 [認証情報] 画面を開き、OAuth 新しいクライアントIDを作成 ボタンをクリックします', 'celtisone'); ?>
                            <p><?php _e('ウェブアプリケーションを選択、サイト名とリダイレクトURIを設定します', 'celtisone'); ?></P>
                            <p><?php  _e("リダイレクトURIへは、下記 URI をコピーして貼り付けて下さい", 'celtisone');  ?></p>
                            <p><mark><?php  echo $access['redirect'];  ?></mark></p>
                        </td>
                    </tr>
                    <tr valign="top">
                        <td><?php _e('Step5', 'celtisone'); ?></td>
                        <td><?php _e('API と認証 [同意画面] 画面を開き、認証時に表示される画面の設定を行います', 'celtisone'); ?>
                            <p><?php  _e("サービス名に Celtis-one アナリティクスデータ・アクセス と設定します", 'celtisone');  ?></p>
                        </td>
                    </tr>
                </table>
                <table class="form-table">
                    <tr valign="top">
                    <td>
                    <fieldset>
                        <?php _e('認証 : 作成したクライアントID, シークレットコードを入力して、アクセス認証を行います', 'celtisone');  ?>
                        <br />
                        <label for="clientid">クライアントID</label>
                        <br />
                        <input type="text" size="65" name="clientid" id="clientid" value="<?php echo $access['clientid']; ?>" class="text ui-widget-content ui-corner-all" />
                        <br />
                        <label for="clientsecret">クライアントシークレット</label>
                        <br />
                        <input type="text" size="65" name="clientsecret" id="clientsecret" value="<?php echo $access['clientsecret']; ?>" class="text ui-widget-content ui-corner-all" />
                        <br />
                        <p><?php _e( '認証が成功したら、次回以降は保存したトークンにより自動的に認証を行います', 'celtisone' ); ?></p>
                        <p><?php _e( '人気記事ウィジェットを使い、アナリティクスから取得したページビューによる人気記事が表示出来ます', 'celtisone' ); ?></p>
                    </fieldset>
                    </td>
                    </tr>
                </table>
            </div>
        </form>
    </div>   

クライアントID作成

ダイアログにクライアントID,クライアントシークレットのコードを入力すると jQuery Ajax を使い入力されたコードをPHP側へPOSTします

PHP側の設定

テーマ設定画面で Ajax 処理の登録を行います

wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'jquery-ui-core' );
wp_enqueue_script( 'jquery-ui-dialog' );
wp_enqueue_script ( 'GAoauth', get_template_directory_uri() . '/js/ga-oauth.js', array('jquery', 'jquery-ui-dialog'));  
wp_localize_script( 'GAoauth', 'GAoauth_ajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
wp_enqueue_style ( 'wp-jquery-ui-dialog');

wp_localize_script がポイントです。JQuery 側で使用するグローバル変数を設定できます

引数の2番目 ‘GAoauth_ajax’ が jQuery 側での変数名となり、3番目の連想配列 array( ‘ajaxurl’ => admin_url( ‘admin-ajax.php’ ) ) が json データに変換され var GAoauth_ajax に代入されます

ここで渡している admin-ajax.php が ajax のPOST先 URLとなります

jQuery 側の処理
  • 設定画面の認証ボタン(ga-login)をクリックするとダイアログが表示されます
  • ダイアログのアクセス認証ボタンがクリックされるとクライアントID,シークレットデータが入力されているかチェックします
  • ajaxを使いクライアントID,シークレットデータをPOSTします

ここでは ajax の処理がポイントです
ちょっとした仕掛けを施すことで、通信先のURLで実行させる専用のPHPファイルを用意することなく、関数を指定出来るようになります (^^)

データのPOST先URLに先ほど wp_localize_script で指定した GAoauth_ajax.ajaxurl をセットします

次にデータとして clientid, clientsecret をセットするのですが、そのまえに記述している “action” : “GA_login” が重要です

GA_login というキーワードがWordPress側での受信関数を特定するためのコードとなります

jQuery(function($) {  
    var cid = $( "#clientid" ),
    csecret = $( "#clientsecret" ),
    allFields = $( [] ).add( cid ).add( csecret ),
    tips = $( ".validateTips" );
    
    function updateTips( t ) {
        tips
            .text( t )
            .addClass( "ui-state-highlight" );
        setTimeout(function() {
            tips.removeClass( "ui-state-highlight", 1500 );
        }, 500 );
    }
    
    function checkLength( o, n ) {
        if ( o.val().length == "" ) {
            o.addClass( "ui-state-error" );
            updateTips(n + "は入力されていません");
            return false;
        } else {
            return true;
        }
    }

    function post_clientdata(cid, csecret){
        $.ajax({
            type: 'POST',
            url: GAoauth_ajax.ajaxurl,
            data: {
                "action" : "GA_login",
                "clientid" : cid,
                "clientsecret" : csecret
            },
            dataType: 'json',
            success: function(response, dataType)
            {
               var url = response;
               window.location.href = url;
                //alert('OK');
            },
            error: function(XMLHttpRequest, textStatus, errorThrown)
            {
                //alert('Error : ' + errorThrown);
            }
        });
        return false;
    };
    
    $( "#login-dialog" ).dialog({
        dialogClass : 'wp-dialog',
        modal       : true,  // モーダル表示
        autoOpen    : false, // 自動オープンしない
        resizable   : false, // リサイズしない
        draggable   : false, // ドラッグしない
        height      : 740,
        width       : 700,
        buttons     : {  
            "アクセス認証": function() {
                var bValid = true;
                allFields.removeClass( "ui-state-error" );
                
                //入力があるかないかだけチェック
            bValid = bValid && checkLength( cid, "クライアントID" );
            bValid = bValid && checkLength( csecret, "クライアントシークレット" );
                if ( bValid ) {
                    post_clientdata(cid.val(), csecret.val());
                    $('#login-dialog').dialog( "close" );
                }
            },
            "キャンセル": function() {  
                $('#login-dialog').dialog('close');  
            }  
        },  
        close: function() {
            allFields.val( "" ).removeClass( "ui-state-error" );
        }
    });

    $("#ga-login").click(function(event) {  
        event.preventDefault();  
        $('#login-dialog').dialog('open');  
    });
});

それでは、WordPress側の受信関数について見ていきます

Ajax のデータ受信関数

“GA_login ” というキーワード文字列と組み合わせたアクションフックを作成して、受信関数 celtisone_ga_login() を登録します

登録は、ログインユーザー(wp_ajax_ …)とログインしていないユーザー(wp_nopriv_ajax_ …)用に分かれています

  • wp_ajax_nopriv_GA_login
  • wp_ajax_GA_login

今回は、管理画面だけの処理なので wp_ajax_GA_login でけでOKです

POSTデータ中の action と キーワードが、送信先の admin-ajax.php で処理され、do_action によりアクションフックに登録されている wp_ajax_GA_login  にフックされ celtisone_ga_login 関数が実行されます

従って、action とキーワードを記述しないと受信されないので注意です (^^)

//Google Analytics アクセス認証開始
function celtisone_ga_login() {
    global $ga_pvpopular;

    if(!empty($ga_pvpopular)){
        if(isset($_POST['clientid']) && isset($_POST['clientsecret'])){
            $access = $ga_pvpopular->gaccess;
            $access['clientid'] = stripslashes($_POST['clientid']);
            $access['clientsecret'] = stripslashes($_POST['clientsecret']);
            update_option('ga_pvpopular', $access );

            $client = $ga_pvpopular->client_create($access);
            if(!empty($client)){
                $authUrl = $client->createAuthUrl();
                if(!empty($authUrl)){
                    $ajaxdata = array( $authUrl);
                    echo json_encode($ajaxdata), PHP_EOL;
                    exit;    
                }
            }
        }
    }
}
add_action('wp_ajax_GA_login',  'celtisone_ga_login');

celtisone_ga_login 関数の処理

  • 受信したクライアントID,シークレットを使いクライアントオブジェクトを作成します
  • OAuth認証用のコードを作成して jQuery ajax にそのデータを送り返します

クライアントオブジェクトは、データにアクセスする前には、必ず作成する必要があります

//クライアントインスタンスの作成
public function client_create(&$access)
{
    if(!class_exists('Google_Client', FALSE)) { 
        require_once ( get_template_directory() . '/includes/google-api-php-client/src/Google_Client.php' );
    }
    if(!class_exists('Google_AnalyticsService', FALSE)) { 
        require_once ( get_template_directory() . '/includes/google-api-php-client/src/contrib/Google_AnalyticsService.php' );
    }
    $client = new Google_Client();
    $client->setApplicationName('Google Analytics Popular posts widget');
    $client->setClientId($access['clientid']);
    $client->setClientSecret($access['clientsecret']);
    $client->setRedirectUri($access['redirect']);
    $client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
    $client->setUseObjects(true);
    return $client;
}

 jQuery ajax レスポンス受信

次に ajax 側の success 処理でレスポンスデータとして送られてきたURLデータを取得して、リダイレクトします

最初はPHP側で OAuth認証用コードを作成した時に, header関数でリダイレクトしようとしたのですが、うまく行かなかったのでURLデータを返信して、jQuery 側からリダイレクトさせるようにしました (^_^;)

Oauth 認証アクセストークン取得

ここまで正しく処理されると承認の為の確認ダイアログが表示されます

‌認証同意画面

アクセスを承認すると google 側からアクセストークンがリダイレクト先に送られてきます

アクセストークンは、 $_GET[‘code’] にセットされてきます

class GA_PVpopular {

    public $gaccess = null;

    public function __construct() {
        $default = array( 'clientid' => '', 'clientsecret' => '', 'token' => '', 'pid' => '', 'pname' => '', 'website' => '', 'day' => '', 'time' => '', 'result' => null  );
        $default['redirect'] = admin_url('themes.php?page=theme_options');
        $access = wp_parse_args( (array)get_option('ga_pvpopular'),  $default);

        //指定間隔(分)以上経っている場合のみ有効
        $queryfg = false;
        if (!empty($access['token']) && !empty($access['pname'])) {
            $now = strtotime("now");
            if(empty($access['time']) || ( $access['time'] < $now))
                $queryfg = true;
        }
        $requri = $_SERVER['REQUEST_URI'];
        if( (!is_admin() && $queryfg) || stripos($requri, 'theme_options' ) !== false ){
            //通常のアナリティクスアクセスまたは、テーマ設定画面へのリダイレクト
            $client = $this->client_create($access);
        }

        if(is_admin()) {
            if (!empty($client) ) {
                if (empty($access['token']) ) {
                    // oauth 認証アクセストークン取得
                    if (isset($_GET['code'])) {
                        $client->authenticate();
                        $access['token'] = $client->getAccessToken();
                        update_option('ga_pvpopular', $access );
                        header('Location: ' . $access['redirect']);
                        exit;
                    }
                }
                else if (empty($access['pid']) || empty($access['pname'])) {
                    //プロファイル取得(設定からビューID変更時は再取得)
                    $this->ga_getprofile($access, $client);
                }
            }
        }
        else {            
            if($queryfg){
                if (!empty($client) && !empty($access['token']) && !empty($access['pname'])) {
                    $result = $this->ga_getpopular($access, $client);
                    if(!empty($result)) {
                        $access['result'] = $result;
                        //問い合わせインターバル時間更新と人気記事ウィジェットキャッシュクリア
                        $access['time'] = strtotime( "now + 15 min");
                        update_option('ga_pvpopular', $access );
                        delete_transient( 'celtisone_popular_widget' );
                    }
                }
            }
        }

  $client->authenticate(); で承認作業を行い、accessToken を所得したら、update_option 関数でデータベースへ保存してから、ページを再読み込みさせます

アナリティクスのビューID取得

次にアクセストークンを使用してアナリティクスサービスへアクセスしてビューIDを取得します

//アナリティクスデータのプロファイル(ビューID)を取得(デフォルトは最初のID)
public function getGAviewid(&$analytics, $changepid = '') 
{
    //アナリティクス アカウント情報(アカウントID)  
    $accounts = $analytics->management_accounts->listManagementAccounts();
    if (count($accounts->getItems()) > 0) {
        $acitems = $accounts->getItems();
        foreach ($acitems as $acitem) {
            $accountId = $acitem->getId();

            //アナリティクス ウェブプロパティ情報(ビューID UA-xxxxxxxx-x)
            $webproperties = $analytics->management_webproperties->listManagementWebproperties($accountId);
            if (count($webproperties->getItems()) > 0) {
                $wpitems = $webproperties->getItems();
                foreach ($wpitems as $wpitem) {
                    $webpropertyId = $wpitem->getId();

                    //アカウントIDとビューIDからプロファイル情報取得(ビューID)
                    $profiles = $analytics->management_profiles->listManagementProfiles($accountId, $webpropertyId);
                    if (count($profiles->getItems()) > 0) {
                        $pfitems = $profiles->getItems();
                        if(empty($changepid))   //IDが未指定なら最初の情報
                            return $pfitems[0];
                        else {                  //指定ビューIDと照合
                            foreach ($pfitems as $pfitem) {
                                if($pfitem->getID() === $changepid )
                                    return $pfitem;
                            }
                        }
                    }
                }
            }
        }
    } 
    return null;
}

//アナリティクス profile(ビューID) 取得
public function ga_getprofile(&$access, $client)
{
    //トークンの期限チェック
    $client->setAccessToken($access['token']);
    $token= json_decode($access['token']);
    $now = strtotime("now");
    if($now - 60  > $token->created + $token->expires_in) {
        $client->refreshToken($token->refresh_token);
        $access['token'] = $client->getAccessToken();
        update_option('ga_pvpopular', $access );
    }
    if(!empty($access['token'])) {
        $analytics = new Google_AnalyticsService($client);
        $profile = $this->getGAviewid($analytics, $access['pid']);
        if (!empty($profile)) {
            $access['pid']     = $profile->getID();
            $access['pname']   = $profile->getName();
            $access['website'] = $profile->getWebsiteUrl();
            update_option('ga_pvpopular', $access );
        }
    }
}

ビューIDを取得するには、アカウント情報、プロパティ情報、ビュー情報と順番に問い合わせて取得していく必要があります

プログラムでは、最初に見つけたビューIDを取得していますが、複数のビューIDを使用している場合等では、テーマ設定画面からビューIDを変更できるようにしています

これでようやくアナリティクスデータを取得する為の準備が完了しました (^^)

Oauth 認証アクセストークン更新

その前に、アクセストークンには有効期限があります(3600秒?)

従って、データアクセス時には、有効期限を調べ必要なら更新してからデータにアクセスするようにします

ここでは、問い合わせ前に有効期限を調べて、有効期限が60秒以上残っていなければ、アクセストークンを更新して保存しています

$client->setAccessToken($access['token']);
$token= json_decode($access['token']);
$now = strtotime("now");
if($now - 60  > $token->created + $token->expires_in) {
    $client->refreshToken($token->refresh_token);
    $access['token'] = $client->getAccessToken();
    update_option('ga_pvpopular', $access );
}

アナリティクスデータ取得

いよいよアナリティクスデータを取得してみます

下記コードで指定期間のページビュー数順の人気記事を取得することが出来ます

//指定期間の人気記事リスト
public function getPopularposts(&$analytics, $pid, $sday, $eday, $count, $pvsum=0) 
{
    $ids = 'ga:' . $pid;            // プロファイル(ビューID)
    $start_date = $sday->format("Y-m-d");
    $end_date   = $eday->format("Y-m-d");
    $metrics = 'ga:pageviews';      // メトリクス
    $dimensions = 'ga:pageTitle,ga:pagePath';
    $sort = '-ga:pageviews';        // ソート項目, - をつけると降順
    $max_results = $count;          
    $optParams = array('dimensions' => $dimensions, 'sort' => $sort, 'max-results' => $max_results);
    $ptitle = $analytics->data_ga->get($ids, $start_date, $end_date, $metrics, $optParams);

    $ttldata = array();
    if(!empty($ptitle)){
        if (count($ptitle->getRows()) > 0) {
            $rows = $ptitle->getRows();
            $headers = $ptitle->getColumnHeaders();
            $results = array();
            foreach( $rows as $num1 => $row ) {
                foreach($headers as $num2 => $header ) {
                    $results[ $num1 ][ $header->name ] = $row[ $num2 ];
                }
            }
            foreach( $results as $result ) {
                $rate      = ($pvsum > 0) ? (int)($result[ 'ga:pageviews' ] * 100 / $pvsum):('');
                $ttldata[] = array('url' => $result[ 'ga:pagePath' ], 'title' => $result[ 'ga:pageTitle' ], 'pv' => $result[ 'ga:pageviews' ], 'rate' => $rate);
            }
        }
    }
    $getdt['popular'] = $ttldata;
    return $getdt;
}

アナリティクスデータに関しては、この辺りを参考にして下さい

アナリティクスの世界は奥が深いです (^^)

Oauth 認証アクセストークン解除

アナリティクスデータへのアクセスを解除したい場合は、テーマ設定画面から解除します

認証開始時と同様に jQuery の Dialog, Ajax を用いて行います

その辺りの処理は、ここでは割愛しますので、ソースコードを参照して頂ければと思います

だいたいこんな感じで認証からデータアクセスまで行うことが出来るようになります

 

実際に動作させるには

2014/11/18 追記

ここで紹介しているプログラムは一部修正してプラグイン化しています

プログラムは、WordPress Plugin : Celtispack ページからダウンロードすることが出来ますので、modules/GA-popular-posts フォルダのファイルを参照して下さい

なかなかコードを見ただけではイメージが湧きにくいかと思いますが、ローカル環境にWordPressを構築して実際に動作を確認することが出来ます。

※ローカル環境からのアクセスには、ローカル用のクライアントIDを別に作成する必要があります

NetBeans等で実際に動作させて見ることでいろいろ素敵なアイデアが湧いてくるかも知れません (^^)

では

 

関連コンテンツ


まとめ記事紹介

search star user home refresh tag chevron-left chevron-right exclamation-triangle calendar comment folder thumb-tack navicon angle-double-up angle-double-down angle-up angle-down quote-left googleplus facebook instagram twitter rss