diff --git a/source/Plugins/GoogleAnalyticsV3/GAIHandler.cs b/source/Plugins/GoogleAnalyticsV3/GAIHandler.cs new file mode 100644 index 0000000..338fc69 --- /dev/null +++ b/source/Plugins/GoogleAnalyticsV3/GAIHandler.cs @@ -0,0 +1,234 @@ +/* + Copyright 2014 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using UnityEngine; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +/* + Wrapper for Objective-C iOS SDK +*/ +public class GAIHandler { +#if UNITY_IPHONE && !UNITY_EDITOR + [DllImport("__Internal")] + private static extern void setName(string name); + public void _setName(string name){ + setName(name); + } + + [DllImport("__Internal")] + private static extern void setOptOut(bool optOut); + public void _setOptOut(bool optOut){ + setOptOut(optOut); + } + + [DllImport("__Internal")] + private static extern void setDispatchInterval(int time); + public void _setDispatchInterval(int time){ + setDispatchInterval(time); + } + + [DllImport("__Internal")] + private static extern void anonymizeIP(); + public void _anonymizeIP(){ + anonymizeIP(); + } + + [DllImport("__Internal")] + private static extern void setTrackUncaughtExceptions(bool trackUncaughtExceptions); + public void _setTrackUncaughtExceptions(bool trackUncaughtExceptions){ + setTrackUncaughtExceptions(trackUncaughtExceptions); + } + + [DllImport("__Internal")] + private static extern void setDryRun(bool dryRun); + public void _setDryRun(bool dryRun){ + setDryRun(dryRun); + } + + [DllImport("__Internal")] + private static extern void setSampleFrequency(float sampleFrequency); + public void _setSampleFrequency(float sampleFrequency){ + setSampleFrequency(sampleFrequency); + } + + [DllImport("__Internal")] + private static extern void setLogLevel(int logLevel); + public void _setLogLevel(int logLevel){ + setLogLevel(logLevel); + } + + [DllImport("__Internal")] + private static extern void startSession(); + public void _startSession(){ + startSession(); + } + + [DllImport("__Internal")] + private static extern void stopSession(); + public void _stopSession(){ + stopSession(); + } + + [DllImport("__Internal")] + private static extern IntPtr trackerWithName(string name, string trackingId); + public IntPtr _getTrackerWithName(string name, string trackingId){ + return trackerWithName(name, trackingId); + } + + [DllImport("__Internal")] + private static extern IntPtr trackerWithTrackingId(string trackingId); + public IntPtr _getTrackerWithTrackingId(string trackingId){ + return trackerWithTrackingId(trackingId); + } + + [DllImport("__Internal")] + private static extern void set(string parameterName, string value); + public void _set(string parameterName, object value){ + set(parameterName, value.ToString()); + } + + [DllImport("__Internal")] + private static extern void setBool(string parameterName, bool value); + public void _setBool(string parameterName, bool value){ + setBool(parameterName, value); + } + + [DllImport("__Internal")] + private static extern string get(string parameterName); + public string _get(string parameterName){ + return get(parameterName); + } + + [DllImport("__Internal")] + private static extern void send(string parametersString); + public void _send(Dictionary parameters){ + string parametersString = ""; + foreach(KeyValuePair kvp in parameters) + { + parametersString += kvp.Key + "=" + kvp.Value + "\n"; + } + send(parametersString); + } + + [DllImport("__Internal")] + private static extern void dispatch(); + public void _dispatchHits(){ + dispatch(); + } + + [DllImport("__Internal")] + private static extern void sendAppView(string screenName); + public void _sendAppView(AppViewHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendAppView(builder.GetScreenName()); + } + + [DllImport("__Internal")] + private static extern void sendEvent(string category, string action, string label, long value); + public void _sendEvent(EventHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendEvent(builder.GetEventCategory(), builder.GetEventAction(), builder.GetEventLabel(), builder.GetEventValue()); + } + +//NOT TESTED + [DllImport("__Internal")] + private static extern void sendTransaction(string transactionID, string affiliation, double revenue, double tax, double shipping, string currencyCode); + public void _sendTransaction(TransactionHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendTransaction(builder.GetTransactionID(), builder.GetAffiliation(), builder.GetRevenue(), builder.GetTax(), builder.GetShipping(), builder.GetCurrencyCode()); + } + + [DllImport("__Internal")] + private static extern void sendItemWithTransaction(string transactionID, string name, string sku, string category, double price, long quantity, string currencyCode); + public void _sendItemWithTransaction(ItemHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendItemWithTransaction(builder.GetTransactionID(), builder.GetName(), builder.GetSKU(), builder.GetCategory(), builder.GetPrice(), builder.GetQuantity(),builder.GetCurrencyCode()); + } + + [DllImport("__Internal")] + private static extern void sendException(string exceptionDescription, bool isFatal); + public void _sendException(ExceptionHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendException(builder.GetExceptionDescription(), builder.IsFatal()); + } + + [DllImport("__Internal")] + private static extern void sendSocial(string socialNetwork, string socialAction, string targetUrl); + public void _sendSocial(SocialHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendSocial(builder.GetSocialNetwork(), builder.GetSocialAction(), builder.GetSocialTarget()); + } + + [DllImport("__Internal")] + private static extern void sendTiming(string timingCategory,long timingInterval, string timingName, string timingLabel); + public void _sendTiming(TimingHitBuilder builder){ + _setCustomDimensionOnTracker(builder); + _setCustomMetricOnTracker(builder); + _buildCampaignParametersDictionary(builder); + sendTiming(builder.GetTimingCategory(), builder.GetTimingInterval(), builder.GetTimingName(), builder.GetTimingLabel()); + } + + [DllImport("__Internal")] + private static extern void setCustomDimensionOnTracker(int index, string value); + public void _setCustomDimensionOnTracker(HitBuilder builder){ + foreach(KeyValuePair entry in builder.GetCustomDimensions()) + { + setCustomDimensionOnTracker(entry.Key, entry.Value); + } + } + + [DllImport("__Internal")] + private static extern void setCustomMetricOnTracker(int index, string value); + public void _setCustomMetricOnTracker(HitBuilder builder){ + foreach(KeyValuePair entry in builder.GetCustomMetrics()) + { + setCustomMetricOnTracker(entry.Key, entry.Value); + } + } + + [DllImport("__Internal")] + private static extern void buildCampaignParametersDictionary(string source, string medium, string name, string content, string keyword); + public void _buildCampaignParametersDictionary(HitBuilder builder){ + if(!String.IsNullOrEmpty(builder.GetCampaignSource())){ + buildCampaignParametersDictionary(builder.GetCampaignSource(), + builder.GetCampaignMedium() != null ? builder.GetCampaignMedium() : "", + builder.GetCampaignName() != null? builder.GetCampaignName() : "", + builder.GetCampaignContent() != null? builder.GetCampaignContent() : "", + builder.GetCampaignKeyword() != null? builder.GetCampaignKeyword() : ""); + } else if(!String.IsNullOrEmpty(builder.GetCampaignMedium()) || + !String.IsNullOrEmpty(builder.GetCampaignName()) || + !String.IsNullOrEmpty(builder.GetCampaignMedium()) || + !String.IsNullOrEmpty(builder.GetCampaignContent()) || + !String.IsNullOrEmpty(builder.GetCampaignKeyword())) { + Debug.Log("A required parameter (campaign source) is null or empty. No campaign parameters will be added to hit."); + } + } + #endif +} diff --git a/source/Plugins/GoogleAnalyticsV3/GoogleAnalyticsiOSV3.cs b/source/Plugins/GoogleAnalyticsV3/GoogleAnalyticsiOSV3.cs new file mode 100644 index 0000000..e3e63f0 --- /dev/null +++ b/source/Plugins/GoogleAnalyticsV3/GoogleAnalyticsiOSV3.cs @@ -0,0 +1,164 @@ +/* + Copyright 2014 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +using UnityEngine; +using System; +using System.Collections.Generic; + +/* + GoogleAnalyticsiOSV3 handles building hits using the iOS SDK. + Developers should call the methods in GoogleAnalyticsV3, which will call the + appropriate methods in this class if the application is built for iOS. +*/ +public class GoogleAnalyticsiOSV3 { + +#if UNITY_IPHONE && !UNITY_EDITOR + private string trackingCode; + private string appName; + private string bundleIdentifier; + private string appVersion; + private int dispatchPeriod; + private float sampleFrequency; + private GoogleAnalyticsV3.DebugMode logLevel; + private bool anonymizeIP; + private bool dryRun; + private GAIHandler handler; + + internal void InitializeTracker () { + Debug.Log ("Initializing Google Analytics iOS Tracker."); + handler = new GAIHandler(); + handler._setDispatchInterval(dispatchPeriod); + handler._setDryRun(dryRun); + handler._setSampleFrequency(sampleFrequency); + handler._setTrackUncaughtExceptions(true); + SetTrackerVal(Fields.APP_NAME, appName); + SetTrackerVal(Fields.APP_ID, bundleIdentifier); + SetTrackerVal(Fields.APP_VERSION, appVersion); + if(anonymizeIP) { + handler._anonymizeIP(); + } + SetLogLevel(logLevel); + handler._getTrackerWithTrackingId(trackingCode); + } + + private void SetLogLevel(GoogleAnalyticsV3.DebugMode logLevel) { + switch(logLevel) + { + case GoogleAnalyticsV3.DebugMode.ERROR: + handler._setLogLevel(1); + break; + case GoogleAnalyticsV3.DebugMode.VERBOSE: + handler._setLogLevel(4); + break; + case GoogleAnalyticsV3.DebugMode.INFO: + handler._setLogLevel(3); + break; + default: + handler._setLogLevel(2); + break; + } + } + + public void ClearUserIDOverride() { + SetTrackerVal(Fields.USER_ID, null); + } + + public void DispatchHits(){ + handler._dispatchHits(); + } + + public void StartSession(){ + handler._startSession(); + } + + public void StopSession(){ + handler._stopSession(); + } + + public void LogScreen(AppViewHitBuilder builder){ + handler._sendAppView(builder); + } + + public void LogEvent(EventHitBuilder builder){ + handler._sendEvent(builder); + } + + internal void LogTransaction(TransactionHitBuilder builder) { + handler._sendTransaction(builder); + } + + internal void LogItem(ItemHitBuilder builder) { + handler._sendItemWithTransaction(builder); + } + + public void LogException(ExceptionHitBuilder builder) { + handler._sendException(builder); + } + + public void LogSocial(SocialHitBuilder builder) { + handler._sendSocial(builder); + } + + public void LogTiming(TimingHitBuilder builder) { + handler._sendTiming(builder); + } + + public void SetOptOut(bool optOut) { + handler._setOptOut(optOut); + } + + public void SetTrackerVal(Field fieldName, object value){ + handler._set(fieldName.ToString(), value); + } + + public void SetTrackingCode(string trackingCode) { + this.trackingCode = trackingCode; + } + + public void SetAppName(string appName) { + this.appName = appName; + } + + public void SetBundleIdentifier(string bundleIdentifier) { + this.bundleIdentifier = bundleIdentifier; + } + + public void SetAppVersion(string appVersion) { + this.appVersion = appVersion; + } + + public void SetDispatchPeriod(int dispatchPeriod) { + this.dispatchPeriod = dispatchPeriod; + } + + public void SetSampleFrequency(float sampleFrequency) { + this.sampleFrequency = sampleFrequency; + } + + public void SetLogLevelValue(GoogleAnalyticsV3.DebugMode logLevel) { + this.logLevel = logLevel; + } + + public void SetAnonymizeIP(bool anonymizeIP) { + this.anonymizeIP = anonymizeIP; + } + + public void SetDryRun(bool dryRun) { + this.dryRun = dryRun; + } + +#endif +} diff --git a/source/Plugins/iOS/GAI.h b/source/Plugins/iOS/GAI.h new file mode 100644 index 0000000..d9e60e4 --- /dev/null +++ b/source/Plugins/iOS/GAI.h @@ -0,0 +1,166 @@ +/*! + @header GAI.h + @abstract Google Analytics iOS SDK Header + @version 3.0 + @copyright Copyright 2013 Google Inc. All rights reserved. + */ + +#import +#import "GAILogger.h" +#import "GAITracker.h" +#import "GAITrackedViewController.h" + +/*! Google Analytics product string. */ +extern NSString *const kGAIProduct; + +/*! Google Analytics version string. */ +extern NSString *const kGAIVersion; + +/*! + NSError objects returned by the Google Analytics SDK may have this error domain + to indicate that the error originated in the Google Analytics SDK. + */ +extern NSString *const kGAIErrorDomain; + +/*! Google Analytics error codes. */ +typedef enum { + // This error code indicates that there was no error. Never used. + kGAINoError = 0, + + // This error code indicates that there was a database-related error. + kGAIDatabaseError, + + // This error code indicates that there was a network-related error. + kGAINetworkError, +} GAIErrorCode; + +/*! + Google Analytics iOS top-level class. Provides facilities to create trackers + and set behaviorial flags. + */ +@interface GAI : NSObject + +/*! + For convenience, this class exposes a default tracker instance. + This is initialized to `nil` and will be set to the first tracker that is + instantiated in trackerWithTrackingId:. It may be overridden as desired. + + The GAITrackedViewController class will, by default, use this tracker instance. + */ +@property(nonatomic, assign) id defaultTracker; + +/*! + The GAILogger to use. + */ +@property(nonatomic, retain) id logger; + +/*! + When this is true, no tracking information will be gathered; tracking calls + will effectively become no-ops. When set to true, all tracking information that + has not yet been submitted. The value of this flag will be persisted + automatically by the SDK. Developers can optionally use this flag to implement + an opt-out setting in the app to allows users to opt out of Google Analytics + tracking. + + This is set to `NO` the first time the Google Analytics SDK is used on a + device, and is persisted thereafter. + */ +@property(nonatomic, assign) BOOL optOut; + +/*! + If this value is positive, tracking information will be automatically + dispatched every dispatchInterval seconds. Otherwise, tracking information must + be sent manually by calling dispatch. + + By default, this is set to `120`, which indicates tracking information should + be dispatched automatically every 120 seconds. + */ +@property(nonatomic, assign) NSTimeInterval dispatchInterval; + +/*! + When set to true, the SDK will record the currently registered uncaught + exception handler, and then register an uncaught exception handler which tracks + the exceptions that occurred using defaultTracker. If defaultTracker is not + `nil`, this function will track the exception on the tracker and attempt to + dispatch any outstanding tracking information for 5 seconds. It will then call + the previously registered exception handler, if any. When set back to false, + the previously registered uncaught exception handler will be restored. + */ +@property(nonatomic, assign) BOOL trackUncaughtExceptions; + +/*! + When this is 'YES', no tracking information will be sent. Defaults to 'NO'. + */ +@property(nonatomic, assign) BOOL dryRun; + +/*! Get the shared instance of the Google Analytics for iOS class. */ ++ (GAI *)sharedInstance; + +/*! + Creates or retrieves a GAITracker implementation with the specified name and + tracking ID. If the tracker for the specified name does not already exist, then + it will be created and returned; otherwise, the existing tracker will be + returned. If the existing tracker for the respective name has a different + tracking ID, that tracking ID is not changed by this method. If defaultTracker + is not set, it will be set to the tracker instance returned here. + + @param name The name of this tracker. Must not be `nil` or empty. + + @param trackingID The tracking ID to use for this tracker. It should be of + the form `UA-xxxxx-y`. + + @return A GAITracker associated with the specified name. The tracker + can be used to send tracking data to Google Analytics. The first time this + method is called with a particular name, the tracker for that name will be + returned, and subsequent calls with the same name will return the same + instance. It is not necessary to retain the tracker because the tracker will be + retained internally by the library. + + If an error occurs or the name is not valid, this method will return + `nil`. + */ +- (id)trackerWithName:(NSString *)name + trackingId:(NSString *)trackingId; + +/*! + Creates or retrieves a GAITracker implementation with name equal to + the specified tracking ID. If the tracker for the respective name does not + already exist, it is created, has it's tracking ID set to |trackingId|, + and is returned; otherwise, the existing tracker is returned. If the existing + tracker for the respective name has a different tracking ID, that tracking ID + is not changed by this method. If defaultTracker is not set, it is set to the + tracker instance returned here. + + @param trackingID The tracking ID to use for this tracker. It should be of + the form `UA-xxxxx-y`. The name of the tracker will be the same as trackingID. + + @return A GAITracker associated with the specified trackingID. The tracker + can be used to send tracking data to Google Analytics. The first time this + method is called with a particular trackingID, the tracker for the respective + name will be returned, and subsequent calls with the same trackingID + will return the same instance. It is not necessary to retain the tracker + because the tracker will be retained internally by the library. + + If an error occurs or the trackingId is not valid, this method will return + `nil`. + */ +- (id)trackerWithTrackingId:(NSString *)trackingId; + +/*! + Remove a tracker from the trackers dictionary. If it is the default tracker, + clears the default tracker as well. + + @param name The name of the tracker. + */ +- (void)removeTrackerByName:(NSString *)name; + +/*! + Dispatches any pending tracking information. + + It would be wise to call this when application is exiting to initiate the + submission of any unsubmitted tracking information. Note that this does not + have any effect on dispatchInterval, and can be used in conjuntion with + periodic dispatch. */ +- (void)dispatch; + +@end diff --git a/source/Plugins/iOS/GAIDictionaryBuilder.h b/source/Plugins/iOS/GAIDictionaryBuilder.h new file mode 100644 index 0000000..20adff8 --- /dev/null +++ b/source/Plugins/iOS/GAIDictionaryBuilder.h @@ -0,0 +1,178 @@ +/*! + @header GAIDictionaryBuilder.h + @abstract Google Analytics iOS SDK Hit Format Header + @copyright Copyright 2013 Google Inc. All rights reserved. + */ + +#import + +/*! + * Helper class to build a dictionary of hit parameters and values. + *
+ * Examples: + * + * id t = // get a tracker. + * [t send:[[[GAIDictionaryBuilder createEventWithCategory:@"EventCategory" + * action:@"EventAction" + * label:nil + * value:nil] + * set:@"dimension1" forKey:[GAIFields customDimensionForIndex:1]] build]]; + * + * This will send an event hit type with the specified parameters + * and a custom dimension parameter. + *
+ * If you want to send a parameter with all hits, set it on GAITracker directly. + * + * [t set:kGAIScreenName value:@"Home"]; + * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" + * action:@"PlusOne" + * target:@"SOME_URL"] build]]; + * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" + * action:@"Share" + * target:@"SOME_POST"] build]]; + * [t send:[[GAIDictionaryBuilder createSocialWithNetwork:@"Google+" + * action:@"HangOut" + * target:@"SOME_CIRCLE"] + * build]]; + * + * You can override a value set on the tracker by adding it to the dictionary. + * + * [t set:kGAIScreenName value:@"Home"]; + * [t send:...]; + * [t send[[[GAIDictionaryBuilder createEventWithCategory:@"click" + * action:@"popup" + * label:nil + * value:nil] + * set:@"popup title" forKey:kGAIScreenName] build]]; + * + * The values set via [GAIDictionaryBuilder set] or + * [GAIDictionaryBuilder setAll] will override any existing values in the + * GAIDictionaryBuilder object (i.e. initialized by + * [GAIDictionaryBuilder createXYZ]). e.g. + * + * GAIDictionaryBuilder *m = + * GAIDictionaryBuilder createTimingWithCategory:@"category" + * interval:@0 + * name:@"name" + * label:nil]; + * [t send:[m.set:@"10" forKey:kGAITimingVar] build]; + * [t send:[m.set:@"20" forKey:kGAITimingVar] build]; + * + */ +@interface GAIDictionaryBuilder : NSObject + +- (GAIDictionaryBuilder *)set:(NSString *)value + forKey:(NSString *)key; + +/*! + * Copies all the name-value pairs from params into this object, ignoring any + * keys that are not NSString and any values that are neither NSString or + * NSNull. + */ +- (GAIDictionaryBuilder *)setAll:(NSDictionary *)params; + +/*! + * Returns the value for the input parameter paramName, or nil if paramName + * is not present. + */ +- (NSString *)get:(NSString *)paramName; + +/*! + * Return an NSMutableDictionary object with all the parameters set in this + */ +- (NSMutableDictionary *)build; + +/*! + * Parses and translates utm campaign parameters to analytics campaign param + * and returns them as a map. + * + * @param params url containing utm campaign parameters. + * + * Valid campaign parameters are: + *
    + *
  • utm_id
  • + *
  • utm_campaign
  • + *
  • utm_content
  • + *
  • utm_medium
  • + *
  • utm_source
  • + *
  • utm_term
  • + *
  • dclid
  • + *
  • gclid
  • + *
  • gmob_t
  • + *
+ *

+ * Example: + * http://my.site.com/index.html?utm_campaign=wow&utm_source=source + * utm_campaign=wow&utm_source=source. + *

+ * For more information on auto-tagging, see + * http://support.google.com/googleanalytics/bin/answer.py?hl=en&answer=55590 + *

+ * For more information on manual tagging, see + * http://support.google.com/googleanalytics/bin/answer.py?hl=en&answer=55518 + */ +- (GAIDictionaryBuilder *)setCampaignParametersFromUrl:(NSString *)urlString; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to an appview + hit. + + Note that using this method will not set the screen name for followon hits. To + do that you need to call set:kGAIDescription value: on the + GAITracker instance. + */ ++ (GAIDictionaryBuilder *)createAppView; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to an event hit. + */ ++ (GAIDictionaryBuilder *)createEventWithCategory:(NSString *)category + action:(NSString *)action + label:(NSString *)label + value:(NSNumber *)value; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to an exception + hit. + */ ++ (GAIDictionaryBuilder *)createExceptionWithDescription:(NSString *)description + withFatal:(NSNumber *)fatal; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to an item hit. + */ ++ (GAIDictionaryBuilder *)createItemWithTransactionId:(NSString *)transactionId + name:(NSString *)name + sku:(NSString *)sku + category:(NSString *)category + price:(NSNumber *)price + quantity:(NSNumber *)quantity + currencyCode:(NSString *)currencyCode; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to a social hit. + */ ++ (GAIDictionaryBuilder *)createSocialWithNetwork:(NSString *)network + action:(NSString *)action + target:(NSString *)target; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to a timing hit. + */ ++ (GAIDictionaryBuilder *)createTimingWithCategory:(NSString *)category + interval:(NSNumber *)intervalMillis + name:(NSString *)name + label:(NSString *)label; + +/*! + Returns a GAIDictionaryBuilder object with parameters specific to a transaction + hit. + */ ++ (GAIDictionaryBuilder *)createTransactionWithId:(NSString *)transactionId + affiliation:(NSString *)affiliation + revenue:(NSNumber *)revenue + tax:(NSNumber *)tax + shipping:(NSNumber *)shipping + currencyCode:(NSString *)currencyCode; + +@end diff --git a/source/Plugins/iOS/GAIFields.h b/source/Plugins/iOS/GAIFields.h new file mode 100644 index 0000000..caa8660 --- /dev/null +++ b/source/Plugins/iOS/GAIFields.h @@ -0,0 +1,126 @@ +/*! + @header GAIFields.h + @abstract Google Analytics iOS SDK Hit Format Header + @copyright Copyright 2013 Google Inc. All rights reserved. + */ + +#import + +/*! + These fields can be used for the wire format parameter names required by + the |GAITracker| get, set and send methods as well as the set methods in the + |GAIDictionaryBuilder| class. + */ +extern NSString *const kGAIUseSecure; + +extern NSString *const kGAIHitType; +extern NSString *const kGAITrackingId; +extern NSString *const kGAIClientId; +extern NSString *const kGAIAnonymizeIp; +extern NSString *const kGAISessionControl; +extern NSString *const kGAIScreenResolution; +extern NSString *const kGAIViewportSize; +extern NSString *const kGAIEncoding; +extern NSString *const kGAIScreenColors; +extern NSString *const kGAILanguage; +extern NSString *const kGAIJavaEnabled; +extern NSString *const kGAIFlashVersion; +extern NSString *const kGAINonInteraction; +extern NSString *const kGAIReferrer; +extern NSString *const kGAILocation; +extern NSString *const kGAIHostname; +extern NSString *const kGAIPage; +extern NSString *const kGAIDescription; // synonym for kGAIScreenName +extern NSString *const kGAIScreenName; // synonym for kGAIDescription +extern NSString *const kGAITitle; +extern NSString *const kGAIAppName; +extern NSString *const kGAIAppVersion; +extern NSString *const kGAIAppId; +extern NSString *const kGAIAppInstallerId; + +extern NSString *const kGAIEventCategory; +extern NSString *const kGAIEventAction; +extern NSString *const kGAIEventLabel; +extern NSString *const kGAIEventValue; + +extern NSString *const kGAISocialNetwork; +extern NSString *const kGAISocialAction; +extern NSString *const kGAISocialTarget; + +extern NSString *const kGAITransactionId; +extern NSString *const kGAITransactionAffiliation; +extern NSString *const kGAITransactionRevenue; +extern NSString *const kGAITransactionShipping; +extern NSString *const kGAITransactionTax; +extern NSString *const kGAICurrencyCode; + +extern NSString *const kGAIItemPrice; +extern NSString *const kGAIItemQuantity; +extern NSString *const kGAIItemSku; +extern NSString *const kGAIItemName; +extern NSString *const kGAIItemCategory; + +extern NSString *const kGAICampaignSource; +extern NSString *const kGAICampaignMedium; +extern NSString *const kGAICampaignName; +extern NSString *const kGAICampaignKeyword; +extern NSString *const kGAICampaignContent; +extern NSString *const kGAICampaignId; + +extern NSString *const kGAITimingCategory; +extern NSString *const kGAITimingVar; +extern NSString *const kGAITimingValue; +extern NSString *const kGAITimingLabel; + +extern NSString *const kGAIExDescription; +extern NSString *const kGAIExFatal; + +extern NSString *const kGAISampleRate; + +extern NSString *const kGAIIdfa; +extern NSString *const kGAIAdTargetingEnabled; + +// hit types +extern NSString *const kGAIAppView; +extern NSString *const kGAIEvent; +extern NSString *const kGAISocial; +extern NSString *const kGAITransaction; +extern NSString *const kGAIItem; +extern NSString *const kGAIException; +extern NSString *const kGAITiming; + +/*! + This class provides several fields and methods useful as wire format parameter + names. The methods are used for wire format parameter names that are indexed. + */ + +@interface GAIFields : NSObject + +/*! + Generates the correct parameter name for a content group with an index. + + @param index the index of the content group. + + @return an NSString representing the content group parameter for the index. + */ ++ (NSString *)contentGroupForIndex:(NSUInteger)index; + +/*! + Generates the correct parameter name for a custon dimension with an index. + + @param index the index of the custom dimension. + + @return an NSString representing the custom dimension parameter for the index. + */ ++ (NSString *)customDimensionForIndex:(NSUInteger)index; + +/*! + Generates the correct parameter name for a custom metric with an index. + + @param index the index of the custom metric. + + @return an NSString representing the custom metric parameter for the index. + */ ++ (NSString *)customMetricForIndex:(NSUInteger)index; + +@end diff --git a/source/Plugins/iOS/GAIHandler.h b/source/Plugins/iOS/GAIHandler.h new file mode 100644 index 0000000..a6b5172 --- /dev/null +++ b/source/Plugins/iOS/GAIHandler.h @@ -0,0 +1,24 @@ + +#import +#import "GAIDictionaryBuilder.h" + +void _setName(char *); +void _set(char * parameterName, char * value); +char* _get(char * parameterName); +void _send(NSDictionary * parameters); +void _setProductName(char * name); +void _setProductVersion(char * version); +void _setOptOut(bool optOut); +void _setDispatchInterval(int time); +void _setTrackUncaughtExceptions(bool trackUncaughtExceptions); +void _setDryRun(bool dryRun); +id _getTrackerWithName(char* name, char* trackingId); +id _getTrackerWithTrackingId(char* trackingId); +void _removeTrackerByName(char* trackingId); +void _dispatch(); + + +@interface GAIHandler : NSObject + ++ (void) addAdditionalParametersToBuilder: (GAIDictionaryBuilder*)builder; +@end diff --git a/source/Plugins/iOS/GAIHandler.m b/source/Plugins/iOS/GAIHandler.m new file mode 100644 index 0000000..a5622c5 --- /dev/null +++ b/source/Plugins/iOS/GAIHandler.m @@ -0,0 +1,259 @@ +/*! + Copyright 2014 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#import "GAIHandler.h" +#import "GAI.h" +#import "GAITracker.h" +#import "GAILogger.h" +#import "GAIDictionaryBuilder.h" +#import "GAIFields.h" + +@implementation GAIHandler + +bool hasCampaignParameters = false; +bool startSessionOnNextHit = false; +bool endSessionOnNextHit = false; +NSDictionary *campaignData; + +GAI* shared_instance() { + return [GAI sharedInstance]; +} + +id gai_default_tracker() { + return [[GAI sharedInstance] defaultTracker]; +} + +BOOL getOptOut() { + return [GAI sharedInstance].optOut; +} + +void setOptOut(bool opt_out) { + [GAI sharedInstance].optOut = opt_out; +} + +void anonymizeIP(){ + id tracker = [[GAI sharedInstance] defaultTracker]; + [tracker set:kGAIAnonymizeIp value:@"1"]; +} + +void setSampleFrequency(int sampleFrequency) { + id tracker = [[GAI sharedInstance] defaultTracker]; + [tracker set:kGAISampleRate value:sampleFrequency]; +} + +void setLogLevel(int logLevel) { + [[GAI sharedInstance].logger setLogLevel:logLevel]; +} + +void setDispatchInterval(int dispatch_interval) { + [GAI sharedInstance].dispatchInterval = dispatch_interval; +} + +void setTrackUncaughtExceptions(bool track_uncaught_exceptions) { + [GAI sharedInstance].trackUncaughtExceptions = track_uncaught_exceptions; +} + +void setDryRun(bool dry_run) { + [GAI sharedInstance].dryRun = dry_run; +} + +void startSession() { + startSessionOnNextHit = true; +} + +void stopSession() { + endSessionOnNextHit = true; +} + +id trackerWithName(char *name, char *trackingId) { + return [[GAI sharedInstance] trackerWithName: [NSString stringWithUTF8String:name] + trackingId: [NSString stringWithUTF8String:trackingId]]; +} + +id trackerWithTrackingId(char *trackingId) { + return [[GAI sharedInstance] trackerWithTrackingId:[NSString stringWithUTF8String:trackingId ]]; +} + + +void dispatch() { + [[GAI sharedInstance] dispatch]; +} + +void setName(char *name) { + id tracker = [[GAI sharedInstance] defaultTracker]; + [tracker setName:[NSString stringWithUTF8String:name]]; +} + +void setBool(const char * parameterName, const BOOL isValue) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + [tracker set:[NSString stringWithUTF8String:parameterName] + value:isValue ? [@YES stringValue] : [@NO stringValue]]; +} + +void set(const char * parameterName, const char * value ) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + [tracker set:[NSString stringWithUTF8String:parameterName] + value:[NSString stringWithUTF8String:value ]]; +} + +NSString* get(const char * parameterName) { + id tracker = [[GAI sharedInstance] defaultTracker]; + return [tracker get:[NSString stringWithUTF8String:parameterName]]; +} + +void setCustomDimensionOnTracker(int index, char * value) { + id tracker = [[GAI sharedInstance] defaultTracker]; + [tracker set:[GAIFields customDimensionForIndex:index] + value:[NSString stringWithUTF8String:value]]; +} + +void setCustomMetricOnTracker(int index, char * value) { + id tracker = [[GAI sharedInstance] defaultTracker]; + [tracker set:[GAIFields customMetricForIndex:index] + value:[NSString stringWithUTF8String:value]]; +} + +void buildCampaignParametersDictionary(const char * source, const char * medium, const char * name, const char * content, const char * keyword) { + campaignData = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String:source], kGAICampaignSource, + [NSString stringWithUTF8String:medium], kGAICampaignMedium, + [NSString stringWithUTF8String:name], kGAICampaignName, + [NSString stringWithUTF8String:content], kGAICampaignContent, + [NSString stringWithUTF8String:keyword], kGAICampaignKeyword, nil]; + hasCampaignParameters = true; +} + ++ (void) addAdditionalParametersToBuilder: (GAIDictionaryBuilder*)builder { + if (hasCampaignParameters) { + [builder setAll: campaignData]; + } + + if (startSessionOnNextHit) { + startSessionOnNextHit = false; + [builder set:@"start" forKey:kGAISessionControl]; + } else if (endSessionOnNextHit) { + endSessionOnNextHit = false; + [builder set:@"end" forKey:kGAISessionControl]; + } + +} + +void sendAppView(const char * value) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createAppView]; + [tracker set:kGAIScreenName + value:[NSString stringWithUTF8String:value]]; + + [GAIHandler addAdditionalParametersToBuilder:builder]; + + [tracker send:[builder build]]; +} + +void sendEvent(const char * category, const char * action, const char * label, const long long value) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createEventWithCategory:[NSString stringWithUTF8String:category] + action:[NSString stringWithUTF8String:action] + label:[NSString stringWithUTF8String:label] + value:[NSNumber numberWithLongLong:value]]; + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; +} + +void sendTransaction( const char * transactionID, const char* affiliation, const double revenue, const double tax, const double shipping, const char* currencyCode) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createTransactionWithId:[NSString stringWithUTF8String:transactionID] + affiliation:[NSString stringWithUTF8String:affiliation] + revenue:[NSNumber numberWithDouble:revenue] + tax:[NSNumber numberWithDouble:tax] + shipping:[NSNumber numberWithDouble:shipping] + currencyCode:[NSString stringWithUTF8String:currencyCode]]; + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; +} + +void sendItemWithTransaction(const char * transactionID, const char * name, const char * sku, const char * category, const double price, const long long quantity, const char * currencyCode) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createItemWithTransactionId:[NSString stringWithUTF8String:transactionID] + name:[NSString stringWithUTF8String:name] + sku:[NSString stringWithUTF8String:sku] + category:[NSString stringWithUTF8String:category] + price:[NSNumber numberWithDouble:price] + quantity:[NSNumber numberWithLongLong:quantity] + currencyCode:[NSString stringWithUTF8String:currencyCode]]; + + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; +} + + +void sendException(const char * errorDescription, const bool isFatal) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createExceptionWithDescription:[NSString stringWithUTF8String:errorDescription] + withFatal:isFatal ? @YES : @NO]; + + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; + +} + +void sendSocial(const char * socialNetwork, const char * socialAction, const char * targetUrl) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createSocialWithNetwork:[NSString stringWithUTF8String:socialNetwork] + action:[NSString stringWithUTF8String:socialAction] + target:[NSString stringWithUTF8String:targetUrl]]; + + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; +} + +void sendTiming(const char * timingCategory, const long long timingInterval, const char * name, const char * label) { + id tracker = [[GAI sharedInstance] defaultTracker]; + + GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createTimingWithCategory:[NSString stringWithUTF8String:timingCategory] + interval:[NSNumber numberWithLongLong:timingInterval] + name:[NSString stringWithUTF8String:name] + label:[NSString stringWithUTF8String:label]]; + [GAIHandler addAdditionalParametersToBuilder:builder]; + [tracker send:[builder build]]; +} + +void send(const char* parameters) { + id tracker = [[GAI sharedInstance] defaultTracker]; + NSString *attris = [NSString stringWithUTF8String:parameters]; + NSArray *attributesArray = [attris componentsSeparatedByString:@"\n"]; + + NSMutableDictionary *oAttributes = [[NSMutableDictionary alloc] init]; + for (int i=0; i < [attributesArray count]; i++) { + NSString *keyValuePair = [attributesArray objectAtIndex:i]; + NSRange range = [keyValuePair rangeOfString:@"="]; + if (range.location != NSNotFound) { + NSString *key = [keyValuePair substringToIndex:range.location]; + NSString *value = [keyValuePair substringFromIndex:range.location+1]; + [oAttributes setObject:value forKey:key]; + } + } + [tracker send:oAttributes]; +} + +@end diff --git a/source/Plugins/iOS/GAILogger.h b/source/Plugins/iOS/GAILogger.h new file mode 100644 index 0000000..06291f2 --- /dev/null +++ b/source/Plugins/iOS/GAILogger.h @@ -0,0 +1,49 @@ +/*! + @header GAILogger.h + @abstract Google Analytics iOS SDK Source + @copyright Copyright 2011 Google Inc. All rights reserved. + */ + +#import + +typedef NS_ENUM(NSUInteger, GAILogLevel) { + kGAILogLevelNone = 0, + kGAILogLevelError = 1, + kGAILogLevelWarning = 2, + kGAILogLevelInfo = 3, + kGAILogLevelVerbose = 4 +}; + +/*! + Protocol to be used for logging debug and informational messages from the SDK. + Implementations of this protocol can be provided to the |GAI| class, + to be used as the logger by the SDK. See the |logger| property in GAI.h. + */ +@protocol GAILogger +@required + +/*! + Only messages of |logLevel| and below are logged. + */ +@property (nonatomic, assign) GAILogLevel logLevel; + +/*! + Logs message with log level |kGAILogLevelVerbose|. + */ +- (void)verbose:(NSString *)message; + +/*! + Logs message with log level |kGAILogLevelInfo|. + */ +- (void)info:(NSString *)message; + +/*! + Logs message with log level |kGAILogLevelWarning|. + */ +- (void)warning:(NSString *)message; + +/*! + Logs message with log level |kGAILogLevelError|. + */ +- (void)error:(NSString *)message; +@end diff --git a/source/Plugins/iOS/GAITrackedViewController.h b/source/Plugins/iOS/GAITrackedViewController.h new file mode 100644 index 0000000..5cbabdd --- /dev/null +++ b/source/Plugins/iOS/GAITrackedViewController.h @@ -0,0 +1,34 @@ +/*! + @header GAITrackedViewController.h + @abstract Google Analytics for iOS Tracked View Controller Header + @version 2.0 + @copyright Copyright 2012 Google Inc. All rights reserved. + */ + +#import +#import + +@protocol GAITracker; + +/*! + Extends UIViewController to generate Google Analytics appview calls + whenever the view appears; this is done by overriding the `viewDidAppear:` + method. The screen name must be set for any tracking calls to be made. + + By default, this will use [GAI defaultTracker] for tracking calls, but one can + override this by setting the tracker property. + */ +@interface GAITrackedViewController : UIViewController + +/*! + The tracker on which view tracking calls are be made, or `nil`, in which case + [GAI defaultTracker] will be used. + */ +@property(nonatomic, assign) id tracker; +/*! + The screen name, for purposes of Google Analytics tracking. If this is `nil`, + no tracking calls will be made. + */ +@property(nonatomic, copy) NSString *screenName; + +@end diff --git a/source/Plugins/iOS/GAITracker.h b/source/Plugins/iOS/GAITracker.h new file mode 100644 index 0000000..43b5e20 --- /dev/null +++ b/source/Plugins/iOS/GAITracker.h @@ -0,0 +1,53 @@ +/*! + @header GAITracker.h + @abstract Google Analytics iOS SDK Tracker Header + @version 3.0 + @copyright Copyright 2013 Google Inc. All rights reserved. +*/ + +#import + +/*! + Google Analytics tracking interface. Obtain instances of this interface from + [GAI trackerWithTrackingId:] to track screens, events, transactions, timing, + and exceptions. The implementation of this interface is thread-safe, and no + calls are expected to block or take a long time. All network and disk activity + will take place in the background. + */ +@protocol GAITracker + +/*! + Name of this tracker. + */ +@property(nonatomic, readonly) NSString *name; + +/*! + Set a tracking parameter. + + @param parameterName The parameter name. + + @param value The value to set for the parameter. If this is nil, the + value for the parameter will be cleared. + */ +- (void)set:(NSString *)parameterName + value:(NSString *)value; + +/*! + Get a tracking parameter. + + @param parameterName The parameter name. + + @returns The parameter value, or nil if no value for the given parameter is + set. + */ +- (NSString *)get:(NSString *)parameterName; + +/*! + Queue tracking information with the given parameter values. + + @param parameters A map from parameter names to parameter values which will be + set just for this piece of tracking information, or nil for none. + */ +- (void)send:(NSDictionary *)parameters; + +@end diff --git a/source/Plugins/iOS/libGoogleAnalyticsServices.a b/source/Plugins/iOS/libGoogleAnalyticsServices.a new file mode 100644 index 0000000..5716cd0 Binary files /dev/null and b/source/Plugins/iOS/libGoogleAnalyticsServices.a differ