We use Google Analytics at work, and it has always been painful to create any kind of automated reports using that data. To date I have had to setup scheduled .csv reports to myself, parse them and import the into a database. It was definitely a pain to setup and maintain, so I was thrilled to see Google finally released a API for Google Analytics. I decided to put this together to help give people a starting point for using their Google Analytics information in their Perl programs.
The first thing you will need to do is request a token from Google. This is what you will use to authenticate yourself on all data feed requests for your session.
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
use XML::Simple;
# 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;
}
# authenticate with the API to receive token
my $token = &gaGetToken('username','password');
This will give you the token you need to make other requests. Now you have the token, you can request a data feed of the analytics account information that is tied to your Google account. The way I chose to handle this is the parse the feed and return an array of account names and account numbers.
# this sub will return an array of all your ga accounts
# you need to pass your token to it
sub gaAccounts {
# the token you passed to this sub
my $token = $_[0];
# 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 the accounts feed
my $res = $ua->get("https://www.google.com/analytics/feeds/accounts/default", @headers);
# define accounts array
my @accounts;
# if the request was successful...
if ($res->is_success) {
# declare variables
my ($content, $e);
# this is the xml it returns
$content = $res->content;
# create a xml object for the response
my $xml = new XML::Simple(KeyAttr=>[]);
my $tree = $xml->XMLin($content);
# iterate through each entry
my $x = 0;
foreach $e (@{$tree->{entry}})
{
# add the account to the array
$accounts[$x][0] = $e->{title}->{content};
$accounts[$x][1] = $e->{'dxp:tableId'};
$x++
}
} else {
# return the error if there was a problem
return "error: ". $res->status_line;
die;
}
# return the array of accounts
return @accounts;
}
# get array of all sites in your account
my @sites = &gaAccounts($token);
# list all the sites in the array
foreach(@sites) {
print $_->[0] ." => ". $_->[1] ."\n";
}
# going forward, we will use the first account number
my $website = $sites[0][1];
Now you have a token and account number, you have everything you need to make data feed requests for the Google Analytics information for that account. Here is a example of getting visits by day:
# 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;
}
# to test, lets request visit by day
my $pageviews = &gaDataFeed("https://www.google.com/analytics/feeds/data?ids=$website&dimensions=ga%3Adate&metrics=ga%3Avisits&start-date=2009-07-27&end-date=2009-08-10&max-results=365", $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
foreach my $e (@{$tree->{entry}})
{
# date value
print $e->{'dxp:dimension'}->{value};
print " : ";
# visitors value
print $e->{'dxp:metric'}->{value};
print "\n";
}
That is the basics, you can use the above to access just about anything in your Google Analytics account. There is a good query explorer that you can use to generate and test data feed request URI’s. I hope this helps you get started with Google Analytics and Perl.
#1 by Alexandr Ciornii on August 11th, 2009
new XML::Simple ()
is better written as
XML::Simple->new()
#2 by Dan Wolfgang on September 9th, 2009
I’m not having much luck with this. in the gaGetToken sub, the request doesn’t go through, and throws an error:
500 Can’t connect to http://www.google.com:443 (Invalid argument)
Any suggestions?
#3 by Dan Wolfgang on September 12th, 2009
FYI to anybody else, this error was fixed by installing the Crypt::SSLeay module.
#4 by Polprav on November 2nd, 2009
Hello from Russia!
Can I quote a post “No teme” in your blog with the link to you?
#5 by japh on December 3rd, 2009
http://github.com/motemen/WebService-Google-Analytics
#6 by Pheobe on January 14th, 2010
Thanks. Sooooo helpful!
#7 by Patrick on January 15th, 2010
Thanks, I’ll check that out.