Reputation: 19136
I see that Google Analytics (as part of their new and recommended Universal Analytics solution) provides a simple RESTful interface called the Measurement Protocol for collecting analytics from a variety of platforms or applications.
How do you use this interface from a Flash/AS3 app? I'm creating a payload of url-formatted parameters according to the docs, but I'm getting a SecurityError
because crossdomain.xml
is not hosted at http://www.google-analytics.com/crossdomain.xml
when making the URL request:
[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security sandbox violation: http://<mysite>/<myapp>.swf cannot load data from http://www.google-analytics.com/collect."]
Using either POST or GET, this call fails in the context of a web browser (though it succeeds in the context of AIR):
// i.e. var payload:String = 'v=1&t=event&ec=category&ea=action'+
// '&el=label&tid=UA-xxxxxxxx-x&cid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
var req:URLRequest = new URLRequest('http://www.google-analytics.com/collect');
req.method = URLRequestMethod.POST;
req.data = payload;
var urlLoader:URLLoader = new URLLoader();
urlLoader.load(req);
I need these analytics to work from either AIR or the Flash Player (on a web page).
Upvotes: 1
Views: 1186
Reputation: 86
or you can use a library
Google Universal Analytics for ActionScript 3.0
checkout as3-universal-analytics v0.8
https://github.com/zwetan/as3-universal-analytics/releases/tag/0.8
full support for: Flash Player, AIR, Redtamarin
it just works everywhere or almost everywhere :)
in your case
var config:Configuration = new Configuration();
config.forcePOST = true;
var tracker:WebTracker = new WebTracker( "UA-12345-67", config );
tracker.pageview( "/hello/world", "Hello World" );
Upvotes: 1
Reputation: 2251
Jeff has a good answer, but you can improve it by leveraging POST
method, not GET
, since GET is quite restricted and not good to send a big bunch of data.
var req:URLRequest = new URLRequest(url);
req.method = URLRequestMethod.POST;
req.data = payload;
var l:Loader = new Loader();
l.load(req);
Notice POST
request method, it will do the trick
Upvotes: 0
Reputation: 19136
As is noted in the URLRequest docs, cross-site scripting (xss) restrictions require a crossdomain.xml
for POST requests. Since google doesn't host this file, you have to avoid POST. But the measurement protocol doc says it will accept either GET or POST. So you have to use a GET. GET with the above code still throws, but it turns out if you use a Loader instead of a URLLoader (as if you were going to access an image on the web, which is not covered by xss rules), it works:
// i.e. var payload:String = 'v=1&t=event&ec=category&ea=action'+
// '&el=label&tid=UA-xxxxxxxx-x&cid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
var req:URLRequest = new URLRequest('http://www.google-analytics.com/collect?'+payload);
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, cleanup);
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, cleanup);
l.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, cleanup);
l.load(req);
function cleanup(e:Event):void {
l.contentLoaderInfo.removeEventListener(Event.COMPLETE, cleanup);
l.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, cleanup);
l.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, cleanup);
}
You want the error listeners so that no errors pop-up, and you also need to clean them up to prevent memory leaks.
However, on mobile, I'd still use your original URLLoader
code (as it has fewer allocations / events), perhaps using conditional compilation:
// i.e. var payload:String = 'v=1&t=event&ec=category&ea=action'+
// '&el=label&tid=UA-xxxxxxxx-x&cid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
ENV::AIR {
var req:URLRequest = new URLRequest('http://www.google-analytics.com/collect');
req.method = URLRequestMethod.POST;
req.data = payload;
var urlLoader:URLLoader = new URLLoader();
urlLoader.load(req);
}
ENV::WEB {
var req:URLRequest = new URLRequest('http://www.google-analytics.com/collect?'+payload);
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, cleanup);
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, cleanup);
l.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, cleanup);
l.load(req);
function cleanup(e:Event):void {
l.contentLoaderInfo.removeEventListener(Event.COMPLETE, cleanup);
l.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, cleanup);
l.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, cleanup);
}
}
Upvotes: 1