Copy link to clipboard
Copied
Hi All,
I'd like to enable Google Analytics for my app. I know that there are some ANEs that aim to provide this functionality. I tried one of them a few years ago and wasn't able to get it to work correctly.
Have any of you gotten this working in your apps, i.e. successfully and reliably sending events to Google Analytics? If so, what ANE did you use?
Thanks in advance,
Douglas
Copy link to clipboard
Copied
The one I've used is NativeGATracker, and the version from a few years ago stopped working. But, version 2.0.7 does work, I'm using it in a current app update:
Copy link to clipboard
Copied
I used to work with the Milkmangames ganalytics but Alex is MIA and stopped updating his ANEs so the only safe bet right now is from distriqt
https://airnativeextensions.com/extension/com.distriqt.GoogleAnalytics
It is updated and works.
Copy link to clipboard
Copied
Thanks Colin and Leo - this is very helpful.
Copy link to clipboard
Copied
Or you can use Google Analytics without an ANE
GitHub - zwetan/as3-universal-analytics: Google Universal Analytics for AS3
Copy link to clipboard
Copied
Thanks Zwetan!
Copy link to clipboard
Copied
Here's an update, in case someone happens upon this thread and wants to know how it worked out.
I ended up using a modified version of Zwetan's as3-universal-analytics code rather than an ANE. I've now got it working, and I can see messages appear in GA's "real time" view almost instantaneously once they are dispatched from my app.
The main reason that I went with this pure-AS approach is that it's very helpful to be able to see what is happening, i.e. to step through the code in a debugger and see the values that are being sent over the wire, etc. When I was trying to get ANEs to work it felt like I was working with a black box ... full of mystery ... the great unknown. But, actually, what is happening isn't mysterious at all - it's quite straightforward. We're simply sending HTTP requests to Google as explained here:
https://developers.google.com/analytics/devguides/collection/protocol/v1/
https://developers.google.com/analytics/devguides/collection/protocol/v1/reference
Another reason I didn't go with Distriqt's ANE is that it had conflicts with other (MyFlashLab) ANEs that I use.
Zwetan's sample code shows how to track page views, but I wanted to use GA's "event" message type for my app instead. Below is an abbreviated copy of the code I ended up with.
Thanks again,
Douglas
package com.foo.util {
public class Utils_GoogleAnalytics {
private static var _clientID:String;
private static var _loader:Loader;
private static var _trackLogDataCallbackFunction:Function;
public static function trackSomething(data:String):void {
sendEvent("someCategoryName", data);
}
<snip> other public methods that track other kinds of things </snip>
private static function sendEvent(category:String, action:String, label:String = null, value:Number = NaN):void {
if (!_clientID)
_clientID = Utils_Misc.generateImitationUUIDString();
if (!_loader) {
_loader = new Loader();
_loader.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onLoaderUncaughtError);
_loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, onLoaderHTTPStatus);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoaderIOError);
}
var payload:Array = [];
payload.push("v=1");
payload.push("tid=" + Constant_Private.GOOGLE_ANALYTICS_CODE);
payload.push("cid=" + _clientID);
payload.push("t=event");
payload.push("ec=" + category);
payload.push("ea=" + action);
if (label)
payload.push("el=" + label);
if (!isNaN(value))
payload.push("ev=" + value);
var request:URLRequest = new URLRequest();
request.method = URLRequestMethod.POST; // POST accepts a larger payload than GET
request.url = "http://www.google-analytics.com/collect";
request.data = payload.join("&");
try {
_loader.load(request);
}
catch (e:Error) {
// trace or log something
}
}
private static function onLoaderUncaughtError(e:UncaughtErrorEvent):void {
if (e.error is Error) {
var error:Error = e.error as Error;
// trace or log something
}
else if (e.error is ErrorEvent) {
var errorEvent:ErrorEvent = e.error as ErrorEvent;
// trace or log something
}
else {
// trace or log something
}
}
private static function onLoaderHTTPStatus(e:HTTPStatusEvent):void {
if (e.status == 200) {
// the request was accepted
}
else {
// trace or log something
}
}
private static function onLoaderIOError(e:IOErrorEvent):void {
// trace or log something
}
private static function onLoaderComplete(e:Event):void {
// success - trace or log something?
}
}
}
Copy link to clipboard
Copied
Zwetan's sample code shows how to track page views, but I wanted to use GA's "event" message type for my app instead. Below is an abbreviated copy of the code I ended up with.
That's why there is a library, you can use raw code but the library is better in the sense that many things are already tested/configured/etc. eg. "ready to use"
be careful with the raw code, it would works for testing but it will probably fail in the long run
as it doesn't do any throttling etc. simply if your app send too many events to GA then the tracking will be locked by GA
you may even have your account banned
there are limits to not abuse
for ex
look into AnalyticsTracker.as
the event() method
eg.
event( category:String, action:String, label:String = "", value:int = -1 ):Boolean
small example
var tracker:AppTracker = new AppTracker( "UA-12345-67" );
tracker.set( Tracker.APP_NAME, "My App" );
tracker.event( "Videos", "play", "Big Buck Bunny" );
so you mentioned
The main reason that I went with this pure-AS approach is that it's very helpful to be able to see what is happening, i.e. to step through the code in a debugger and see the values that are being sent over the wire, etc.
When you test locally you can use a configuration to change the sender type to use TraceHitSender or DebugHitSender
for example
var config:Configuration = new Configuration();
config.senderType = "libraries.uanalytics.tracker.senders.TraceHitSender";
var tracker:WebTracker = new WebTracker( "UA-12345-67", config );
see the documentation TrackingConfiguration
by using something like TraceHitSender it will display in the output all the tracking hits without sending then to GA backend
Copy link to clipboard
Copied
Thanks, Zwetan. This is helpful info.
Copy link to clipboard
Copied
If the only reason for not using ANE is the conflict between myflashlabs and distriqt, you can remove some duplicate service ANEs to get around this.
I use many ANEs from different vendors without any issues, but always use services (like google service for analytics) from one vendor and not add duplicates. If you remove the androidsupport.ane from distriqt in your project, it will run as expected.
Copy link to clipboard
Copied
Hi Leo,
Thanks for this info.
In the case of GA I prefer to avoid using an ANE, but what you are saying is still of great interest to me as I'd like to use other Distriqt ANEs in addition to the MyFlashLabs ANEs that I'm currently using.
I'm a bit confused about this:
> If you remove the androidsupport.ane from distriqt in your project, it will run as expected.
I get the impression from Distriqt's documentation that androidsupport.ane is a required "support" ANE.
Will their other ANEs work without this, even on Android?
If so, why are they telling me that I need it?
I notice that MyFlashLabs also has "support" ANEs. Is it the case that if I remove androidsupport.ane then my Distriqt ANEs will get the needed functionality from the MyFlashLabs support ANEs?
Thanks,
Douglas
Copy link to clipboard
Copied
If you are getting any conflicts between ANEs, it means that you have a duplicate ANE somewhere. If you need androidsupport, use only 1 from a vendor (don't add both the androidsupport from distriqt and myflashlabs).
Check this example. As you can see I am using marpies, distriqt, milkman and myFlashlabs in the same app. However all the needed dependencies come from only one vendor (myflashlabs). This way I get no conflicts.
ps. Yes I use so many ANEs that this app is basically native
Copy link to clipboard
Copied
Thanks Leo - very helpful.