在Adobe AIR刚刚推出的时候,有一个Google Analytics AIR的应用非常吸引人。它读取Google Analytics的数据,运用各种Chart图表进行展示。后来这个项目从beta到正式版,名字也更换为Polaris,在Adobe的AIR Market上叫做Polaris For Google Anlytics。当它beta版本的时候,Google Analytics还没有发布相关的API,如何取得Google Analytics的数据着实让人迷惑。现在Google Analytics发布了Data Export API,利用这个API我们也可以读取Google Analytics的数据,做出自己的AIR应用。而且Google Analytics现在可以跟踪记录Flash/Flex应用里面的按钮或者链接事件,能够让我们更准确的记录和分析用户在网站上的行为。
首先让我们了解一下Google Analytics Data Export API的一些读取限制政策,避免在开发的时候遇到访问数量的限制:
Google Analytics Data Export API的数量读取限制是针对一个站点的,即一个profile的。
24小时内不能多于10,000个HTTP Request。
10秒内不能多于100个HTTP Request。
每次返回的XML数据中,不多于10,000个entry。
开发一个AIR应用使用Google的API,首先要让用户通过Google账户的认证。Google API的认证有3种方式:
AuthSub Proxy Authentication
OAuth Authentication
ClientLogin Username/Password Authentication
由于是AIR客户端,所以在这篇文章中我们选择ClientLogin Username/Password Authentication的认证方式,如果想开发基于OAuth的认证方式可以参考以前的文章《ActionScript For OAuth Step By Step》。要注意的是开发WEB Application的话,尽量选择OAuth的认证方式,因为Google安全策略的限制,ClientLogin的认证方式可能不能正常登陆。
ClientLogin Username/Password Authentication是Google为客户端提供的认证方式,AIR的程序或者使用C#、C++开发的桌面程序都可以使用这种认证方式。这种认证方式很简单,就是向ClientLogin的认证地址POST一个表单,登录成功后从返回的数据中提取Auth这个变量。在以后的读取过程中在HTTP Header的Authorization中加入Auth这个变量就可以。
ClientLogin的POST地址:
https://www.google.com/accounts/ClientLogin
表单有以下几项:
accountType 账户类型有GOOGLE、HOSTED和HOSTED_OR_GOOGLE。由于是Google Analytics和Google Account绑定在一起,所以这里是使用GOOGLE这个账户类型。
Email Google Analytics对应的Gmail账号。
Passwd Gmail密码
service 这里service是个固定值:analytics。如果想使用其它服务的API,这里应该是对应服务的名称。具体参考看Google Service Name List。
source 可以是空的,也可以按照companyName-applicationName-versionID这个格式填写。
现在我们写个函数登录和处理登录的返回值,取得想要的Auth变量。
private function login(email : String, password : String) : void
{
var _loginRequest : URLRequest = new URLRequest();
_loginRequest.url = 'https://www.google.com/accounts/ClientLogin';
_loginRequest.method = URLRequestMethod.POST;
_loginRequest.requestHeaders.push(
new URLRequestHeader('Content-Type',
'application/x-www-form-urlencoded'));
var _data : URLVariables = new URLVariables();
_data.accountType = 'GOOGLE';
_data.Email = email;
_data.Passwd = password;
_data.service = 'analytics';
_data.source = '';
_loginRequest.data = _data;
var _loader : URLLoader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, doLogin);
_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, doLogin);
_loader.addEventListener(IOErrorEvent.IO_ERROR, doLogin);
_loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doLogin);
try
{
_loader.load(_loginRequest);
}
catch(error : Error)
{
Alert.show(error.message);
}
}
private function doLogin(event : Event) : void
{
switch(event.type)
{
case Event.COMPLETE:
authGoogle((event as Event).target.data);
break;
case HTTPStatusEvent.HTTP_STATUS:
if((event as HTTPStatusEvent).status == 200)
{
//do something
}
break;
case IOErrorEvent.IO_ERROR:
Alert.show((event as IOErrorEvent).text);
break;
case SecurityErrorEvent.SECURITY_ERROR:
Alert.show((event as SecurityErrorEvent).text);
break;
}
}
private function authGoogle(data : Object) : void
{
var auth : String;
var sid : String;
var lsid : String;
var _array : Array = (data as String).split('\n');
for(var i : int = 0; i < _array.length; i++) {
if((_array[i] as String).length > 0)
{
var _param : URLVariables = new URLVariables()
_param.decode(_array[i] as String);
if(_param.hasOwnProperty('Auth'))
auth = _param['Auth'];
if(_param.hasOwnProperty('SID'))
sid = _param['SID'];
if(_param.hasOwnProperty('LSID'))
lsid = _param['LSID'];
}
}
analyticsProfiles(auth);
}
一个Google Account可以添加多个Web Site的Profile,同时还可能会有别人share的Profile。所以在认证完成后,需要从Google Analytics取得Profile的列表。这个Profile列表是一个feed的xml文件,读取这个文件的时候要注意使用上一步的auth添加到HTTP的Header中。
private function analyticsProfiles(auth : String) : void
{
var _profiles : URLRequest = new URLRequest();
_profiles.url =
'https://www.google.com/analytics/feeds/accounts/default';
_profiles.method = URLRequestMethod.GET;
var _auth : String = 'GoogleLogin auth=' + auth;
_profiles.requestHeaders.push(
new URLRequestHeader('Authorization', _auth));
var _loader : URLLoader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, doProfile);
try
{
_loader.load(_profiles);
}
catch(err : Error)
{
//Alert Error Message
}
}
返回的xml数据:
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'
xmlns:dxp='http://schemas.google.com/analytics/2009'>
<id>
http://www.google.com/analytics/feeds/accounts/genedna@gmail.com
</id>
<updated>2009-01-07T22:13:35.000-08:00</updated>
<title type='text'>Profile list for genedna@gmail.com</title>
<link rel='self' type='application/atom+xml'
href='http://www.google.com/analytics/feeds/accounts/default'/>
<author>
<name>Google Analytics</name>
</author>
<generator version='1.0'>Google Analytics</generator>
<openSearch:totalResults>2</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>2</openSearch:itemsPerPage>
<entry>
<id>
http://www.google.com/analytics/feeds/accounts/ga:10200000
</id>
<updated>2008-08-11T19:21:12.000-07:00</updated>
<title type='text'>www.douhua.im</title>
<link rel='alternate' type='text/html'
href='http://www.google.com/analytics'/>
<dxp:tableId>ga:10200000</dxp:tableId>
<dxp:property name='ga:accountId' value='1400000'/>
<dxp:property name='ga:accountName' value='Meaglith Ma'/>
<dxp:property name='ga:profileId' value='10204831'/>
<dxp:property name='ga:webPropertyId' value='UA-140000-15'/>
<dxp:property name='ga:currency' value='USD'/>
<dxp:property name='ga:timezone' value='Asia/Shanghai'/>
</entry>
</feed>
返回的XML数据中tableId的值是一一对应Profile的,我们要访问douhua.im站点的访问数据情况,必须使用tableId这个值。读取Google Analytics Report的数据方式和读取Profile的方式一样,只是根据不同的参数读取不同的Report类型,目前可以访问的类型有Visitors、Traffic Sources 、Content、Goals和Ecommerce,访问的地址根据需要进行拼装,具体请参考Google Analytics Data Export API的Dimensions & Metrics Reference章节。示例:
https://www.google.com/analytics/feeds/data?ids=ga:10204831&dimensions=ga:country,ga:city&metrics=ga:pageviews&start-date=2009-05-01&end-date=2009-05-31