Google Analyticsのデータからアクセスランキングを生成するPerlスクリプト

2009年9月20日

当ブログ「Publickey」でアクセスランキングの表示を始めました。そのために作成したPerlのコードを、せっかくなので公開します。

作成したのは、Google AnalyticsからAPI経由でランキング情報を取得して、それをHTML形式で出力するPerlのコードです。

この方法が優れている点は、統計処理済みのランキング情報をGoogle Analyticsから取得するためWebサーバにほとんど負荷がかからない点です。Perlのコードもシンプルで導入は容易だと思います。

コードは、「Using Perl for Google Analytics API « Patrick Hartman's Log」を基に、不要な部分の削除や変更を行ってシンプルにし、HTMLの出力部分などを追加したものです。ただし僕はPerlのプログラミングの知識があまりなくマニュアルを見ながらコードをいじったので、もし変なところがあったら教えてください。

基本的な使い方は、まず下記の部分にGoogle Analyticsへログインするときのユーザー名([email protected]のxxxxの部分)とパスワード、そしてGoogle AnalyticsのプロファイルIDと、ランキングを何位までにしたいかを設定してください。

my $token = &gaGetToken('User-ID','Passwd');
my $profileid = "XXXXXXXX";
my $maxresult = 10;

プロファイルIDとは、Google AnalyticsのWebサイトでレポートを表示したときに用いるURLの「id=」の後ろに表示されている数字です(例:15249720)。

デフォルトでは今日から過去7日分のデータを集計しています。もし期間を変更したい場合には、以下の「$tm=」の右辺を変更してください。この式は7日×24時間×60分×60秒で7日分の秒数を求めています。7日を14日に変更すれば過去2週間分、31日に変更すれば過去1カ月分が集計対象となります。

$tm = localtime(time-7*24*60*60);
my $wago = sprintf "%04d-%02d-%02d",$tm->year+1900, $tm->mon+1,$tm->mday;

