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);
}
}