From 69ac1717cf91b358568faf0280cbdc75729defd2 Mon Sep 17 00:00:00 2001
From: zwetan
+ * The which utility takes a command name and searches the path
+ * for each executable file that would be run had this
+ * command actually been invoked.
+ *
+ * Note: This class is not a component, it is just
+ * a shim that allow to declare the SWC manifest and associate an icon file.
+ *
+ * Use
+ * Note: this is a temporary solution as the current redtamarin runtimes
+ * does not implment
+ * The equivalent of iOS / Android Google Analytics SDK
+ * for desktop and/or mobile AIR applications.
+ *
+ * Features:
+ *
+ * By default, all the parameters are empty (not initialised).
+ * Only the non-empty (or initialised) parameters wil be exported
+ * by the
+ * Features:
+ *
+ * This tracker is to be considered as a basic common denominator,
+ * but you would want to customise it for different use cases.
+ *
+ * Important things to know:
+ *
+ * Those values are examples of what we think is "common use case",
+ * you can use any value you want.
+ *
+ * In general, we think you would want to differentiate between
+ * the web: a SWF hosted in an online HTML page,
+ * an app: an AIR application,
+ * and commandline: a Redtamarin command-line program.
+ *
+ * You may want also to differentiate between
+ * a desktop app: AIR published for the desktop
+ * and a mobile app: AIR published for mobile.
+ *
+ * That said, you could use any values, here few more examples:
+ * "cms" (content management system), "server" (when you do tracking server-side),
+ * "shellscript" (when using a shell script vs a static binary), etc.
+ *
+ * This tracker is to be considered as a basic common denominator,
+ * we mainly use it to do quick tests and experiments,
+ * and you do not want to use it "as is" in production unless you really
+ * know what you are doing.
+ *
+ * Important things to know:
+ *
+ * depending on your use case you would want to use a specialised tracker:
+ *
+ * By default, all the parameters are empty (not initialised).
+ * Only the non-empty (or initialised) parameters wil be exported
+ * by the
+ * By default, all the parameters are empty (not initialised).
+ * Only the non-empty (or initialised) parameters wil be exported
+ * by the
+ * The equivalent of analytics.js for online SWF files.
+ *
+ * Features:
+ *
+ * To integrate with a Twitter API.
+ *
+ * Some example of buttons: Tweet, Follow, hashtag, Mention, etc.
+ *
+ * This is the default implementation we use in all the Redtamarin trackers.
+ *
+ * Different and More complicated implementations could do more things;
+ * for example: queue hits and send them at a later time, validate the hit
+ * by checking the HTTP response code, etc.
+ *
+ * When enableErrorChecking is
+ * The "debug mode", if set to
+ * The "verbose mode", if set to
+ * Will call the
+ * Will call the
+ * Will call the
+ * As Redtamarin doesn't have SSL support for sockets on the command-line
+ * cURL allow to fill this void.
+ * To ensure that your hits are correctly formatted and contain all required
+ * parameters, you can test them against the validation server before
+ * deploying them to production.
+ *
+ * The sender use the endpoint
+ * This is the default implementation we use in all the Flash and AIR trackers
+ * for the following reasons:
+ *
+ * The only problem you can encounter is with local SWF files outside the
+ * "User Flash Player Trust directories".
+ * By default a local SWF file is placed in the local-with-filesystem sandbox
+ * see security sandboxes
+ * and will prevent the tracking to work (as it can not access the network).
+ * Although, this behaviour can be changed by setting the document’s publish
+ * settings in the authoring tool.
+ *
+ * Different and More complicated implementations could do more things;
+ * for example: queue hits and send them at a later time, validate the hit
+ * by checking the HTTP response code, etc.
+ *
+ * Note:
+ *
+ * It will work only in a debug Flash Player, debug AIR application,
+ * and with the debug redshell (or as3shebang).
+ * It will not send any data to the Google Analytics servers.
+ *
+ * Note:
+ *
+ * The strict minimum of what a sender need to implement
+ * is to send a data model to a URL.
+ *
+ * For a Flash / AIR implementation see
+ * The strict minimum of what a tracker need to implement:
+ *
+ * The format is UA-XXXX-Y.
+ * All collected data is associated by this ID.
+ *
+ * For the web, this is generally stored as a first-party cookie with
+ * a two-year expiration.
+ * For mobile apps, this is randomly generated for each particular
+ * instance of an application install.
+ * The value of this field should be a random UUID (version 4)
+ * as described in rfc4122.
+ *
+ * The configuration is applied for each hits, if you change properties
+ * between hits, it will affect the way hits are processed.
+ *
+ * Page tracking allows you to measure the number of views you had for a
+ * particular page on your website.
+ *
+ * Pages often correspond to an an entire HTML document, but they can
+ * also represent dynamically loaded content;
+ * this is known as "virtual pageviews".
+ *
+ * Screens in Google Analytics represent content users are viewing
+ * within your app.
+ * The equivalent concept in web analytics is a pageview.
+ *
+ * Measuring screen views allows you to see which content is being
+ * viewed most by your users, and how they are navigating between
+ * different pieces of content.
+ *
+ * Events are user interactions with content that can be tracked
+ * independently from a web page or a screen load.
+ *
+ * Downloads, mobile ad clicks, gadgets, Flash elements, AJAX embedded
+ * elements, and video plays are all examples of actions you might want
+ * to track as Events.
+ *
+ * Ecommerce tracking allows you to measure the number of transactions
+ * and revenue that your website generates.
+ *
+ * A transaction represents the entire transaction that occurs on your
+ * site.
+ *
+ * An item represents the individual products that were in the shopping
+ * cart.
+ *
+ * Social interaction measurement allows you to measure a user's
+ * interactions with various social network sharing and recommendation
+ * widgets embedded in your content.
+ *
+ * While event tracking measures general user-interactions very well,
+ * Social Analytics provides a consistent framework for recording social
+ * interactions.
+ * This in turn provides a consistent set of reports to compare social
+ * network interactions across multiple networks.
+ *
+ * Exception tracking allows you to measure the number and type of
+ * crashes or errors that occur on your property.
+ *
+ * Allows to measure periods of time, particularly useful for developers
+ * to measure the latency, or time spent, executing a particular action.
+ *
+ * Google Analytics has a number of powerful reports that automatically
+ * measure and report on page load times.
+ * However, it is also possible to track custom timing information to
+ * measure performance specific to your site.
+ *
+ * Those are the default configuration settings used by all the trackers.
+ * You can change the configuration settings while in use by the trackers,
+ * each time a hit request is send the configuration is applied again.
+ *
+ * Will add the undocumented
+ * If empty, the tracker will use the default
+ * To override the
+ * Attention:
+ * Default to
+ * Default to
+ * Default to
+ * Default to
+ * When processinga hit request we do check
+ * This defaults to 100 (no users are sampled out) but large sites may
+ * need to use a lower sample rate to stay within Google Analytics
+ * processing limits.
+ *
+ * A storage could be anything:
+ * In general, the storage will only contain the ClientId and no other informations.
+ *
+ * Users primarily get and set field values.
+ *
+ * Common field names are provided as static members of the
+ * See the
+ * Sampling is determined on a per-client basis as identified by
+ * the
+ * By default we use the value set in true
list all instances of executables found.
+ * @return the full path of the program or the empty string if not found.
+ *
+ * @langversion 3.0
+ * @playerversion AVM 0.4
+ * @playerversion POSIX +
+ *
+ * @see http://docs.redtamarin.com/latest/C/stdlib/package.html#getenv() C.stdlib.getenv()
+ * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/getenv.html getenv()
+ * @see http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script Check if a program exists from a bash script
+ * @see http://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/which/which.c shell command which
+ */
+ public function which( name:String, all:Boolean = false ):String
+ {
+ var PATH:String = getenv( "PATH" );
+ if( PATH == "" ) { return ""; }
+
+ /* Note:
+ usual paths are
+
+ /opt/local/bin
+ /opt/local/sbin
+ /usr/local/bin
+ /usr/bin
+ /bin
+ /usr/sbin
+ /sbin
+ */
+ var paths:Array = PATH.split( ":" );
+ paths.push( "." );
+
+ var is_there:Function = function( candidate:String ):Boolean
+ {
+ var fin:* = new status();
+ /* Note:
+ getlogin() != "root"
+ should be
+ getuid() != 0
+ */
+ if( (access( candidate, X_OK ) == 0) &&
+ (stat( candidate, fin ) == 0) &&
+ S_ISREG( fin.st_mode ) &&
+ ( (getlogin() != "root") ||
+ ((fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) ) )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ var found:String = "";
+
+ var i:uint;
+ var len:uint = paths.length;
+ var candidate:String;
+ for( i = 0; i < len; i++ )
+ {
+ candidate = paths[i] + "/" + name;
+ if( is_there( candidate ) )
+ {
+ if( all )
+ {
+ found += (found == "" ? "": " ") + candidate;
+ }
+ else
+ {
+ return candidate;
+ }
+ }
+ }
+
+ return found;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Library.as b/src/Library.as
new file mode 100644
index 0000000..47a9098
--- /dev/null
+++ b/src/Library.as
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package
+{
+ import flash.display.Sprite;
+
+ /**
+ * The basic framework Library to be included in the SWC.
+ *
+ * generateRandomBytes()
to generate cryptographic keys,
+ * strong identifiers, session ids, and so on.
+ * The random sequence is generated using cryptographically strong functions
+ * provided by the operating system.
+ * If the appropriate function is not available on an individual client
+ * computer or device, then an error is thrown.
+ * flash.crypto.generateRandomBytes
yet.
+ * It will work under Linux and Mac OS X but not under Windows (unless under a cygwin shell).
+ *
+ * Android SDK
+ * For each tracker instance on a device, each app instance starts with
+ * 60 hits that are replenished at a rate of 1 hit every 2 seconds.
+ * Applies to all hits except for ecommerce (item or transaction).
+ *
+ * iOS SDK
+ * Each property starts with 60 hits that are replenished at a rate of 1 hit
+ * every 2 seconds.
+ * Applies to all hits except for ecommerce (item or transaction).
+ *
+ *
+ *
+ *
+ *
+ * @example Usage
+ * RateLimiter
settings: the tracker starts with 60 hits
+ * that are replenished at a rate of 1 hit every 2 seconds.
+ * SharedObject
storage to save/restore the ClientId.
+ * DefaultTracker
+ *
+ *
+ */
+ protected override function _ctor( trackingId:String = "" ):void
+ {
+ _model = new HitModel();
+ _temporary = new HitModel();
+
+ if( _config.senderType != "" )
+ {
+ var S:Class = ApplicationDomain.currentDomain.getDefinition( _config.senderType ) as Class;
+ _sender = new S( this );
+ }
+ else
+ {
+ _sender = new LoaderHitSender( this );
+ }
+
+ /* Note:
+ the tracker starts with 60 hits
+ that are replenished at a rate of 1 hit every 2 seconds.
+ */
+ _limiter = new RateLimiter( 20, 2, 1 );
+
+ if( trackingId != "" )
+ {
+ set( TRACKING_ID, trackingId );
+ }
+
+ var cid:String = _getClientID();
+ if( cid != "" )
+ {
+ set( CLIENT_ID, cid );
+ }
+
+ set( Tracker.DATA_SOURCE, DataSource.APP );
+ }
+
+ /**
+ * @private
+ *
+ * A storage mecanism based on SharedObject
+ * to save and/or restore the ClientId.
+ */
+ protected override function _getClientID():String
+ {
+ // Load the SharedObject '_ga'
+ _storage = SharedObject.getLocal( _config.storageName );
+ var cid:String;
+
+ if( !_storage.data.clientid )
+ {
+ // CID not found, generate Client ID
+ cid = generateUUID();
+
+ // Save CID into SharedObject
+ _storage.data.clientid = cid;
+
+ var flushStatus:String = null;
+ try
+ {
+ flushStatus = _storage.flush( 1024 ); //1KB
+ }
+ catch( e:Error )
+ {
+ //trace( "Could not write SharedObject to disk: " + e.message );
+ }
+
+ if( flushStatus != null )
+ {
+ switch( flushStatus )
+ {
+ case SharedObjectFlushStatus.PENDING:
+ // Requesting permission to save object...
+ _storage.addEventListener( NetStatusEvent.NET_STATUS, onFlushStatus );
+ break;
+
+ case SharedObjectFlushStatus.FLUSHED:
+ // Value flushed to disk"
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ // CID found, restore from SharedObject
+ cid = _storage.data.clientid;
+ }
+
+ return cid;
+ }
+
+ protected function onFlushStatus( event:NetStatusEvent ):void
+ {
+ // User closed permission dialog...
+ _storage.removeEventListener( NetStatusEvent.NET_STATUS, onFlushStatus);
+
+ switch( event.info.code )
+ {
+ case "SharedObject.Flush.Success":
+ // User granted permission, value saved
+ break;
+
+ case "SharedObject.Flush.Failed":
+ // User denied permission, value not saved
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/ApplicationInfo.as b/src/libraries/uanalytics/tracker/ApplicationInfo.as
new file mode 100644
index 0000000..724686a
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/ApplicationInfo.as
@@ -0,0 +1,150 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker
+{
+ import flash.utils.Dictionary;
+
+ import libraries.uanalytics.tracking.Tracker;
+
+ /**
+ * The ApplicationInfo defines parameters meant to be used
+ * for the App / Screen Tracking.
+ *
+ * toDictionary()
function.
+ *
+ *
+ *
+ * @example Usage
+ * RateLimiter
settings: the tracker starts with 100 hits
+ * that are replenished at a rate of 10 hits per second.
+ *
+ *
+ *
+ * @example Usage
+ * RateLimiter
of this tracker starts with 100 hits
+ * that are replenished at a rate of 10 hits per second.
+ * BSDSocketHitSender
.
+ *
+ *
+ *
+ * RateLimiter
of this tracker starts with 100 hits
+ * that are replenished at a rate of 10 hits per second.
+ * LoaderHitSender
.
+ * WebTracker
, AppTracker
, etc.
+ * true
is the passed string type
+ * is a valid Hit Type.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static function isValid( type:String ):Boolean
+ {
+ var _class:XML = describeType( HitType );
+ var found:Boolean = false;
+
+ var property:String;
+ for each( var member:XML in _class.constant )
+ {
+ property = String( member.@name );
+
+ if( HitType[ property ] == type )
+ {
+ found = true;
+ break;
+ }
+
+ }
+ System.disposeXML( _class );
+
+ if( found )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates a HitType.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function HitType()
+ {
+ super();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/SessionControl.as b/src/libraries/uanalytics/tracker/SessionControl.as
new file mode 100644
index 0000000..6b67627
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/SessionControl.as
@@ -0,0 +1,57 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker
+{
+
+ /**
+ * The SessionControl class defines allowed values for the
+ * "session control" parameter.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * see: libraries.uanalytics.tracking.Tracker#SESSION_CONTROL Tracker.SESSION_CONTROL
+ * @see libraries.uanalytics.tracking.Metadata Metadata
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#sc Session Control
+ */
+ public class SessionControl
+ {
+
+ /**
+ * Forces a new session to start with the hit request.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const START:String = "start";
+
+ /**
+ * Forces the current session to end with the hit request.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const END:String = "end";
+
+ /**
+ * Creates a SessionControl.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function SessionControl()
+ {
+ super();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/SystemInfo.as b/src/libraries/uanalytics/tracker/SystemInfo.as
new file mode 100644
index 0000000..7eb20f5
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/SystemInfo.as
@@ -0,0 +1,203 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker
+{
+ import flash.utils.Dictionary;
+
+ import libraries.uanalytics.tracking.Tracker;
+
+ /**
+ * The SystemInfo defines parameters meant to be used
+ * for System Information Tracking.
+ *
+ * toDictionary()
function.
+ * toDictionary()
function.
+ * Document.readyState
+ * to be 'interactive'.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see libraries.uanalytics.tracking.Tracker#DOM_INTERACTIVE_TIME Tracker.DOM_INTERACTIVE_TIME
+ */
+ public var domInteractiveTime:int = -1;
+
+ /**
+ * The time it took for the DOMContentLoaded
Event
+ * to fire.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see libraries.uanalytics.tracking.Tracker#CONTENT_LOAD_TIME Tracker.CONTENT_LOAD_TIME
+ */
+ public var contentLoadTime:int = -1;
+
+ /**
+ * Creates an empty TimingInfo.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function TimingInfo()
+ {
+ super();
+ }
+
+ /**
+ * Export the initialised (non-empty) parameters.
+ *
+ * @return a Dictionary containing field/value pairs.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function toDictionary():Dictionary
+ {
+ var values:Dictionary = new Dictionary();
+
+ if( pageLoadTime > -1 )
+ {
+ values[ Tracker.PAGE_LOAD_TIME ] = String(pageLoadTime);
+ }
+
+ if( dnsTime > -1 )
+ {
+ values[ Tracker.DNS_TIME ] = String(dnsTime);
+ }
+
+ if( pageDownloadTime > -1 )
+ {
+ values[ Tracker.PAGE_DOWNLOAD_TIME ] = String(pageDownloadTime);
+ }
+
+ if( redirectResponseTime > -1 )
+ {
+ values[ Tracker.REDIRECT_RESPONSE_TIME ] = String(redirectResponseTime);
+ }
+
+ if( tcpConnectTime > -1 )
+ {
+ values[ Tracker.TCP_CONNECT_TIME ] = String(tcpConnectTime);
+ }
+
+ if( serverResponseTime > -1 )
+ {
+ values[ Tracker.SERVER_RESPONSE_TIME ] = String(serverResponseTime);
+ }
+
+ if( domInteractiveTime > -1 )
+ {
+ values[ Tracker.DOM_INTERACTIVE_TIME ] = String(domInteractiveTime);
+ }
+
+ if( contentLoadTime > -1 )
+ {
+ values[ Tracker.CONTENT_LOAD_TIME ] = String(contentLoadTime);
+ }
+
+ return values;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/WebTracker.as b/src/libraries/uanalytics/tracker/WebTracker.as
new file mode 100644
index 0000000..8f24edc
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/WebTracker.as
@@ -0,0 +1,192 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker
+{
+ import flash.events.NetStatusEvent;
+ import flash.net.SharedObject;
+ import flash.net.SharedObjectFlushStatus;
+ import flash.system.ApplicationDomain;
+
+ import libraries.uanalytics.tracker.senders.LoaderHitSender;
+ import libraries.uanalytics.tracking.Configuration;
+ import libraries.uanalytics.tracking.HitModel;
+ import libraries.uanalytics.tracking.RateLimiter;
+ import libraries.uanalytics.tracking.Tracker;
+ import libraries.uanalytics.utils.generateUUID;
+
+ /**
+ * A tracker specialised for the web.
+ *
+ *
+ * analytics.js:
+ * Each analytics.js tracker object starts with 20 hits that are replenished
+ * at a rate of 2 hit per second. Applies to all hits except for ecommerce
+ * (item or transaction).
+ *
+ *
+ *
+ *
+ *
+ * @example Usage
+ * RateLimiter
settings: the tracker starts with 20 hits
+ * that are replenished at a rate of 2 hits per second.
+ * SharedObject
storage to save/restore the ClientId.
+ * DefaultTracker
+ *
+ *
+ */
+ protected override function _ctor( trackingId:String = "" ):void
+ {
+ _model = new HitModel();
+ _temporary = new HitModel();
+
+ if( _config.senderType != "" )
+ {
+ var S:Class = ApplicationDomain.currentDomain.getDefinition( _config.senderType ) as Class;
+ _sender = new S( this );
+ }
+ else
+ {
+ _sender = new LoaderHitSender( this );
+ }
+
+ /* Note:
+ the tracker starts with 20 hits
+ that are replenished at a rate of 2 hits per second.
+ */
+ _limiter = new RateLimiter( 20, 2, 1 );
+
+ if( trackingId != "" )
+ {
+ set( TRACKING_ID, trackingId );
+ }
+
+ var cid:String = _getClientID();
+ if( cid != "" )
+ {
+ set( CLIENT_ID, cid );
+ }
+
+ set( Tracker.DATA_SOURCE, DataSource.WEB );
+ }
+
+ /**
+ * @private
+ *
+ * A storage mecanism based on SharedObject
+ * to save and/or restore the ClientId.
+ */
+ protected override function _getClientID():String
+ {
+ // Load the SharedObject '_ga'
+ _storage = SharedObject.getLocal( _config.storageName );
+ var cid:String;
+
+ if( !_storage.data.clientid )
+ {
+ // CID not found, generate Client ID
+ cid = generateUUID();
+
+ // Save CID into SharedObject
+ _storage.data.clientid = cid;
+
+ var flushStatus:String = null;
+ try
+ {
+ flushStatus = _storage.flush( 1024 ); //1KB
+ }
+ catch( e:Error )
+ {
+ //trace( "Could not write SharedObject to disk: " + e.message );
+ }
+
+ if( flushStatus != null )
+ {
+ switch( flushStatus )
+ {
+ case SharedObjectFlushStatus.PENDING:
+ // Requesting permission to save object...
+ _storage.addEventListener( NetStatusEvent.NET_STATUS, onFlushStatus );
+ break;
+
+ case SharedObjectFlushStatus.FLUSHED:
+ // Value flushed to disk"
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ // CID found, restore from SharedObject
+ cid = _storage.data.clientid;
+ }
+
+ return cid;
+ }
+
+ protected function onFlushStatus( event:NetStatusEvent ):void
+ {
+ // User closed permission dialog...
+ _storage.removeEventListener( NetStatusEvent.NET_STATUS, onFlushStatus);
+
+ switch( event.info.code )
+ {
+ case "SharedObject.Flush.Success":
+ // User granted permission, value saved
+ break;
+
+ case "SharedObject.Flush.Failed":
+ // User denied permission, value not saved
+ break;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/addons/DebugFileSystemStorage.as b/src/libraries/uanalytics/tracker/addons/DebugFileSystemStorage.as
new file mode 100644
index 0000000..c880652
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/addons/DebugFileSystemStorage.as
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker.addons
+{
+ import C.errno.*;
+ import C.sys.stat.*;
+ import C.unistd.*;
+ import C.stdio.*;
+
+ import flash.utils.ByteArray;
+
+ import libraries.uanalytics.tracking.Configuration;
+
+ import shell.FileSystem;
+
+ /**
+ * Utility function to debug and/or reset the File System storage.
+ *
+ * @param show show informations and datas of the sotrage (default to true
).
+ * @param reset clear the storage from its data (default to false
).
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function DebugFileSystemStorage( show:Boolean = true,
+ reset:Boolean = false ):void
+ {
+ var homedir:String = FileSystem.homeDirectory;
+
+ if( homedir == "" )
+ {
+ homedir = "/"; // root dir
+ }
+
+ var exists:int = access( homedir, F_OK );
+ if( exists < 0 )
+ {
+ throw new CError( errno );
+ }
+
+ var canread:int = access( homedir, R_OK );
+ if( canread < 0 )
+ {
+ throw new CError( errno );
+ }
+
+ var canwrite:int = access( homedir, W_OK );
+ if( canwrite < 0 )
+ {
+ throw new CError( errno );
+ }
+
+ // by that point we are sure the HOME directory exists and is readable/writable
+ // for ex: /home/username
+
+ var savepath:String = homedir + "/.uanalytics";
+ var s_exists:int = access( savepath, F_OK );
+ if( s_exists < 0 )
+ {
+ throw new CError( errno );
+ }
+
+ // by that point we are sure our preference dir .uanalytics exists
+ // for ex: /home/username/.uanalytics
+
+ var config:Configuration = new Configuration();
+ var filepath:String = savepath + "/" + config.storageName;
+ var data:String = "";
+
+ var f_exists:int = access( filepath, F_OK );
+ if( f_exists < 0 )
+ {
+ throw new CError( errno );
+ }
+ else
+ {
+ // the save file already exists
+ data = FileSystem.read( filepath );
+ }
+
+ if( show )
+ {
+ trace( "File: " + filepath );
+ trace( "size: " + data.length + " bytes" );
+ trace( "data:" );
+ trace( " |_ " + data );
+ }
+
+ if( reset )
+ {
+ // bug: does not allow you to write an empty file
+ //FileSystem.write( filepath, "" );
+ var fp:FILE = fopen( filepath, "w" );
+ if( fp )
+ {
+ var bytes:ByteArray = new ByteArray();
+ fwrite( bytes, bytes.length, fp );
+ fflush( fp );
+ bytes.clear();
+ fclose( fp );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/addons/DebugSharedObjectStorage.as b/src/libraries/uanalytics/tracker/addons/DebugSharedObjectStorage.as
new file mode 100644
index 0000000..cfbbbed
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/addons/DebugSharedObjectStorage.as
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker.addons
+{
+ import flash.net.SharedObject;
+
+ import libraries.uanalytics.tracking.Configuration;
+
+ /**
+ * Utility function to debug and/or reset the SharedObject
+ * storage.
+ *
+ * @param show show informations and datas of the sotrage (default to true
).
+ * @param reset clear the storage from its data (default to false
).
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function DebugSharedObjectStorage( show:Boolean = true,
+ reset:Boolean = false ):void
+ {
+ var conf:Configuration = new Configuration();
+ var so:SharedObject = SharedObject.getLocal( conf.storageName );
+
+ if( show )
+ {
+ trace( "SharedObject: " + conf.storageName );
+ trace( "size: " + so.size + " bytes" );
+ trace( "data:" );
+ for( var m:String in so.data )
+ {
+ trace( " |_ " + m + ": " + so.data[m] );
+ }
+ }
+
+ if( reset )
+ {
+ so.clear();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/addons/Twitter.as b/src/libraries/uanalytics/tracker/addons/Twitter.as
new file mode 100644
index 0000000..188c3f8
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/addons/Twitter.as
@@ -0,0 +1,208 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker.addons
+{
+ import libraries.uanalytics.tracking.AnalyticsTracker;
+
+ /**
+ * Helper class to send Twitter social hits.
+ *
+ * 80
).
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DEFAULT_PORT:int = 80;
+
+ /**
+ * The default HTTPS port (443
).
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SECURE_PORT:int = 443;
+
+ /**
+ * An Analytics tracker.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ protected var _tracker:AnalyticsTracker;
+
+ private var _enableErrorChecking:Boolean;
+ private var _debug:Boolean;
+ private var _verbose:Boolean;
+
+ private var _connected:Boolean;
+
+ private var _addrlist:Array;
+ private var _sockfd:int;
+ private var _info:addrinfo;
+
+ private var _localAddress:String;
+ private var _localPort:int;
+
+ private var _remoteAddress:String;
+ private var _remotePort:int;
+
+ private var _remoteAddresses:Array;
+
+ /**
+ * Creates a BSDSocketHitSender.
+ *
+ * @param tracker an analytics tracker
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function BSDSocketHitSender( tracker:AnalyticsTracker )
+ {
+ super();
+ _tracker = tracker;
+
+ _enableErrorChecking = false;
+ _debug = false;
+ _verbose = false;
+ _reset();
+ }
+
+ /**
+ * Function hook for the socket "connect" event.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public var onConnect:Function;/* = function():void
+ {
+ trace( "onConnect()" );
+ }*/
+
+ /**
+ * Function hook for the socket "disconnect" event.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public var onDisconnect:Function;/* = function():void
+ {
+ trace( "onDisconnect()" );
+ }*/
+
+ /**
+ * Function hook for the socket "send" event.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public var onSend:Function;/* = function():void
+ {
+ trace( "onSend( bytes:ByteArray, total:int )" );
+ }*/
+
+ /**
+ * Function hook for the socket "receive" event.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public var onReceive:Function;/* = function():void
+ {
+ trace( "onReceive( bytes:ByteArray, total:int )" );
+ }*/
+
+ private function _reset():void
+ {
+ _connected = false;
+
+ _addrlist = null;
+ _sockfd = -1;
+ _info = null;
+
+ _localAddress = "";
+ _localPort = -1;
+ _remoteAddress = "";
+ _remotePort = -1;
+
+ _remoteAddresses = null;
+ }
+
+ private function _open( hostname:String, port:String ):int
+ {
+ var hints:addrinfo = new addrinfo();
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = AF_UNSPEC;
+
+ var eaierr:CEAIrror = new CEAIrror();
+ var addrlist:Array = getaddrinfo( hostname, port, hints, eaierr );
+
+ if( !addrlist )
+ {
+ if( enableErrorChecking ) { throw eaierr; }
+
+ return -1;
+ }
+
+ _addrlist = addrlist;
+
+ var i:uint;
+ var info:addrinfo;
+ var sockfd:int;
+ var result:int;
+
+ for( i = 0; i < addrlist.length; i++ )
+ {
+ info = addrlist[i];
+
+ sockfd = socket( info.ai_family, info.ai_socktype, info.ai_protocol );
+ if( sockfd < 0 )
+ {
+ var e:CError = new CError( "", errno );
+ if( enableErrorChecking ) { throw e; }
+
+ return -1;
+ }
+
+ result = connect( sockfd, info.ai_addr );
+ if( result < 0 )
+ {
+ var e:CError = new CError( "", errno );
+ if( enableErrorChecking ) { throw e; }
+
+ return -1;
+ }
+ break;
+ }
+
+ _info = info;
+
+ var a:String = inet_ntop( _info.ai_family, _info.ai_addr );
+ if( !a )
+ {
+ var e:CError = new CError( "", errno );
+ if( enableErrorChecking ) { throw e; }
+ }
+ else
+ {
+ _remoteAddress = a;
+ }
+
+ _remotePort = ntohs( _info.ai_addr.sin_port );
+
+ return sockfd;
+ }
+
+ private function _findLocalAddressAndPort():void
+ {
+ var addr:sockaddr_in = new sockaddr_in();
+
+ var result:int = getsockname( _sockfd, addr );
+ if( result == -1 )
+ {
+ var e:CError = new CError( "", errno );
+ if( enableErrorChecking ) { throw e; }
+ }
+ else
+ {
+ var a:String = inet_ntop( addr.sin_family, addr );
+ if( !a )
+ {
+ var e:CError = new CError( "", errno );
+ if( enableErrorChecking ) { throw e; }
+ }
+ else
+ {
+ _localAddress = a;
+ }
+
+ _localPort = ntohs( addr.sin_port );
+ }
+ }
+
+ private function _receiveAll( socket:int, bytes:ByteArray, len:int = 8192, flags:int = 0 ):int
+ {
+ var total:uint = 0; // how many bytes we received
+ var n:int;
+ var b:ByteArray = new ByteArray();
+
+ var run:Boolean = true;
+ while( run )
+ {
+ b.clear();
+ n = recv( socket, b, len, flags );
+
+ if( n == -1 ) { run = false; break; }
+ bytes.writeBytes( b );
+ total += n;
+ if( n == 0 ) { run = false; break; }
+ }
+
+ b.clear();
+
+ if( n < 0 )
+ {
+ return -1; //failure
+ }
+
+ return total; // number of bytes actually received
+ }
+
+ /**
+ * Specifies whether errors encountered by the sockets are reported
+ * to the application.
+ *
+ * true
methods are synchronous
+ * and can throw errors. When enableErrorChecking is false
,
+ * the default, the methods are asynchronous and errors are not reported.
+ * /debug/collect
+ * instead of /collect
.
+ *
+ * true
, allows to send the
+ * hit requests to the Measurement Protocol Validation Server.
+ * true
, will print the details
+ * of the hit request to the standard output.
+ * host
on a specific port
.
+ *
+ * onConnect()
function if defined.
+ * 80
).
+ *
+ * Errors
+ * "CEAIrror: EAI_NONAME #8: nodename nor servname provided, or not known"
+ * the host provided was not found
+ *
+ * "CError: ETIMEDOUT #60: Operation timed out"
+ * most likely the port provided is not opne on this particular host
+ * (for ex: try to connect on www.comain.com on port 8080 when only port 80 is open)
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ protected function open( host:String, port:int = -1 ):void
+ {
+ //trace( "HttpConnection.open()" );
+
+ if( port == -1 )
+ {
+ port = DEFAULT_PORT;
+ }
+
+ var sockfd:int = _open( host, String( port ) );
+
+ if( sockfd == -1 )
+ {
+ //trace( "Could not connect" );
+ if( enableErrorChecking )
+ {
+ throw new Error( "Could not connect to " + host + ":" + port );
+ }
+ }
+ else
+ {
+ _sockfd = sockfd;
+ _connected = true;
+ _findLocalAddressAndPort();
+
+ if( onConnect ) { this.onConnect(); }
+ }
+ }
+
+ /**
+ * Close the connection.
+ *
+ * onDisconnect()
function if defined.
+ * onReceive()
function if defined.
+ * HitSender
based on the cURL command-line tool.
+ *
+ *
+ * Mainly to be able to test with the Measurement Protocol Validation Server
+ * which works only with HTTPS, and/or if you absolutely have to use HTTPS.
+ * DebugHitSender
will send hit requests
+ * to the Measurement Protocol Validation Server.
+ *
+ * /debug/collect
+ * instead of /collect
.
+ * Hits sent to the Measurement Protocol Validation Server will not show up
+ * in reports. They are for debugging only.
+ *
+ *
+ *
+ *
+ *
+ *
+ * Security.sandboxType
to
+ * know if the SWF file has been published with Security.LOCAL_WITH_FILE
+ * or Security.LOCAL_WITH_NETWORK
+ *
+ * When you use the Loader class, consider the Flash Player
+ * and Adobe AIR security model:
+ *
+ * - You can load content from any accessible source.
+ *
+ * - Loading is not allowed if the calling SWF file is in a network sandbox
+ * and the file to be loaded is local.
+ *
+ * - If the loaded content is a SWF file written with ActionScript 3.0,
+ * it cannot be cross-scripted by a SWF file in another security sandbox
+ * unless that cross-scripting arrangement was approved through a call
+ * to the System.allowDomain() or the System.allowInsecureDomain() method
+ * in the loaded content file.
+ *
+ * - If the loaded content is an AVM1 SWF file
+ * (written using ActionScript 1.0 or 2.0), it cannot be cross-scripted
+ * by an AVM2 SWF file (written using ActionScript 3.0). However, you
+ * can communicate between the two SWF files by using the LocalConnection class.
+ *
+ * - If the loaded content is an image, its data cannot be accessed by a
+ * SWF file outside of the security sandbox, unless the domain of that
+ * SWF file was included in a URL policy file at the origin domain of
+ * the image.
+ *
+ * - Movie clips in the local-with-file-system sandbox cannot script movie
+ * clips in the local-with-networking sandbox, and the reverse is also
+ * prevented.
+ *
+ * - You cannot connect to commonly reserved ports. For a complete list of
+ * blocked ports, see “Restricting Networking APIs” in the ActionScript
+ * 3.0 Developer’s Guide.
+ *
+ * However, in AIR, content in the application security sandbox
+ * (content installed with the AIR application) are not restricted by these
+ * security limitations.
+ *
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html Loader
+ * @see http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3f.html Security sandboxes
+ * @see http://help.adobe.com/en_US/as3/dev/WS1EFE2EDA-026D-4d14-864E-79DFD56F87C6.html Restricting networking APIs
+ */
+ public class LoaderHitSender extends HitSender
+ {
+
+ /**
+ * An Analytics tracker.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _tracker:AnalyticsTracker;
+
+ /**
+ * A Loader.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _loader:Loader;
+
+ /**
+ * Creates a LoaderHitSender.
+ *
+ * @param tracker an analytics tracker
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function LoaderHitSender( tracker:AnalyticsTracker )
+ {
+ super();
+ _tracker = tracker;
+ _loader = new Loader();
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function _hookEvents():void
+ {
+ _loader.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError );
+
+ _loader.contentLoaderInfo.addEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ _loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function _unhookEvents():void
+ {
+ _loader.uncaughtErrorEvents.removeEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError );
+
+ _loader.contentLoaderInfo.removeEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ _loader.contentLoaderInfo.removeEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.contentLoaderInfo.removeEventListener( Event.COMPLETE, onComplete );
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onUncaughtError( event:UncaughtErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+
+ var error:Error;
+
+ if( event.error is Error )
+ {
+ error = event.error as Error;
+ }
+ else if( event.error is ErrorEvent )
+ {
+ var errorEvent:ErrorEvent = event.error as ErrorEvent;
+ error = new Error( errorEvent.text, errorEvent.errorID );
+ }
+ else
+ {
+ error = new Error( "a non-Error, non-ErrorEvent type was thrown and uncaught" );
+ }
+
+ if( _tracker.config.enableErrorChecking )
+ {
+ throw error;
+ }
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onHTTPStatus( event:HTTPStatusEvent ):void
+ {
+ /* Note:
+ An advanced implementation could detect the HTTP status code
+ and if not equal to 200 block any following hit requests.
+
+ see:
+ Response Codes https://developers.google.com/analytics/devguides/collection/protocol/v1/reference#response-codes
+
+ The Measurement Protocol will return a 2xx status code if the
+ HTTP request was received.
+ The Measurement Protocol does not return an error code if the
+ payload data was malformed, or if the data in the payload was
+ incorrect or was not processed by Google Analytics.
+
+ If you do not get a 2xx status code, you should NOT retry the request.
+ Instead, you should stop and correct any errors in your HTTP request.
+ */
+ /*
+ if( event.status == 200 )
+ {
+ // do something here
+ }
+ */
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onIOError( event:IOErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+
+ if( _tracker.config.enableErrorChecking )
+ {
+ var error:IOError = new IOError( event.text, event.errorID );
+ throw error;
+ }
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onComplete( event:Event ):void
+ {
+ /* Note:
+ We are done and so we want to unhook all our events
+ */
+ _unhookEvents();
+ }
+
+ /** @inheritDoc */
+ public override function send( model:HitModel ):void
+ {
+ var payload:String = _buildHit( model );
+ var url:String = "";
+
+ /* Note:
+ It is more performant to send a GET request
+ so by default we want to send a GET request
+ */
+ var sendViaPOST:Boolean = false;
+
+ /* Note:
+ unless we forcePOST
+ or the payload size is bigger than maxGETlength (2000 bytes)
+ then we send a POST request
+ */
+ if( _tracker.config.forcePOST ||
+ (payload.length > _tracker.config.maxGETlength) )
+ {
+ sendViaPOST = true;
+ }
+
+ /* Note:
+ if payload is bigger than maxPOSTlength (8192 bytes)
+ Google Analytics backend will ignore the request
+ */
+ if( payload.length > _tracker.config.maxPOSTlength )
+ {
+ throw new ArgumentError( "POST data is bigger than " + _tracker.config.maxPOSTlength + " bytes." );
+ }
+
+ if( _tracker.config.forceSSL )
+ {
+ url = _tracker.config.secureEndpoint;
+ }
+ else
+ {
+ url = _tracker.config.endpoint;
+ }
+
+ // we build the request
+ var request:URLRequest = new URLRequest();
+ request.url = url;
+
+ if( sendViaPOST )
+ {
+ request.method = URLRequestMethod.POST;
+ }
+ else
+ {
+ request.method = URLRequestMethod.GET;
+ }
+
+ request.data = payload;
+
+ _hookEvents();
+ var err:* = null;
+
+ /* Note:
+ Here we wrap the sender call in a try/catch
+ only to remove our event listeners if an error occur
+ but we do want to throw errors.
+
+ this is not the same as config.enableErrorChecking
+ in a tracker.
+ */
+ try
+ {
+ // we send the request
+ _loader.load( request );
+ }
+ catch( e:IOError )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "IOError: " + e.message );
+ err = e;
+ }
+ catch( e:SecurityError )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "SecurityError: " + e.message );
+ err = e;
+ }
+ catch( e:IllegalOperationError )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "IllegalOperationError: " + e.message );
+ err = e;
+ }
+ catch( e:Error )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "Error: " + e.message );
+ err = e;
+ }
+
+ // a HitSender always throw errors
+ if( err )
+ {
+ throw err;
+ }
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/senders/TraceHitSender.as b/src/libraries/uanalytics/tracker/senders/TraceHitSender.as
new file mode 100644
index 0000000..939a158
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/senders/TraceHitSender.as
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker.senders
+{
+ import libraries.uanalytics.tracking.AnalyticsTracker;
+ import libraries.uanalytics.tracking.Configuration;
+ import libraries.uanalytics.tracking.HitModel;
+ import libraries.uanalytics.tracking.HitSender;
+
+ /**
+ * A HitSender
that will trace the hit requests to the console
+ * output.
+ *
+ * hitSender
implemented with URLLoader
.
+ *
+ *
+ * When you use this class in Flash Player and in AIR application content
+ * in security sandboxes other than then application security sandbox,
+ * consider the following security model:
+ *
+ * - A SWF file in the local-with-filesystem sandbox may not load data
+ * from, or provide data to, a resource that is in the network sandbox.
+ *
+ * - By default, the calling SWF file and the URL you load must be in
+ * exactly the same domain. For example, a SWF file at www.adobe.com
+ * can load data only from sources that are also at www.adobe.com.
+ * To load data from a different domain, place a URL policy file on the
+ * server hosting the data.
+ *
+ *
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLLoader.html URLLoader
+ */
+ public class URLLoaderHitSender extends HitSender
+ {
+
+ /**
+ * An Analytics tracker.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _tracker:AnalyticsTracker;
+
+ /**
+ * A URLLoader.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _loader:URLLoader;
+
+ /**
+ * Creates a URLLoaderHitSender.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function URLLoaderHitSender( tracker:AnalyticsTracker )
+ {
+ super();
+ _tracker = tracker;
+ _loader = new URLLoader();
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function _hookEvents():void
+ {
+ _loader.addEventListener( Event.OPEN, onOpen );
+ _loader.addEventListener( ProgressEvent.PROGRESS , onProgress );
+ _loader.addEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ _loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
+ _loader.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.addEventListener( Event.COMPLETE, onComplete );
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function _unhookEvents():void
+ {
+ _loader.removeEventListener( Event.OPEN, onOpen );
+ _loader.removeEventListener( ProgressEvent.PROGRESS , onProgress );
+ _loader.removeEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ _loader.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
+ _loader.removeEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.removeEventListener( Event.COMPLETE, onComplete );
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onOpen( event:Event ):void
+ {
+ //nothing
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onProgress( event:ProgressEvent ):void
+ {
+ //nothing
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onHTTPStatus( event:HTTPStatusEvent ):void
+ {
+ /* Note:
+ Here you can deal with the HTTP response status
+ see comments in LoaderHitSender.onHTTPStatus()
+ */
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onSecurityError( event:SecurityErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onIOError( event:IOErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+ }
+
+ /**
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected function onComplete( event:Event ):void
+ {
+ /* Note:
+ We are done and so we want to unhook all our events
+ */
+ _unhookEvents();
+ }
+
+ /** @inheritDoc */
+ public override function send( model:HitModel ):void
+ {
+ var payload:String = _buildHit( model );
+ var url:String = "";
+
+ var sendViaPOST:Boolean = false;
+
+ if( _tracker.config.forcePOST ||
+ (payload.length > _tracker.config.maxGETlength) )
+ {
+ sendViaPOST = true;
+ }
+
+ if( payload.length > _tracker.config.maxPOSTlength )
+ {
+ throw new ArgumentError( "POST data is bigger than " + _tracker.config.maxPOSTlength + " bytes." );
+ }
+
+ if( _tracker.config.forceSSL )
+ {
+ url = _tracker.config.secureEndpoint;
+ }
+ else
+ {
+ url = _tracker.config.endpoint;
+ }
+
+ var request:URLRequest = new URLRequest();
+ request.url = url;
+
+ if( sendViaPOST )
+ {
+ request.method = URLRequestMethod.POST;
+ }
+ else
+ {
+ request.method = URLRequestMethod.GET;
+ }
+
+ request.data = payload;
+
+ _hookEvents();
+ var err:* = null;
+
+ try
+ {
+ _loader.load( request );
+ }
+ catch( e:Error )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "Error: " + e.message );
+ err = e;
+ }
+
+ if( err )
+ {
+ throw err;
+ }
+
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracker/senders/URLStreamHitSender.as b/src/libraries/uanalytics/tracker/senders/URLStreamHitSender.as
new file mode 100644
index 0000000..a238ad0
--- /dev/null
+++ b/src/libraries/uanalytics/tracker/senders/URLStreamHitSender.as
@@ -0,0 +1,232 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracker.senders
+{
+ import flash.errors.MemoryError;
+ import flash.events.Event;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.IOErrorEvent;
+ import flash.events.ProgressEvent;
+ import flash.events.SecurityErrorEvent;
+ import flash.net.URLRequest;
+ import flash.net.URLRequestMethod;
+ import flash.net.URLStream;
+
+ import libraries.uanalytics.tracking.AnalyticsTracker;
+ import libraries.uanalytics.tracking.HitModel;
+ import libraries.uanalytics.tracking.HitSender;
+
+ /**
+ * A hitSender
implemented with URLStream
.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLStream.html URLStream
+ */
+ public class URLStreamHitSender extends HitSender
+ {
+
+ /**
+ * An Analytics tracker.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _tracker:AnalyticsTracker;
+
+ /**
+ * A URLStream.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ protected var _loader:URLStream;
+
+ /**
+ * Creates a URLStreamHitSender.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function URLStreamHitSender( tracker:AnalyticsTracker )
+ {
+ super();
+ _tracker = tracker;
+ _loader = new URLStream();
+ }
+
+ protected function _hookEvents():void
+ {
+ _loader.addEventListener( Event.OPEN, onOpen );
+ _loader.addEventListener( ProgressEvent.PROGRESS, onProgress );
+ _loader.addEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ //_loader.addEventListener( HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHTTPResponseStatus );
+ _loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
+ _loader.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.addEventListener( Event.COMPLETE, onComplete );
+ }
+
+ protected function _unhookEvents():void
+ {
+ _loader.removeEventListener( Event.OPEN, onOpen );
+ _loader.removeEventListener( ProgressEvent.PROGRESS, onProgress );
+ _loader.removeEventListener( HTTPStatusEvent.HTTP_STATUS, onHTTPStatus );
+ //_loader.removeEventListener( HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHTTPResponseStatus );
+ _loader.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
+ _loader.removeEventListener( IOErrorEvent.IO_ERROR, onIOError );
+ _loader.removeEventListener( Event.COMPLETE, onComplete );
+ }
+
+ protected function onOpen( event:Event ):void
+ {
+ //trace( "onOpen()" );
+ }
+
+ protected function onProgress( event:ProgressEvent ):void
+ {
+ //trace( "onProgress()" );
+ }
+
+ protected function onHTTPStatus( event:HTTPStatusEvent ):void
+ {
+ //trace( "onHTTPStatus()" );
+ }
+
+ protected function onHTTPResponseStatus( event:HTTPStatusEvent ):void
+ {
+ //trace( "onHTTPResponseStatus()" );
+ }
+
+ protected function onSecurityError( event:SecurityErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+ //trace( "onSecurityError()" );
+ }
+
+ protected function onIOError( event:IOErrorEvent ):void
+ {
+ /* Note:
+ An error occured and so we want to unhook all our events
+ */
+ _unhookEvents();
+ //trace( "onIOError()" );
+ }
+
+ protected function onComplete( event:Event ):void
+ {
+ /* Note:
+ We are done and so we want to unhook all our events
+ */
+ _unhookEvents();
+ //trace( "onComplete()" );
+ }
+
+ /** @inheritDoc */
+ public override function send( model:HitModel ):void
+ {
+ var payload:String = _buildHit( model );
+ var url:String = "";
+
+ var sendViaPOST:Boolean = false;
+
+ if( _tracker.config.forcePOST ||
+ (payload.length > _tracker.config.maxGETlength) )
+ {
+ sendViaPOST = true;
+ }
+
+ if( payload.length > _tracker.config.maxPOSTlength )
+ {
+ throw new ArgumentError( "POST data is bigger than " + _tracker.config.maxPOSTlength + " bytes." );
+ }
+
+ if( _tracker.config.forceSSL )
+ {
+ url = _tracker.config.secureEndpoint;
+ }
+ else
+ {
+ url = _tracker.config.endpoint;
+ }
+
+ var request:URLRequest = new URLRequest();
+ request.url = url;
+
+ if( sendViaPOST )
+ {
+ request.method = URLRequestMethod.POST;
+ }
+ else
+ {
+ request.method = URLRequestMethod.GET;
+ }
+
+ request.data = payload;
+
+ _hookEvents();
+ var err:* = null;
+
+ try
+ {
+ _loader.load( request );
+ }
+ catch( e:ArgumentError )
+ {
+ _unhookEvents();
+ //trace( "objects may not contain certain prohibited HTTP request headers." );
+ //trace( "ArgumentError: " + e.message );
+ err = e;
+ }
+ catch( e:MemoryError )
+ {
+ _unhookEvents();
+ /*
+ if( request.method == URLRequestMethod.GET )
+ {
+ trace( "cannot convert the URLRequest.data parameter from UTF8 to MBCS." );
+ }
+ else if( request.method == URLRequestMethod.POST )
+ {
+ trace( "cannot allocate memory for the POST data." );
+ }
+ */
+
+ //trace( "MemoryError: " + e.message );
+ err = e;
+ }
+ catch( e:SecurityError )
+ {
+ _unhookEvents();
+ //trace( "Local untrusted SWF files may not communicate with the Internet." );
+ //trace( "OR" );
+ //trace( "You are trying to connect to a commonly reserved port." );
+ //trace( "Error: " + e.message );
+ err = e;
+ }
+ catch( e:Error )
+ {
+ _unhookEvents();
+ //trace( "unable to load requested page." );
+ //trace( "Error: " + e.message );
+ err = e;
+ }
+
+ if( err )
+ {
+ throw err;
+ }
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracking/AnalyticsSender.as b/src/libraries/uanalytics/tracking/AnalyticsSender.as
new file mode 100644
index 0000000..fa05217
--- /dev/null
+++ b/src/libraries/uanalytics/tracking/AnalyticsSender.as
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracking
+{
+
+ /**
+ * The contract to send a hit request to Google Analytics servers.
+ *
+ * URLLoaderHitSender
,
+ * for a Redtamarin implementation see BSDSocketHitSender
.
+ *
+ *
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see libraries.uanalytics.tracker.DefaultTracker DefaultTracker
+ * @see libraries.uanalytics.tracker.WebTracker WebTracker
+ * @see libraries.uanalytics.tracker.AppTracker AppTracker
+ * @see libraries.uanalytics.tracker.CliTracker CliTracker
+ */
+ public interface AnalyticsTracker
+ {
+
+ /**
+ * The Tracking ID / Web Property ID.
+ *
+ * ApplicationInfo
(optional)
+ *
+ * @return false if the hit has not been sent due to sampling
+ * or other reasons.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ function screenview( name:String, appinfo:Dictionary = null ):Boolean;
+
+ /**
+ * Send an event hit.
+ *
+ * true
if the exception was fatal.
+ *
+ * @return false if the hit has not been sent due to sampling
+ * or other reasons.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ function exception( description:String = "",
+ isFatal:Boolean = true ):Boolean;
+
+ /**
+ * Send a timing hit.
+ *
+ * TimingInfo
(optional)
+ *
+ * @return false if the hit has not been sent due to sampling
+ * or other reasons.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ function timing( category:String, name:String, value:int,
+ label:String = "",
+ timinginfo:Dictionary = null ):Boolean;
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/tracking/Configuration.as b/src/libraries/uanalytics/tracking/Configuration.as
new file mode 100644
index 0000000..2df569c
--- /dev/null
+++ b/src/libraries/uanalytics/tracking/Configuration.as
@@ -0,0 +1,357 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package libraries.uanalytics.tracking
+{
+ /**
+ * Analytics Tracking Configuration.
+ *
+ *
+ * It is possible to overide them and provide your own configuration.
+ * _v
parameters
+ * to every hitSender
requests.
+ * HitSender
+ * used by the tracker.
+ *
+ * HitSender
:
+ * LoaderHitSender
for Flash and AIR,
+ * BSDSocketHitSender
for Redtamarin.
+ * HitSender
you need to provide the full
+ * class path, for example if oyu want to use TraceHitSender
+ * use the string "libraries.uanalytics.tracker.senders.TraceHitSender",
+ * not just "TraceHitSender".
+ *
+ * You will have to define a reference to this HitSender
+ * in your code, otherwise the code reflection will not be able to find
+ * it in memory.
+ * false
, we don't want the tracker
+ * to throw any errors at all.
+ * RateLimiter
will ensure
+ * the tracker does not send too many hits at once.
+ *
+ * true
, each trackers define by default the
+ * capacity, rate and span of the number of hits that can be send.
+ * true
, each tracker will use the sampleRate
+ * to select a subset (in percentage) of data to send.
+ * false
, as in general we don't need it.
+ * Also note that a cache buster will be used only with GET requests,
+ * not with POST requests.
+ * true
will force the HitSender
+ * to use the HTTPS protocol.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public var forceSSL:Boolean = false;
+
+ /**
+ * Setting this property to true
will force the HitSender
+ * to use send requests using POST.
+ *
+ * maxGETlength
+ * and if the payload data is bigger the tracker will automatically switch
+ * to POST.
+ * true
the IP address of the sender will be anonymized.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see Tracker#ANON_IP Tracker.ANON_IP
+ */
+ public var anonymizeIp:Boolean = false;
+
+ /**
+ * Allows to override the IP address of the user.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see Tracker#IP_OVERRIDE Tracker.IP_OVERRIDE
+ */
+ public var overrideIpAddress:String = "";
+
+ /**
+ * Allows to override the User Agent of the browser.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see Tracker#USER_AGENT_OVERRIDE Tracker.USER_AGENT_OVERRIDE
+ */
+ public var overrideUserAgent:String = "";
+
+ /**
+ * Allows to override the geographical location of the user.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see Tracker#GEOGRAPHICAL_OVERRIDE Tracker.GEOGRAPHICAL_OVERRIDE
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/geoid Geographical Targeting
+ */
+ public var overrideGeographicalId:String = "";
+
+
+ /* read-only */
+
+ /**
+ * The URL Endpoint where to send the HTTP requests.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/reference#endpoint URL Endpoint
+ */
+ public function get endpoint():String { return _endpoint; }
+
+ /**
+ * The Secure URL Endpoint where to send the HTTPS requests.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/reference#endpoint URL Endpoint
+ */
+ public function get secureEndpoint():String { return _secureEndpoint; }
+
+ /**
+ * The length of the entire encoded URL must be no longer than 2000 Bytes.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/reference#get GET
+ */
+ public function get maxGETlength():uint { return _maxGETlength; }
+
+ /**
+ * The POST body of a request must be no longer than 8192 bytes.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see http://developers.google.com/analytics/devguides/collection/protocol/v1/reference#using-post using POST
+ */
+ public function get maxPOSTlength():uint { return _maxPOSTlength; }
+
+ /**
+ * The name of the storage container.
+ *
+ * SharedObject
, File, DataBase, etc.
+ * Tracker
class.
+ * You may also use your own field names to store information in the data
+ * model but they will not be sent in the tracking beacon.
+ * set
method for a description of possible field
+ * names.
+ * HitModel
to this model.
+ *
+ * @param model the model to add.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function add( model:HitModel ):void
+ {
+ for( var key:String in model._data )
+ {
+ _data[ key ] = model._data[ key ];
+ }
+ }
+
+ /**
+ * Returns a new copy of this HitModel
with all the same
+ * fields set.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function clone():HitModel
+ {
+ var copy:HitModel = new HitModel();
+
+ for( var key:String in _data )
+ {
+ copy._data[ key ] = _data[ key ];
+ }
+
+ return copy;
+ }
+
+ /**
+ * Clear all the fields set in the model.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function clear():void
+ {
+ _data = new Dictionary();
+ }
+
+ /**
+ * Returns all of the field names currently set in the model.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function getFieldNames():Vector.Tracker.CLIENT_ID
field.
+ * This means that either all or none of the hits from a particular client
+ * will be sent.
+ * Configuration
,
+ * you can edit the configuration to use something else than the
+ * default (100%).
+ * parseFloat()
+ * except that trailing non-numeric characters are not ignored and return NaN.
+ *
+ * @param The string to read and convert to a Number.
+ * @return A number or NaN (not a number).
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ private static function _parseNumber( str:String ):Number
+ {
+ if( str == "" ) { return NaN; }
+
+ var i:uint;
+ var l:uint = str.length;
+ var dot:uint = 0;
+ for( i=0; iSAMPLE_RATE
field.
+ *
+ * Values will be rounded to the nearest 100th.
+ * Invalid numbers will return 0
.
+ * Values greater than 100 will return 100
.
+ *
+ * To be considered as an abstract class to extend from. + *
+ * + * @example Usage + * + *+ * Do not use or instanciate this class directly, extend it instead. + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function HitSender() + { + super(); + } + + /** + * Adds the named query parameter and value to the specified String. + * This take care of URL encoding special characters. + * + * @param name the HitModel key name. + * @param value the field value. + * + * @return a string formated such as&NAME=VALUE
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ protected function _addParameter( name:String, value:String ):String
+ {
+ var str:String = "";
+ str += "&";
+ str += _appendEncoded( name.substring(1) );
+ str += "=";
+ str += _appendEncoded( value );
+
+ return str;
+ }
+
+ /**
+ * URL encodes the specified value.
+ *
+ * @param value the value to encode.
+ *
+ * @return the value URL encoded.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ protected function _appendEncoded( value:String ):String
+ {
+ return encodeURIComponent( value );
+ }
+
+ /**
+ * Build the hit payload from the hit model. The payload can be sent
+ * via either setting this as the body of an HTTP POST request or
+ * as the query parameter string of the request.
+ *
+ * @param model the HitModel to send.
+ *
+ * @return the payload representation that is used to send the hit.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ protected function _buildHit( model:HitModel ):String
+ {
+ var str:String = "";
+
+ // This library supports version 1 of the tracking API.
+ str += "v=1";
+
+ if( Configuration.SDKversion != "" )
+ {
+ // Identify the client library version.
+ str += _addParameter( "&_v", Configuration.SDKversion );
+ }
+
+ var names:Vector.+ * For example, the field named "&sr" specify the screen resolution + * which is sent as the URL query parameter name "sr" in the tracking API. + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public static const FIELD_PREFIX:String = "&"; + + /** + * A map from field name to parameter. + * + *+ * Eg. "screenResolution" to "&sr". + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + private var _nameToParameterMap:Dictionary = new Dictionary(); + + /** + * A map from a regular expression to a query parameter name. + * + *+ * Eg. "metric([0-9])+" to "&cm". + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + private var _patternToParameterMap:Dictionary = new Dictionary(); + + /** + * Creates the default Metadata. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function Metadata() + { + super(); + + // General + addAlias( Tracker.PROTOCOL_VERSION, "v" ); + addAlias( Tracker.TRACKING_ID, "tid" ); + addAlias( Tracker.ANON_IP, "aip" ); + addAlias( Tracker.DATA_SOURCE, "ds" ); + addAlias( Tracker.QUEUE_TIME, "qt" ); + addAlias( Tracker.CACHE_BUSTER, "z" ); + + // User + addAlias( Tracker.CLIENT_ID, "cid" ); + addAlias( Tracker.USER_ID, "uid" ); + + // Session + addAlias( Tracker.SESSION_CONTROL, "sc" ); + addAlias( Tracker.IP_OVERRIDE, "uip" ); + addAlias( Tracker.USER_AGENT_OVERRIDE, "ua" ); + addAlias( Tracker.GEOGRAPHICAL_OVERRIDE, "geoid" ); + + // Traffic Sources + addAlias( Tracker.DOCUMENT_REFERRER, "dr" ); + addAlias( Tracker.CAMPAIGN_NAME, "cn" ); + addAlias( Tracker.CAMPAIGN_SOURCE, "cs" ); + addAlias( Tracker.CAMPAIGN_MEDIUM, "cm" ); + addAlias( Tracker.CAMPAIGN_KEYWORD, "ck" ); + addAlias( Tracker.CAMPAIGN_CONTENT, "cc" ); + addAlias( Tracker.CAMPAIGN_ID, "ci" ); + addAlias( Tracker.GOOGLE_ADWORDS_ID, "gclid" ); + addAlias( Tracker.GOOGLE_DISPLAY_ADS_ID, "dclid" ); + + // System Info + addAlias( Tracker.SCREEN_RESOLUTION, "sr" ); + addAlias( Tracker.VIEWPORT_SIZE, "vp" ); + addAlias( Tracker.DOCUMENT_ENCODING, "de" ); + addAlias( Tracker.SCREEN_COLORS, "sd" ); + addAlias( Tracker.USER_LANGUAGE, "ul" ); + addAlias( Tracker.JAVA_ENABLED, "je" ); + addAlias( Tracker.FLASH_VERSION, "fl" ); + + // Hit + addAlias( Tracker.HIT_TYPE, "t" ); + addAlias( Tracker.NON_INTERACTION, "ni" ); + + // Content Information + addAlias( Tracker.DOCUMENT_LOCATION, "dl" ); + addAlias( Tracker.DOCUMENT_HOSTNAME, "dh" ); + addAlias( Tracker.DOCUMENT_PATH, "dp" ); + addAlias( Tracker.DOCUMENT_TITLE, "dt" ); + addAlias( Tracker.SCREEN_NAME, "cd" ); + addAlias( Tracker.LINK_ID, "linkid" ); + + // App Tracking + addAlias( Tracker.APP_NAME, "an" ); + addAlias( Tracker.APP_ID, "aid" ); + addAlias( Tracker.APP_VERSION, "av" ); + addAlias( Tracker.APP_INSTALLER_ID, "aiid" ); + + // Event Tracking + addAlias( Tracker.EVENT_CATEGORY, "ec" ); + addAlias( Tracker.EVENT_ACTION, "ea" ); + addAlias( Tracker.EVENT_LABEL, "el" ); + addAlias( Tracker.EVENT_VALUE, "ev" ); + + // E-Commerce + addAlias( Tracker.TRANSACTION_ID, "ti" ); + addAlias( Tracker.TRANSACTION_AFFILIATION, "ta" ); + addAlias( Tracker.TRANSACTION_REVENUE, "tr" ); + addAlias( Tracker.TRANSACTION_SHIPPING, "ts" ); + addAlias( Tracker.TRANSACTION_TAX, "tt" ); + addAlias( Tracker.ITEM_NAME, "in" ); + addAlias( Tracker.ITEM_PRICE, "ip" ); + addAlias( Tracker.ITEM_QUANTITY, "iq" ); + addAlias( Tracker.ITEM_CODE, "ic" ); + addAlias( Tracker.ITEM_CATEGORY, "iv" ); + addAlias( Tracker.CURRENCY_CODE, "cu" ); + + // Enhanced E-Commerce (not completely supported yet) + // Product SKU + // Product Name + // Product Brand + // Product Category + // Product Variant + // Product Price + // Product Quantity + // Product Coupon Code + // Product Position + // Product Custom Dimension + // Product Custom Metric + addAlias( Tracker.PRODUCT_ACTION, "pa" ); + // Transaction ID - duplicate + // Affiliation - duplicate + // Revenue - duplicate + // Tax - duplicate + // Shipping - duplicate + addAlias( Tracker.COUPON_CODE, "tcc" ); + addAlias( Tracker.PRODUCT_ACTION_LIST, "pal" ); + addAlias( Tracker.CHECKOUT_STEP, "cos" ); + addAlias( Tracker.CHECKOUT_STEP_OPTION, "col" ); + // Product Impression List Name + // Product Impression SKU + // Product Impression Name + // Product Impression Brand + // Product Impression Category + // Product Impression Variant + // Product Impression Position + // Product Impression Price + // Product Impression Custom Dimension + // Product Impression Custom Metric + // Promotion ID + // Promotion Name + // Promotion Creative + // Promotion Position + addAlias( Tracker.PROMOTION_ACTION, "promoa" ); + + // Social Interactions + addAlias( Tracker.SOCIAL_NETWORK, "sn" ); + addAlias( Tracker.SOCIAL_ACTION, "sa" ); + addAlias( Tracker.SOCIAL_TARGET, "st" ); + + // Timing + addAlias( Tracker.USER_TIMING_CATEGORY, "utc" ); + addAlias( Tracker.USER_TIMING_VAR, "utv" ); + addAlias( Tracker.USER_TIMING_TIME, "utt" ); + addAlias( Tracker.USER_TIMING_LABEL, "utl" ); + addAlias( Tracker.PAGE_LOAD_TIME, "plt" ); + addAlias( Tracker.DNS_TIME, "dns" ); + addAlias( Tracker.PAGE_DOWNLOAD_TIME , "pdt" ); + addAlias( Tracker.REDIRECT_RESPONSE_TIME, "rrt" ); + addAlias( Tracker.TCP_CONNECT_TIME, "tcp" ); + addAlias( Tracker.SERVER_RESPONSE_TIME, "srt" ); + addAlias( Tracker.DOM_INTERACTIVE_TIME, "dit" ); + addAlias( Tracker.CONTENT_LOAD_TIME, "clt" ); + + // Exceptions + addAlias( Tracker.EXCEPT_DESCRIPTION, "exd" ); + addAlias( Tracker.EXCEPT_FATAL, "exf" ); + + // Custom Dimensions / Metrics + addPatternAlias( "dimension([0-9]+)", "cd" ); + addPatternAlias( "metric([0-9]+)", "cm" ); + //addPatternAlias( "contentGroup([0-9]+)", "cg" ); // not supported anymore? + + } + + /** + * Given a field name, return the key to use in the data model map based + * on whether the field name matches a registered regular expression. + * + * @param field the field name to find in pattern + * + * @return the key to use in the data model map based on whether the + * field name matches a registered regular expression. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + private function _getKeyFromPattern( field:String ):String + { + for( var pattern:String in _patternToParameterMap ) + { + var re:RegExp = new RegExp( pattern ); + var result:Object = re.exec( field ); + + if( result && result[1] ) + { + var param:String = FIELD_PREFIX + _patternToParameterMap[pattern] + result[1]; + addAlias( field, param ); + return param; + } + } + + return field; + } + + /** + * Add an alias in the data from field name to query parameter. + * + * @param field the field name + * @param parameter the associated parameter + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + protected function addAlias( field:String, parameter:String ):void + { + _nameToParameterMap[ field ] = FIELD_PREFIX + parameter; + } + + /** + * Add an alias in the data from field name regular expression + * to query parameter. + * + *+ * The pattern should have one group defined which will capture the + * portion of the field name to use as the suffix for the parameter. + *
+ * + *+ * For example, the field name "metric34" would match the pattern: + * "metric([0-9])+" with parameter prefix "cm" and would map the field + * to the parameter "cm34" + *
+ * + * @param pattern the pattern to match + * @param parameterPrefix the parameter prefix + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + protected function addPatternAlias( pattern:String, parameterPrefix:String ):void + { + _patternToParameterMap[ pattern ] = parameterPrefix; + } + + /** + * Given a field name, return the key to use in the data model map + * for which to store the field value. + * + * @param field the field name + * + * @return the key to use in the data model map + * for which to store the field value. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function getHitModelKey( field:String ):String + { + if( (field.length > 0) && (field.charAt(0) == FIELD_PREFIX) ) + { + return field; + } + + var key:String = _nameToParameterMap[ field ]; + + if( key == null ) + { + key = _getKeyFromPattern( field ); + } + + return key; + } + + } + +} \ No newline at end of file diff --git a/src/libraries/uanalytics/tracking/RateLimitError.as b/src/libraries/uanalytics/tracking/RateLimitError.as new file mode 100644 index 0000000..6f76743 --- /dev/null +++ b/src/libraries/uanalytics/tracking/RateLimitError.as @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package libraries.uanalytics.tracking +{ + /** + * An error that will be thrown when hits are being sent at too great a rate. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public class RateLimitError extends Error + { + prototype.name = "RateLimitError"; + + /** + * Creates a RateLimitError. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function RateLimitError( message:String = "", id:int = 0 ) + { + super( message, id ); + this.name = prototype.name; + } + } +} \ No newline at end of file diff --git a/src/libraries/uanalytics/tracking/RateLimiter.as b/src/libraries/uanalytics/tracking/RateLimiter.as new file mode 100644 index 0000000..80a7518 --- /dev/null +++ b/src/libraries/uanalytics/tracking/RateLimiter.as @@ -0,0 +1,131 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package libraries.uanalytics.tracking +{ + import flash.utils.getTimer; + + /** + * Implements a rate limiting mecanism that ensures the tracker + * does not send too many hits at once. + * + *+ * The mecanism is based on the token bucket algorithm, + * and allows you to send bursts of hits to Google Analytics, + * while preventing clients from sending data too quickly. + *
+ * + *
+ * Each tracker has a maximum limit for the number of requests it can send concurrently.
+ * The tracker also maintain a count of the number of concurrent hits that have been sent.
+ * As a hit is sent to Google Analytics, the count decreases by one.
+ * When the count is 0
, the maximum limit has been reached,
+ * and no new requests are sent.
+ * Then over a small period of time, the count is increased back to its original limit,
+ * allowing data to be sent again.
+ *
+ * The limiting rate is specified in each individual trackers.
+ * For the WebTracker
, we follow what is done with analytics.js,
+ * the tracker starts with 20
hits that are replenished at a rate of 2
hits per second.
+ * For the ApplicationTracker
, we follow what is done with the Android SDK and the iOS SDK,
+ * each trackers starts with 60
hits that are replenished at a rate of 1
hit every 2 seconds.
+ *
RateLimiter
with the specified maximum token capacity
+ * and a specified number of new tokens generated per second (rate
).
+ *
+ * + * The token count is initialized to the maximum token capacity. + *
+ * + * @param capacity maximum number of accumulated tokens. + * @param rate the number of additional tokens to regenerate per second. + * @param span the time span to generate tokens (default to 1 second) + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function RateLimiter( capacity:int, rate:int, span:Number = 1 ) + { + _capacity = capacity; + _rate = rate; + _span = span; + _tokenCount = capacity; + _lastTime = now(); + } + + /** + * Returns the number of milliseconds that have elapsed since the + * Flash runtime virtual machine for ActionScript 3.0 (AVM2) started. + * + *+ * Used internally for generating tokens and useful for testing purposes. + *
+ * + * @return a relative time in milliseconds. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + protected function now():int + { + return getTimer(); + } + + /** + * Attempt to consume a token and returntrue
if successful.
+ *
+ * + * A return value of false indicates that tokens are being consumed in excess + * of the defined limits. + *
+ * + * @return true if the rate limit has not been exceeded. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function consumeToken():Boolean + { + var now:int = now(); + var newTokens:int = Math.max( 0, (now - _lastTime) * ( (_rate * _span) / 1000) ); + _tokenCount = Math.min( _tokenCount + newTokens, _capacity ); + + if( _tokenCount > 0 ) + { + _tokenCount--; + _lastTime = now; + return true; + } + + return false; + } + + } + +} \ No newline at end of file diff --git a/src/libraries/uanalytics/tracking/Tracker.as b/src/libraries/uanalytics/tracking/Tracker.as new file mode 100644 index 0000000..4129ce9 --- /dev/null +++ b/src/libraries/uanalytics/tracking/Tracker.as @@ -0,0 +1,1936 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package libraries.uanalytics.tracking +{ + + import flash.utils.Dictionary; + + /** + * A base class for the Google Analytics tracker. + * + *
+ * To be considered as an abstract class that provides
+ * measurement protocol contants and utility methods
+ * related to the HitModel
.
+ *
+ * The Protocol version. + *
+ * + *
+ * The current value is '1'
.
+ * This will only change when there are changes made that are not
+ * backwards compatible.
+ *
v=1
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PROTOCOL_VERSION:String = "protocolVersion";
+
+ /**
+ * Required for all hit types.
+ * + * The tracking ID / web property ID. + *
+ * + *
+ * The format is UA-XXXX-Y
.
+ * All collected data is associated by this ID.
+ *
tid=UA-XXXX-Y
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRACKING_ID:String = "trackingId";
+
+ /**
+ * Optional.
+ * + * When present, the IP address of the sender will be anonymized. + *
+ * + *
+ * For example, the IP will be anonymized if any of the following
+ * parameters are present in the payload: &aip=
,
+ * &aip=0
, or &aip=1
+ *
aip=1
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ANON_IP:String = "anonymizeIp";
+
+ /**
+ * Optional.
+ * + * Indicates the data source of the hit. + *
+ * + *
+ * Hits sent from analytics.js will have data source set to 'web'
;
+ * hits sent from one of the mobile SDKs will have data source set to 'app'
.
+ *
ds=web
,
+ * ds=app
.
+ * ds=call%20center
,
+ * ds=crm
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DATA_SOURCE:String = "dataSource";
+
+ /**
+ * Optional.
+ * + * Used to collect offline / latent hits. + *
+ * + *+ * The value represents the time delta (in milliseconds) between when + * the hit being reported occurred and the time the hit was sent. + * The value must be greater than or equal to 0. + * Values greater than four hours may lead to hits not being processed. + *
+ * + * @example + *qt=560
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const QUEUE_TIME:String = "queueTime";
+
+ /**
+ * Optional.
+ * + * Used to send a random number in GET requests to ensure browsers and + * proxies don't cache hits. + *
+ * + *+ * It should be sent as the final parameter of the request since we've + * seen some 3rd party internet filtering software add additional + * parameters to HTTP requests incorrectly. + * This value is not used in reporting. + *
+ * + * @example + *z=289372387623
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CACHE_BUSTER:String = "cacheBuster";
+
+
+ // User
+
+ /**
+ * Required for all hit types.
+ * + * The Client ID anonymously identifies a particular user, device, + * or browser instance. + *
+ * + *+ * For the web, this is generally stored as a first-party cookie with a + * two-year expiration. + * For mobile apps, this is randomly generated for each particular + * instance of an application install. + * The value of this field should be a random UUID (version 4) as + * described in rfc4122. + *
+ * + * @example + *cid=35009a79-1a05-49d7-b876-2b884d0f825b
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CLIENT_ID:String = "clientId";
+
+ /**
+ * Optional.
+ * + * This is intended to be a known identifier for a user provided by + * the site owner/tracking library user. + *
+ * + *+ * It must not itself be PII (personally identifiable information). + * The value should never be persisted in GA cookies or other Analytics + * provided storage. + *
+ * + * @example + *uid=as8eknlll
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_ID:String = "userId";
+
+
+ // Session
+
+ /**
+ * Optional.
+ * + * Used to control the session duration. + *
+ * + *+ * A value of 'start' forces a new session to start with this hit + * and 'end' forces the current session to end with this hit. + * All other values are ignored. + *
+ * + * @example + *sc=start
, sc=end
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SESSION_CONTROL:String = "sessionControl";
+
+ /**
+ * Optional.
+ * + * The IP address of the user. + *
+ * + *
+ * This should be a valid IP address in IPv4 or IPv6 format.
+ * It will always be anonymized just as though aip
(anonymize IP)
+ * had been used.
+ *
uip=1.2.3.4
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const IP_OVERRIDE:String = "ipOverride";
+
+ /**
+ * Optional.
+ * + * The User Agent of the browser. + *
+ * + *+ * Note that Google has libraries to identify real user agents. + * Hand crafting your own agent could break at any time. + *
+ * + * @example + *ua=Opera%2F9.80%20%28Windows%20NT%206.0%29%20Presto%2F2.12.388%20Version%2F12.14
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_AGENT_OVERRIDE:String = "userAgentOverride";
+
+ /**
+ * Optional.
+ * + * The geographical location of the user. + *
+ * + *+ * The geographical ID should be a two letter country code or a + * criteria ID representing a city or region + * (see geoid). + * This parameter takes precedent over any location derived from IP + * address, including the IP Override parameter. + * An invalid code will result in geographical dimensions to be set to + * '(not set)'. + *
+ * + * @example + *geoid=21137
, geoid=US
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const GEOGRAPHICAL_OVERRIDE:String = "geographicalOverride";
+
+
+ // Traffic Sources
+
+ /**
+ * Optional.
+ * + * Specifies which referral source brought traffic to a website. + *
+ * + *+ * This value is also used to compute the traffic source. + * The format of this value is a URL. + *
+ * + * @example + *dr=http%3A%2F%2Fexample.com
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_REFERRER:String = "documentReferrer";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign name. + *
+ * + * @example + *cn=%28direct%29
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_NAME:String = "campaignName";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign source. + *
+ * + * @example + *cs=%28direct%29
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_SOURCE:String = "campaignSource";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign medium. + *
+ * + * @example + *cm=organic
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_MEDIUM:String = "campaignMedium";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign keyword. + *
+ * + * @example + *ck=Blue%20Shoes
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_KEYWORD:String = "campaignKeyword";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign content. + *
+ * + * @example + *cc=content
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_CONTENT:String = "campaignContent";
+
+ /**
+ * Optional.
+ * + * Specifies the campaign ID. + *
+ * + * @example + *ci=ID
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CAMPAIGN_ID:String = "campaignId";
+
+ /**
+ * Optional.
+ * + * Specifies the Google AdWords Id. + *
+ * + * @example + *gclid=CL6Q-OXyqKUCFcgK2goddQuoHg
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const GOOGLE_ADWORDS_ID:String = "googleAdwordsId";
+
+ /**
+ * Optional.
+ * + * Specifies the Google Display Ads Id. + *
+ * + * @example + *dclid=d_click_id
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const GOOGLE_DISPLAY_ADS_ID:String = "googleDisplayAdsId";
+
+
+ // System Info
+
+ /**
+ * Optional.
+ * + * Specifies the screen resolution. + *
+ * + * @example + *sr=800x600
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SCREEN_RESOLUTION:String = "screenResolution";
+
+ /**
+ * Optional.
+ * + * Specifies the viewable area of the browser / device. + *
+ * + * @example + *vp=123x456
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const VIEWPORT_SIZE:String = "viewportSize";
+
+ /**
+ * Optional.
+ * + * Specifies the character set used to encode the page / document. + *
+ * + * @example + *de=UTF-8
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_ENCODING:String = "documentEncoding";
+
+ /**
+ * Optional.
+ * + * Specifies the screen color depth. + *
+ * + * @example + *sd=24-bits
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SCREEN_COLORS:String = "screenColors";
+
+ /**
+ * Optional.
+ * + * Specifies the language. + *
+ * + * @example + *ul=en-us
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_LANGUAGE:String = "userLanguage";
+
+ /**
+ * Optional.
+ * + * Specifies whether Java was enabled. + *
+ * + * @example + *je=1
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const JAVA_ENABLED:String = "javaEnabled";
+
+ /**
+ * Optional.
+ * + * Specifies the flash version. + *
+ * + * @example + *fl=10%201%20r103
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const FLASH_VERSION:String = "flashVersion";
+
+
+ // Hit
+
+ /**
+ * Required for all hit types.
+ * + * The type of hit. Must be one of 'pageview', 'screenview', 'event', + * 'transaction', 'item', 'social', 'exception', 'timing'. + *
+ * + * @example + *t=pageview
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const HIT_TYPE:String = "hitType";
+
+ /**
+ * Optional.
+ * + * Specifies that a hit be considered non-interactive. + *
+ * + * @example + *ni=1
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const NON_INTERACTION:String = "nonInteraction";
+
+
+ // Content Information
+
+ /**
+ * Optional.
+ * + * Use this parameter to send the full URL (document location) of the + * page on which content resides. + *
+ * + *
+ * You can use the dh
and dp
parameters to
+ * override the hostname and path + query portions of the document
+ * location, accordingly.
+ * The JavaScript clients determine this parameter using the
+ * concatenation of the document.location.origin +
+ * document.location.pathname + document.location.search
browser
+ * parameters.
+ * Be sure to remove any user authentication or other private information
+ * from the URL if present.
+ *
+ * For 'pageview' hits, either dl
+ * or both dh
and dp
have to be specified for
+ * the hit to be valid.
+ *
dl=http%3A%2F%2Ffoo.com%2Fhome%3Fa%3Db
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_LOCATION:String = "documentLocation";
+
+ /**
+ * Optional.
+ * + * Specifies the hostname from which content was hosted. + *
+ * + * @example + *dh=foo.com
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_HOSTNAME:String = "documentHostname";
+
+ /**
+ * Optional.
+ * + * The path portion of the page URL. + *
+ * + *
+ * Should begin with '/'.
+ * For 'pageview' hits, either dl
+ * or both dh
and dp
have to be specified for
+ * the hit to be valid.
+ *
dp=%2Ffoo
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_PATH:String = "documentPath";
+
+ /**
+ * Optional.
+ * + * The title of the page / document. + *
+ * + * @example + *dt=Settings
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOCUMENT_TITLE:String = "documentTitle";
+
+ /**
+ * Required for all hit types.
+ *
+ *
+ * This parameter is optional on web properties, and required on mobile
+ * properties for screenview hits, where it is used for the 'Screen Name'
+ * of the screenview hit.
+ *
+ * On web properties this will default to the unique URL of the page by
+ * either using the dl
parameter as-is
+ * or assembling it from dh
and dp
.
+ *
cd=High%20Scores
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SCREEN_NAME:String = "screenName"; //also: Content Description
+
+ /**
+ * Optional.
+ * + * The ID of a clicked DOM element. + *
+ * + *+ * Used to disambiguate multiple links to the same URL in + * In-Page Analytics reports when Enhanced Link Attribution is enabled + * for the property. + *
+ * + * @example + *linkid=nav_bar
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const LINK_ID:String = "linkId";
+
+
+ // App Tracking
+
+ /**
+ * Required for all hit types.
+ * + * Specifies the application name. + *
+ * + *+ * This field is required for all hit types sent to app properties. + * For hits sent to web properties, this field is optional. + *
+ * + * @example + *an=My%20App
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const APP_NAME:String = "appName";
+
+ /**
+ * Optional.
+ * + * Application identifier. + *
+ * + * @example + *aid=com.company.app
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const APP_ID:String = "appId";
+
+ /**
+ * Optional.
+ * + * Specifies the application version. + *
+ * + * @example + *av=1.2
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const APP_VERSION:String = "appVersion";
+
+ /**
+ * Optional.
+ * + * Application installer identifier. + *
+ * + * @example + *aiid=com.platform.vending
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const APP_INSTALLER_ID:String = "appInstallerId";
+
+
+ // Event Tracking
+
+ /**
+ * Required for event hit type.
+ * + * Specifies the event category. + *
+ * + *+ * Must not be empty. + *
+ * + * @example + *ec=Category
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EVENT_CATEGORY:String = "eventCategory";
+
+ /**
+ * Required for event hit type.
+ * + * Specifies the event action + *
+ * + *+ * Must not be empty. + *
+ * + * @example + *ea=Action
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EVENT_ACTION:String = "eventAction";
+
+ /**
+ * Optional.
+ * + * Specifies the event label. + *
+ * + * @example + *el=Label
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EVENT_LABEL:String = "eventLabel";
+
+ /**
+ * Optional.
+ * + * Specifies the event value. + *
+ * + *+ * Values must be non-negative. + *
+ * + * @example + *ev=55
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EVENT_VALUE:String = "eventValue";
+
+
+ // E-Commerce
+
+ /**
+ * Required for transaction hit type.
+ * Required for item hit type.
+ *+ * A unique identifier for the transaction. + *
+ * + *+ * This value should be the same for both the Transaction hit and + * Items hits associated to the particular transaction. + *
+ * + * @example + *ti=OD564
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRANSACTION_ID:String = "transactionId";
+
+ /**
+ * Optional.
+ * + * Specifies the affiliation or store name. + *
+ * + * @example + *ta=Member
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRANSACTION_AFFILIATION:String = "transactionAffiliation";
+
+ /**
+ * Optional.
+ * + * Specifies the total revenue associated with the transaction. + *
+ * + *+ * This value should include any shipping or tax costs. + *
+ * + * @example + *tr=15.47
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRANSACTION_REVENUE:String = "transactionRevenue";
+
+ /**
+ * Optional.
+ * + * Specifies the total shipping cost of the transaction. + *
+ * + * @example + *ts=3.50
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRANSACTION_SHIPPING:String = "transactionShipping";
+
+ /**
+ * Optional.
+ * + * Specifies the total tax of the transaction. + *
+ * + * @example + *tt=11.20
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TRANSACTION_TAX:String = "transactionTax";
+
+ /**
+ * Required for item hit type.
+ * + * Specifies the item name. + *
+ * + * @example + *in=Shoe
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ITEM_NAME:String = "itemName";
+
+ /**
+ * Optional.
+ * + * Specifies the price for a single item / unit. + *
+ * + * @example + *ip=3.50
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ITEM_PRICE:String = "itemPrice";
+
+ /**
+ * Optional.
+ * + * Specifies the number of items purchased. + *
+ * + * @example + *iq=4
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ITEM_QUANTITY:String = "itemQuantity";
+
+ /**
+ * Optional.
+ * + * Specifies the SKU or item code. + *
+ * + * @example + *ic=SKU47
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ITEM_CODE:String = "itemCode";
+
+ /**
+ * Optional.
+ * + * Specifies the category that the item belongs to. + *
+ * + * @example + *iv=Blue
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const ITEM_CATEGORY:String = "itemCategory";
+
+ /**
+ * Optional.
+ * + * When present indicates the local currency for all transaction + * currency values. + *
+ * + *+ * Value should be a valid ISO 4217 currency code. + *
+ * + * @example + *cu=EUR
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CURRENCY_CODE:String = "currencyCode";
+
+ // Enhanced E-Commerce (not completely supported yet)
+
+ // Product SKU
+ // Product Name
+ // Product Brand
+ // Product Category
+ // Product Variant
+ // Product Price
+ // Product Quantity
+ // Product Coupon Code
+ // Product Position
+ // Product Custom Dimension
+ // Product Custom Metric
+
+ /**
+ * Optional.
+ * + * The role of the products included in a hit. + *
+ * + *+ * If a product action is not specified, all product definitions + * included with the hit will be ignored. + * Must be one of: detail, click, add, remove, checkout, checkout_option, + * purchase, refund. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *pa=detail
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PRODUCT_ACTION:String = "productAction";
+
+ // Transaction ID - duplicate
+ // Affiliation - duplicate
+ // Revenue - duplicate
+ // Tax - duplicate
+ // Shipping - duplicate
+
+ /**
+ * Optional.
+ * + * The transaction coupon redeemed with the transaction. + *
+ * + *+ * This is an additional parameter that can be sent when Product Action + * is set to 'purchase' or 'refund'. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *tcc=SUMMER08
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const COUPON_CODE:String = "couponCode";
+
+ /**
+ * Optional.
+ * + * The list or collection from which a product action occurred. + *
+ * + *+ * This is an additional parameter that can be sent when Product Action + * is set to 'detail' or 'click'. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *pal=Search%20Results
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PRODUCT_ACTION_LIST:String = "productActionList";
+
+ /**
+ * Optional.
+ * + * The step number in a checkout funnel. + *
+ * + *+ * This is an additional parameter that can be sent when Product Action + * is set to 'checkout'. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *cos=2
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CHECKOUT_STEP:String = "checkoutStep";
+
+ /**
+ * Optional.
+ * + * Additional information about a checkout step. + *
+ * + *+ * This is an additional parameter that can be sent when Product Action + * is set to 'checkout'. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *col=Visa
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CHECKOUT_STEP_OPTION:String = "checkoutStepOption";
+
+ // Product Impression List Name
+ // Product Impression SKU
+ // Product Impression Name
+ // Product Impression Brand
+ // Product Impression Category
+ // Product Impression Variant
+ // Product Impression Position
+ // Product Impression Price
+ // Product Impression Custom Dimension
+ // Product Impression Custom Metric
+ // Promotion ID
+ // Promotion Name
+ // Promotion Creative
+ // Promotion Position
+
+ /**
+ * Optional.
+ * + * Specifies the role of the promotions included in a hit. + *
+ * + *+ * If a promotion action is not specified, the default promotion action, + * 'view', is assumed. + * To measure a user click on a promotion set this to 'promo_click'. + * + * For analytics.js the Enhanced Ecommerce plugin must be installed + * before using this field. + *
+ * + * @example + *promoa=click
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PROMOTION_ACTION:String = "promotionAction";
+
+
+ // Social Interactions
+
+ /**
+ * Required for social hit type.
+ * + * Specifies the social network. + *
+ * + *+ * For example Facebook or Google Plus. + *
+ * + * @example + *sn=facebook
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SOCIAL_NETWORK:String = "socialNetwork";
+
+ /**
+ * Required for social hit type.
+ * + * Specifies the social interaction action. + *
+ * + *+ * For example on Google Plus when a user clicks the +1 button, + * the social action is 'plus'. + *
+ * + * @example + *sa=like
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SOCIAL_ACTION:String = "socialAction";
+
+ /**
+ * Required for social hit type.
+ * + * Specifies the target of a social interaction. + *
+ * + *+ * This value is typically a URL but can be any text. + *
+ * + * @example + *st=http%3A%2F%2Ffoo.com
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SOCIAL_TARGET:String = "socialTarget";
+
+
+ // Timing
+
+ /**
+ * Required for timing hit type.
+ * + * Specifies the user timing category. + *
+ * + * @example + *utc=category
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_TIMING_CATEGORY:String = "userTimingCategory";
+
+ /**
+ * Required for timing hit type.
+ * + * Specifies the user timing variable. + *
+ * + * @example + *utv=lookup
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_TIMING_VAR:String = "userTimingVar";
+
+ /**
+ * Required for timing hit type.
+ * + * Specifies the user timing value. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *utt=123
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_TIMING_TIME:String = "userTimingTime";
+
+ /**
+ * Optional.
+ * + * Specifies the user timing label. + *
+ * + * @example + *utl=label
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const USER_TIMING_LABEL:String = "userTimingLabel";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took for a page to load. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *plt=3554
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PAGE_LOAD_TIME:String = "pageLoadTime";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took to do a DNS lookup. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *dns=43
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DNS_TIME:String = "dnsTime";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took for the page to be downloaded. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *pdt=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const PAGE_DOWNLOAD_TIME:String = "pageDownloadTime";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took for any redirects to happen. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *rrt=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const REDIRECT_RESPONSE_TIME:String = "redirectResponseTime";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took for a TCP connection to be made. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *tcp=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const TCP_CONNECT_TIME:String = "tcpConnectTime";
+
+ /**
+ * Optional.
+ * + * Specifies the time it took for the server to respond after the + * connect time. + *
+ * + *+ * The value is in milliseconds. + *
+ * + * @example + *srt=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const SERVER_RESPONSE_TIME:String = "serverResponseTime";
+
+ /**
+ * Optional.
+ *
+ * Specifies the time it took for Document.readyState
+ * to be 'interactive'.
+ *
+ * The value is in milliseconds. + *
+ * + * @example + *dit=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const DOM_INTERACTIVE_TIME:String = "domInteractiveTime";
+
+ /**
+ * Optional.
+ *
+ * Specifies the time it took for the DOMContentLoaded
Event
+ * to fire.
+ *
+ * The value is in milliseconds. + *
+ * + * @example + *clt=500
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const CONTENT_LOAD_TIME:String = "contentLoadTime";
+
+
+ // Exceptions
+
+ /**
+ * Optional.
+ * + * Specifies the description of an exception. + *
+ * + * @example + *exd=DatabaseError
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EXCEPT_DESCRIPTION:String = "exceptionDescription";
+
+ /**
+ * Optional.
+ * + * Specifies whether the exception was fatal. + *
+ * + * @example + *exf=0
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public static const EXCEPT_FATAL:String = "exceptionFatal";
+
+
+ // Custom Dimensions / Metrics
+
+ /**
+ * Optional.
+ * + * Each custom dimension has an associated index. + *
+ * + *+ * There is a maximum of 20 custom dimensions (200 for Premium accounts). + * The dimension index must be a positive integer between 1 and 200, inclusive. + *
+ * + *+ * Dimensions describe data, it answers "What?" + * (what keyword did they use, what city is the visitor from). + *
+ * + * @example + *cd<dimensionIndex>=Sports
+ *
+ * @example Usage
+ * + * Each custom metric has an associated index. + *
+ * + *+ * There is a maximum of 20 custom metrics (200 for Premium accounts). + * The metric index must be a positive integer between 1 and 200, inclusive. + *
+ * + *+ * Metrics measure data, it answers "How long?", "How many?" + * (how many sessions). + *
+ * + * @example + *cm<metricIndex>=47
+ *
+ * @example Usage
+ * + * Do not use or instanciate this class directly, extend it instead. + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + * + * @see libraries.uanalytics.tracker.DefaultTracker + */ + public function Tracker() + { + super(); + } + + /** @inheritDoc */ + public function get trackingId():String + { + return get( TRACKING_ID ); + } + + /** @inheritDoc */ + public function get clientId():String + { + return get( CLIENT_ID ); + } + + /** @inheritDoc */ + public function get config():Configuration + { + return _config; + } + + /** + * Set the specified model field to the specified value. + * + * @param field the field to set. May not be null. + * @param value the new field value. May be null. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function set( field:String, value:String ):void + { + if( _model ) + { + _model.set( field, value ); + } + } + + /** + * Set the specified model field to the specified value + * for a one time use. + * + *+ * The field will be consumed on next hit and then will be reset. + *
+ * + * @param field the field to set. May not be null. + * @param value the new field value. May be null. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function setOneTime( field:String, value:String ):void + { + if( _temporary ) + { + _temporary.set( field, value ); + } + } + + /** + * Return the value of the specified field. + * + * @param field the field to get. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function get( field:String ):String + { + if( _model ) + { + return _model.get( field ); + } + + return null; + } + + /** + * Set multiple field values as specified in the Dictionary. + * + * @param values field/value pairs to set in the model. + * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + */ + public function add( values:Dictionary ):void + { + if( _model ) + { + for( var entry:String in values ) + { + set( entry, values[entry] ); + } + } + } + + /** @inheritDoc */ + public function send( hitType:String = null, tempValues:Dictionary = null ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function pageview( path:String, title:String = "" ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function screenview( name:String, appinfo:Dictionary = null ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function event( category:String, action:String, + label:String = "", value:int = -1 ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function transaction( id:String, + affiliation:String = "", + revenue:Number = 0, + shipping:Number = 0, + tax:Number = 0, + currency:String = "" ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function item( transactionId:String, name:String, + price:Number = 0, + quantity:int = 0, + code:String = "", + category:String = "", + currency:String = "" ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function social( network:String, action:String, target:String ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function exception( description:String = "", + isFatal:Boolean = true ):Boolean + { + return false; + } + + /** @inheritDoc */ + public function timing( category:String, name:String, value:int, + label:String = "", + timinginfo:Dictionary = null ):Boolean + { + return false; + } + } + +} \ No newline at end of file diff --git a/src/libraries/uanalytics/utils/crc32.as b/src/libraries/uanalytics/utils/crc32.as new file mode 100644 index 0000000..e28fd4c --- /dev/null +++ b/src/libraries/uanalytics/utils/crc32.as @@ -0,0 +1,188 @@ +package libraries.uanalytics.utils +{ + import flash.utils.ByteArray; + import flash.utils.Endian; + + /** + * A class to compute the CRC-32 checksum of a data stream. + * + *+ * Other names: CRC-32/ADCCP, PKZIP + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @playerversion AVM 0.4 + * @langversion 3.0 + * + * @see https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks Computation of cyclic redundancy checks + */ + public final class crc32 + { + + private static var lookup:Vector.
+ * Either Endian.BIG_ENDIAN
for "Most significant bit first"
+ * or Endian.LITTLE_ENDIAN
for "Least significant bit first".
+ *
ApplicationInfo
+ * from the AIR application descriptor.
+ *
+ * @param installerID provide a string for the installer id (optional).
+ * @param useVersionLabel option flag to use the version label
+ * over the version number (default to true
).
+ *
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/air/build/WS5b3ccc516d4fbf351e63e3d118666ade46-7ff1.html AIR application descriptor files
+ * @see http://help.adobe.com/en_US/air/build/WSD079A3A2-1B38-4543-A792-06594E4325FE.html Localizing the application name and description in the AIR application installer
+ * @see http://blog.dannypatterson.com/2010/03/namespaces-on-attributes-with-e4x-in-actionscript-3/ Namespaces on Attributes with E4X in ActionScript 3
+ */
+ public function generateAIRAppInfo( installerID:String = "",
+ useVersionLabel:Boolean = true ):ApplicationInfo
+ {
+ var appinfo:ApplicationInfo = new ApplicationInfo();
+
+ var na:NativeApplication = NativeApplication.nativeApplication;
+ var app_name:String = "";
+ var app_id:String = "";
+ var app_version:String = "";
+
+ if( na )
+ {
+ var descriptor:XML = na.applicationDescriptor;
+
+ // we get the default namespace, eg. SystemInfo
+ * from an AIR application.
+ *
+ *
+ * Almost the same function as generateFlashSystemInfo()
+ * but provide a bit more details for "screenColors" and "userLanguage".
+ *
DisplayObject
reference (optional).
+ *
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function generateAIRSystemInfo( display:DisplayObject = null ):SystemInfo
+ {
+ var sysinfo:SystemInfo = new SystemInfo();
+ sysinfo.screenResolution = getScreenResolution();
+
+ if( display && display.stage )
+ {
+ sysinfo.viewportSize = getViewportSize( display.stage );
+ }
+
+ sysinfo.documentEncoding = getDocumentEncoding();
+
+ var screenColors:String = "";
+
+ if( display && display.stage )
+ {
+ screenColors = getAIRScreenColors( display.stage );
+ }
+
+ if( screenColors == "" )
+ {
+ screenColors = getScreenColors();
+ }
+
+ var userLanguage:String = "";
+
+ userLanguage = getAIRUserLanguage();
+
+ if( userLanguage == "" )
+ {
+ userLanguage = getUserLanguage();
+ }
+
+ sysinfo.screenColors = screenColors;
+ sysinfo.userLanguage = userLanguage;
+ sysinfo.javaEnabled = false;
+ sysinfo.flashVersion = getFlashVersion();
+
+ return sysinfo;
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/generateCLISystemInfo.as b/src/libraries/uanalytics/utils/generateCLISystemInfo.as
new file mode 100644
index 0000000..393df0d
--- /dev/null
+++ b/src/libraries/uanalytics/utils/generateCLISystemInfo.as
@@ -0,0 +1,157 @@
+package libraries.uanalytics.utils
+{
+ import shell.Runtime;
+
+ import C.stdlib.*;
+ import C.unistd.which;
+
+ import libraries.uanalytics.tracker.SystemInfo;
+
+ /**
+ * Utility function to gather automatically the SystemInfo
+ * from a command-line program.
+ *
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ *
+ * @see http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html POSIX Locale
+ * @see http://docs.redtamarin.com/latest/shell/Runtime.html#api Runtime.api
+ */
+ public function generateCLISystemInfo():SystemInfo
+ {
+ var sysinfo:SystemInfo = new SystemInfo();
+
+ /* Note:
+ for the command-line we ignore
+ screenResolution and viewportSize.
+ */
+
+ var documentEncoding:String = "";
+ var userLanguage:String = "";
+
+ /* Note:
+ under POSIX, you could find somethign like
+ LANG = en_GB.UTF-8
+ which allow us to find out the language and encoding used
+ */
+ var LANG:String = getenv( "LANG" );
+ if( LANG != "" )
+ {
+ var pos:int = LANG.indexOf( "." );
+ if( pos > -1 )
+ {
+ userLanguage = LANG.substring( 0, pos );
+ documentEncoding = LANG.substr( pos + 1 );
+ }
+ else
+ {
+ userLanguage = LANG;
+ }
+
+ userLanguage = userLanguage.split( "_" ).join( "-" );
+ userLanguage = userLanguage.toLowerCase();
+ }
+
+ var JAVA:String = which( "java" );
+
+ if( documentEncoding != "" )
+ {
+ sysinfo.documentEncoding = documentEncoding;
+ }
+
+ // as default we set for a "gray" color depth
+ sysinfo.screenColors = "2-bits";
+
+ if( userLanguage != "" )
+ {
+ sysinfo.userLanguage = userLanguage;
+ }
+
+ if( JAVA != "" )
+ {
+ sysinfo.javaEnabled = true;
+ }
+
+ var FLASH:String = "";
+ switch( Runtime.api )
+ {
+
+ case "FP_10_0":
+ case "AIR_1_5":
+ FLASH = "10 0";
+ break;
+
+ case "FP_10_0_32":
+ case "AIR_1_5_1":
+ FLASH = "10 0 r32";
+ break;
+
+ case "FP_10_1":
+ case "AIR_1_5_2":
+ FLASH = "10 1";
+ break;
+
+ case "AIR_2_0":
+ case "AIR_2_5":
+ FLASH = "10 2";
+ break;
+
+ case "FP_10_2":
+ case "AIR_2_6":
+ FLASH = "10 2";
+ break;
+
+ case "SWF_12":
+ case "AIR_2_7":
+ FLASH = "10 3";
+ break;
+
+ case "SWF_13":
+ case "AIR_3_0":
+ FLASH = "11 0";
+ break;
+
+ case "SWF_14":
+ case "AIR_3_1":
+ FLASH = "11 1";
+ break;
+
+ case "SWF_15":
+ case "AIR_3_2":
+ FLASH = "11 2";
+ break;
+
+ case "SWF_16":
+ case "AIR_3_3":
+ FLASH = "11 3";
+ break;
+
+ case "SWF_17":
+ case "AIR_3_4":
+ FLASH = "11 4";
+ break;
+
+ case "SWF_18":
+ case "AIR_3_5":
+ FLASH = "11 5";
+ break;
+
+ case "SWF_19":
+ case "AIR_3_6":
+ FLASH = "11 6";
+ break;
+
+ case "FP_9_0":
+ case "AIR_1_0":
+ default:
+ FLASH = "9 0";
+ }
+
+ if( FLASH != "" )
+ {
+ sysinfo.flashVersion = FLASH;
+ }
+
+ return sysinfo;
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/generateCLIUUID.as b/src/libraries/uanalytics/utils/generateCLIUUID.as
new file mode 100644
index 0000000..e841d57
--- /dev/null
+++ b/src/libraries/uanalytics/utils/generateCLIUUID.as
@@ -0,0 +1,69 @@
+package libraries.uanalytics.utils
+{
+ import flash.utils.ByteArray;
+ import crypto.generateRandomBytes;
+
+ /**
+ * Generates a version 4 UUID string representation.
+ *
+ *
+ * format is xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+ * where x
is any hexadecimal digit
+ * and y
is oen of 8
, 9
, A
, or B
.
+ *
+ * Note: this is a temporary solution as the current redtamarin runtimes
+ * does not implment flash.crypto.generateRandomBytes
yet.
+ * It will work under Linux and Mac OS X but not under Windows.
+ *
+ * In your analytics reports you will find: + *
+ *
+ * Note:
+ * The documentation do warn about that
+ *
+ * a wrong user-agent could be the reason of a hit request not being + * registered by the Google Analytics Servers. + *
+ * + * @param platform override the platform with either + * "windows", "macintosh", "linux" + * + * @playerversion AVM 0.4 + * @langversion 3.0 + * + * @see https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#ua User Agent Override + */ + public function generateCLIUserAgent( platform:String = "" ):String + { + var ua:String = ""; + ua += "uanalytics/0.8"; + ua += " "; + ua += "("; + + if( platform == "" ) + { + platform = Runtime.platform; + } + else + { + switch( platform ) + { + case "windows": + case "macintosh": + case "linux": + //those are valid do nothing + break; + + default: + //not valid so we use system default + platform = Runtime.platform; + } + } + + + var p:String = platform.substr( 0, 1 ); + p = p.toUpperCase(); + platform = p + platform.substring( 1 ); + + /* Note: + the current release of Redtamarin do not detect further + than the operating system platform + eg. "windows", "macintosh", or "linux" + + It will be updated in the futur to detect the exact + operating system informations. + + As a workaround it can also be done manually + by parsing the result of + lsb_release -a + cat /etc/*release + uname -a + cat /System/Library/CoreServices/SystemVersion.plist + sysctl kern.osrelease + sysctl kern.osversion + */ + switch( platform ) + { + case "Windows": + /* Note: + "Windows" alone will not work + "Windows NT" without a version will not work + "Windows NT x.y" will work + */ + ua += platform; + ua += " NT 6.1"; + break; + + case "Macintosh": + /* Note: + "Macintosh" alone will not work + "Macintosh; Intel Mac OS X" without a version will not work + "Macintosh; Intel Mac OS X x_y" will work + */ + ua += platform; + ua += "; Intel Mac OS X 10_10"; + break; + + case "Linux": + ua += platform; + + /* Note: + "Linux" alone will not work + either "Linux x86_64" or "Linux i686" will work + */ + if( Runtime.is64bit() ) + { + ua += " x86_64"; + } + else + { + ua += " i686"; + } + break; + } + + ua += ")"; + ua += " "; + ua += "redtamarin/" + Runtime.redtamarin; + ua += " "; + ua += "AVM+/" + Runtime.version; + + return ua; + } +} \ No newline at end of file diff --git a/src/libraries/uanalytics/utils/generateFlashSystemInfo.as b/src/libraries/uanalytics/utils/generateFlashSystemInfo.as new file mode 100644 index 0000000..95fe316 --- /dev/null +++ b/src/libraries/uanalytics/utils/generateFlashSystemInfo.as @@ -0,0 +1,69 @@ +package libraries.uanalytics.utils +{ + import flash.display.DisplayObject; + + import libraries.uanalytics.tracker.SystemInfo; + + /** + * Utility function to gather automatically theSystemInfo
+ * from a SWF file.
+ *
+ *
+ * Even if the display
argument is optional,
+ * it is the only way to obtain a reference to the stage
property
+ * to obtain the "viewport size".
+ *
+ * If a display object is not added to the display list, + * its stage property is set to null. + *+ * + * @param display
DisplayObject
reference (optional).
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html Basics of display programming
+ * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#stage DisplayObject.stage property
+ *
+ */
+ public function generateFlashSystemInfo( display:DisplayObject = null ):SystemInfo
+ {
+ /* Note:
+ the principle is pretty simple, we build a defautl value object
+ if we can detect system info we then fill the info
+ otherwise we keep the value empty (or false, whatever the default).
+
+ Yes we took a very conservative and safe approach to avoid as much
+ as possible errors, ex: "I don't understand why my display object
+ does not work", that said you can do more advanced things
+ like: use a JS bridge to detect if Java is enabled, find out the
+ document encoding, etc.
+
+ The point is the default will work no matter what, more advanced users
+ will know how to setup things in order to gather more info.
+
+ usage:
+ var tracker:DefaultTracker = new DefaultTracker( trackingId );
+ var sysinfo:SystemInfo = generateFlashSystemInfo();
+ tracker.add( sysinfo );
+
+ */
+ var sysinfo:SystemInfo = new SystemInfo();
+ sysinfo.screenResolution = getScreenResolution();
+
+ if( display && display.stage )
+ {
+ sysinfo.viewportSize = getViewportSize( display.stage );
+ }
+
+ sysinfo.documentEncoding = getDocumentEncoding();
+ sysinfo.screenColors = getScreenColors();
+ sysinfo.userLanguage = getUserLanguage();
+ sysinfo.javaEnabled = false;
+ sysinfo.flashVersion = getFlashVersion();
+
+ return sysinfo;
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/generateUUID.as b/src/libraries/uanalytics/utils/generateUUID.as
new file mode 100644
index 0000000..d0c14a4
--- /dev/null
+++ b/src/libraries/uanalytics/utils/generateUUID.as
@@ -0,0 +1,86 @@
+package libraries.uanalytics.utils
+{
+ import flash.crypto.generateRandomBytes;
+ import flash.utils.ByteArray;
+
+ /**
+ * Generates a version 4 UUID string representation.
+ *
+ *
+ * format is xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+ * where x
is any hexadecimal digit
+ * and y
is oen of 8
, 9
, A
, or B
.
+ *
DisplayObject
.
+ *
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Screen.html#colorDepth Screen.colorDepth
+ */
+ public function getAIRScreenColors( stage:Stage ):String
+ {
+ var current:Screen = getCurrentScreen( stage );
+
+ if( current )
+ {
+ return current.colorDepth + "-bits";
+ }
+
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/getAIRUserLanguage.as b/src/libraries/uanalytics/utils/getAIRUserLanguage.as
new file mode 100644
index 0000000..5eae56e
--- /dev/null
+++ b/src/libraries/uanalytics/utils/getAIRUserLanguage.as
@@ -0,0 +1,31 @@
+package libraries.uanalytics.utils
+{
+ import flash.system.Capabilities;
+
+ /**
+ * Returns a language tag (and script and region information, where applicable)
+ * defined by RFC4646.
+ *
+ *
+ * Note:
+ * The value of Capabilities.language
property is limited to the possible
+ * values on this list.
+ * Because of this limitation, Adobe AIR applications should use the first
+ * element in the Capabilities.languages
array to determine the primary user
+ * interface language for the system.
+ *
Screen
+ * of an AIR application.
+ *
+ * + * For example, if an AIR desktop application run on a system with + * multiple screens, this function will return the screen reference + * under which the app is running. + *
+ * + * @param stage the stage property of aDisplayObject
.
+ *
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function getCurrentScreen( stage:Stage ):Screen
+ {
+ if( stage && stage.nativeWindow )
+ {
+ var screens:Array = Screen.getScreensForRectangle( stage.nativeWindow.bounds );
+ if( screens.length > 0 )
+ {
+ return screens[0];
+ }
+ }
+
+ return Screen.mainScreen;
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/getDocumentEncoding.as b/src/libraries/uanalytics/utils/getDocumentEncoding.as
new file mode 100644
index 0000000..0ecd25f
--- /dev/null
+++ b/src/libraries/uanalytics/utils/getDocumentEncoding.as
@@ -0,0 +1,42 @@
+package libraries.uanalytics.utils
+{
+ import flash.system.System;
+
+ /**
+ * Return the encoding or code page of the current SWF file
+ * or AIR application.
+ *
+ *
+ * Because System.useCodePage = false
by default,
+ * it should always be "UTF-8" (eg. we don't use the sytem code page
+ * so we know we use Unicode).
+ * And in the case where System.useCodePage = true
+ * then it will return the empty string (eg. the system code page is used
+ * so we don't know).
+ *
+ * The language is specified as a lowercase two-letter language code + * from ISO 639-1. + *
+ * + *+ * On English systems, this property returns only the language code (en), + * not the country code. + * On Microsoft Windows systems, this property returns the user interface (UI) + * language, which refers to the language used for all menus, dialog boxes, + * error messages, and help files. + *
+ * + * @playerversion Flash 11 + * @playerversion AIR 3.0 + * @langversion 3.0 + * + * @see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Capabilities.html#language Capabilities.language + * @see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes List of ISO 639-1 codes + */ + public function getUserLanguage():String + { + var lang:String = Capabilities.language; + + // Other/unknown + if( lang == "xu" ) + { + lang = ""; + } + + return lang; + } +} \ No newline at end of file diff --git a/src/libraries/uanalytics/utils/getViewportSize.as b/src/libraries/uanalytics/utils/getViewportSize.as new file mode 100644 index 0000000..806605c --- /dev/null +++ b/src/libraries/uanalytics/utils/getViewportSize.as @@ -0,0 +1,24 @@ +package libraries.uanalytics.utils +{ + import flash.display.Stage; + + /** + * Utility function to return the "viewport size" + * (eg. the actual rectangle area used by the application). + * + * @param stage the stage property of aDisplayObject
.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ *
+ * @see http://www.adobe.com/devnet/air/articles/multiple-screen-sizes.html Supporting the multiple screen sizes of multiple devices in Adobe AIR
+ */
+ public function getViewportSize( stage:Stage ):String
+ {
+ var w:Number = stage.stageWidth;
+ var h:Number = stage.stageHeight;
+
+ return String(w) + "x" + String(h);
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/isAIR.as b/src/libraries/uanalytics/utils/isAIR.as
new file mode 100644
index 0000000..69a4ea9
--- /dev/null
+++ b/src/libraries/uanalytics/utils/isAIR.as
@@ -0,0 +1,16 @@
+package libraries.uanalytics.utils
+{
+ import flash.system.Security;
+
+ /**
+ * Returns true
if the current context is an AIR application.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @langversion 3.0
+ */
+ public function isAIR():Boolean
+ {
+ return Security.sandboxType == Security.APPLICATION;
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/uanalytics/utils/isDigit.as b/src/libraries/uanalytics/utils/isDigit.as
new file mode 100644
index 0000000..0649232
--- /dev/null
+++ b/src/libraries/uanalytics/utils/isDigit.as
@@ -0,0 +1,27 @@
+package libraries.uanalytics.utils
+{
+
+ /**
+ * Indicates if the specified character is a digit.
+ *
+ * @param c The expression to evaluate.
+ * @param index The optional index to evaluate a specific character in the
+ * passed-in expression.
+ *
+ * @return True if the specified character is a digit.
+ *
+ * @playerversion Flash 11
+ * @playerversion AIR 3.0
+ * @playerversion AVM 0.4
+ * @langversion 3.0
+ */
+ public function isDigit( c:String , index:uint = 0 ):Boolean
+ {
+ if( index > 0 )
+ {
+ c = c.charAt( index ) ;
+ }
+
+ return ("0" <= c) && (c <= "9");
+ }
+}
\ No newline at end of file
diff --git a/src/uanalytics.as b/src/uanalytics.as
new file mode 100644
index 0000000..4af70e6
--- /dev/null
+++ b/src/uanalytics.as
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include "C/unistd/which.as";
+include "crypto/generateRandomBytes.as";
+
+include "libraries/uanalytics/tracking/AnalyticsTracker.as";
+include "libraries/uanalytics/tracking/AnalyticsSender.as";
+include "libraries/uanalytics/tracking/Configuration.as";
+include "libraries/uanalytics/tracking/HitModel.as";
+include "libraries/uanalytics/tracking/HitSampler.as";
+include "libraries/uanalytics/tracking/HitSender.as";
+include "libraries/uanalytics/tracking/Metadata.as";
+include "libraries/uanalytics/tracking/RateLimiter.as";
+include "libraries/uanalytics/tracking/RateLimitError.as";
+include "libraries/uanalytics/tracking/Tracker.as";
+
+include "libraries/uanalytics/tracker/HitType.as";
+include "libraries/uanalytics/tracker/DataSource.as";
+include "libraries/uanalytics/tracker/SessionControl.as";
+include "libraries/uanalytics/tracker/ApplicationInfo.as";
+include "libraries/uanalytics/tracker/SystemInfo.as";
+include "libraries/uanalytics/tracker/TimingInfo.as";
+include "libraries/uanalytics/tracker/CommandLineTracker.as";
+include "libraries/uanalytics/tracker/CliTracker.as";
+
+include "libraries/uanalytics/tracker/senders/TraceHitSender.as";
+include "libraries/uanalytics/tracker/senders/BSDSocketHitSender.as";
+include "libraries/uanalytics/tracker/senders/CurlHitSender.as";
+
+include "libraries/uanalytics/utils/isDigit.as";
+include "libraries/uanalytics/utils/crc32.as";
+include "libraries/uanalytics/utils/getCLIHostname.as";
+include "libraries/uanalytics/utils/generateCLIUUID.as";
+include "libraries/uanalytics/utils/generateCLISystemInfo.as";
+include "libraries/uanalytics/utils/generateCLIUserAgent.as";
+
+include "libraries/uanalytics/tracker/addons/DebugFileSystemStorage.as";
+
+"uanalytics 0.8.0";
\ No newline at end of file
diff --git a/src/uanalytics.png b/src/uanalytics.png
new file mode 100644
index 0000000000000000000000000000000000000000..1cd5fad56bcffabd7b787be47ebcfd1b8e5b184c
GIT binary patch
literal 1624
zcmV-e2B-OnP)