Google Analytics APIの機能や使い方についての詳細は、グーグルのページを参照してください(Developer's Guide - Google Analytics - Google Code

重要な注意!:このコードは、Webサーバから見えるところには置かないでください。第三者にあなたのログイン名とパスワードを盗まれてしまいます。Webサーバに見えない位置にコードを設置して、出力だけをWebサーバから見える場所に書き込むようにするべきです。

そのためには、例えば次のようなシェルスクリプトを用意するとよいのではないでしょうか。

/usr/bin/perl /usr/local/RankingByGoogleAnalytics.pl > /home/www/ranking.inc

上記のシェルスクリプトをcronで定期的に実行することで、Webサーバから見えるところに自動的にランキングのファイルが生成されます。

また、TypePadやココログなどのブログサービスを利用していて、サーバではスクリプトを実行できない場合には、別のサーバを借りてこのコードを実行する方法も考えられるでしょう。その場合は、出力形式をJSONに変更したうえでJavaScriptで読み込む方法や、AtomPPなどを使ってブログサーバに書き込んでからテンプレートでincludeする方法などが考えられます。いろいろ工夫してみてください。

このコードはさくらインターネットで動作を確認していますが、ホスティング先によってはPerlのバージョンやライブラリの違いで動作しないかもしれません。どうかご了承を。また分からない部分や変な部分があれば、どうぞコメント欄などでご指摘ください。

以下、ソースコードです。

#!/usr/bin/perl -w
use strict;
use Encode;
use LWP::UserAgent;
use XML::Simple;
use Time::localtime;

# authenticate with the API to receive token
my $token = &gaGetToken('User-ID','Passwd');
my $profileid = "XXXXXXXX";
my $maxresult = 10;
$maxresult++;

my $tm = localtime();
my $tdy = sprintf "%04d-%02d-%02d",$tm->year+1900, $tm->mon+1,$tm->mday;
$tm = localtime(time-7*24*60*60);
my $wago = sprintf "%04d-%02d-%02d",$tm->year+1900, $tm->mon+1,$tm->mday;

my $url = "https://www.google.com/analytics/feeds/data?"
."ids=ga%3A$profileid&"
."dimensions=ga%3ApagePath%2Cga%3ApageTitle&"
."metrics=ga%3AuniquePageviews&"
."sort=-ga%3AuniquePageviews&"
."start-date=$wago&"
."end-date=$tdy&"
."max-results=$maxresult";

my $pageviews = &gaDataFeed($url, $token);

# create a xml object for the response
my $xml = new XML::Simple(KeyAttr=>[]);
my $tree = $xml->XMLin($pageviews);

# iterate through each entry in the xml
my $i = 0;
print "<ol>";

foreach my $e (@{$tree->{entry}}) {
# eliminate toppage(/) from ranking
if ($e->{'dxp:dimension'}->[0]->{value} eq "/") { next; }

print "<li>";
print "<a href=\"";
print $e->{'dxp:dimension'}->[0]->{value};
print "\">";
print Encode::encode("utf8",substr($e->{'dxp:dimension'}->[1]->{value},0,22));
print "...</a></li>";

$i++;
if ($i >= ($maxresult -1)) { last; } 
}
print "</ol>";


# this sub will return the token you need to authenticate api requests
# you need to pass your ga login and password to it
sub gaGetToken {
# arguments passed to this function
my $user = $_[0];
my $pass = $_[1];

# create user agent object
my $ua = LWP::UserAgent->new;
$ua->agent("MyApp/0.1 ");

# Create a request
my $req = HTTP::Request->new(POST => 'https://www.google.com/accounts/ClientLogin');
$req->content_type('application/x-www-form-urlencoded');
$req->content("accountType=GOOGLE&Email=$user&Passwd=$pass&service=analytics&source=companyName-applicationName-versionID");

# Pass request to the user agent and get a response back
my $res = $ua->request($req);

# declare variable
my $token;

# Check the outcome of the response
if ($res->is_success) {
    # look at the result
    if ($res->content =~ m/(?<=Auth=).*/im) {
        # store token so it can be used in subsequent requests
        $token = $&;
    }
}
else {
    # return the error if there was a problem
    return "error: ". $res->status_line;
    die;
}

# return the token
return $token;
}


# this sub will return the xml from a datafeed request
# you need to pass your token to it
sub gaDataFeed {
# arguments passed to this function
my $url = $_[0];
my $token = $_[1];    

# create user agent object
my $ua = LWP::UserAgent->new;
$ua->agent("MyApp/0.1 ");

# add authorization to headers
my @headers = (Authorization => "GoogleLogin Auth=$token");

# request page
my $res = $ua->get($url, @headers);

my $content;

# if the request was successful...
if ($res->is_success) {
    # this is the xml response
    $content = $res->content;
} else {
    # return the error if there was a problem
    return "error: ". $res->status_line;
    die;
}

# return the xml
return $content;
}

あわせて読みたい

編集後記 Perl




タグクラウド

クラウド
AWS / Azure / Google Cloud
クラウドネイティブ / サーバレス
クラウドのシェア / クラウドの障害

コンテナ型仮想化

プログラミング言語
JavaScript / Java / .NET
WebAssembly / Web標準
開発ツール / テスト・品質

アジャイル開発 / スクラム / DevOps

データベース / 機械学習・AI
RDB / NoSQL

ネットワーク / セキュリティ
HTTP / QUIC

OS / Windows / Linux / 仮想化
サーバ / ストレージ / ハードウェア

ITエンジニアの給与・年収 / 働き方

殿堂入り / おもしろ / 編集後記

全てのタグを見る

Blogger in Chief

photo of jniino

Junichi Niino(jniino)
IT系の雑誌編集者、オンラインメディア発行人を経て独立。2009年にPublickeyを開始しました。
詳しいプロフィール

Publickeyの新着情報をチェックしませんか?
Twitterで : @Publickey
Facebookで : Publickeyのページ
RSSリーダーで : Feed

最新記事10本