TrackingManager.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. using UnityEngine;
  2. using UnityEngine.Analytics;
  3. using System.Collections.Generic;
  4. using System;
  5. public class TrackingManager:MonoBehaviour {
  6. /*
  7. * A MonoBehavior to track using different systems.
  8. */
  9. // https://github.com/googleanalytics/google-analytics-plugin-for-unity
  10. public GoogleAnalyticsV3 googleAnalyticsTracker;
  11. public bool useGoogleAnalytics;
  12. public bool useUnityAnalytics;
  13. public bool loggingEnabled;
  14. public bool trackingEnabled;
  15. private static TrackingManager instance;
  16. // ================================================================================================================
  17. // MAIN EVENT INTERFACE -------------------------------------------------------------------------------------------
  18. void Awake() {
  19. instance = this;
  20. }
  21. void Start() {
  22. if (!trackingEnabled) return;
  23. // Google Analytics
  24. if (useGoogleAnalytics && googleAnalyticsTracker != null) {
  25. // Start session
  26. googleAnalyticsTracker.StartSession();
  27. }
  28. // Start session
  29. // The id is set in "Edit > Project Settings > Player" (as the cloud id)
  30. // Custom tracking: platform
  31. trackCustomEventPlatform();
  32. // Custom tracking: application
  33. trackCustomEventApplication();
  34. // Custom tracking: device
  35. trackCustomEventDevice();
  36. // Custom tracking: user
  37. trackCustomEventUser();
  38. // TODO: performance (average fps, lowest fps)
  39. }
  40. void Update() {
  41. }
  42. void OnDestroy() {
  43. if (!trackingEnabled) return;
  44. if (useGoogleAnalytics && googleAnalyticsTracker != null) {
  45. googleAnalyticsTracker.StopSession();
  46. }
  47. }
  48. /*
  49. public void DispatchHits();
  50. */
  51. private void trackCustomEventApplication() {
  52. trackCustomEvent("info.application",
  53. "version", "~" + Application.version.ToString(), // Float
  54. "uri", Application.absoluteURL, // "" on editor and while testing on Android
  55. "bundle", Application.bundleIdentifier, // "com.zehfernando.KanaGenius"
  56. "install_mode", Application.installMode // "Editor" (testing on editor), "DeveloperBuild" (testing on Android)
  57. );
  58. }
  59. private void trackCustomEventPlatform() {
  60. #if UNITY_EDITOR
  61. string platformId = "editor-" + Application.platform;
  62. #elif UNITY_IPHONE
  63. string platformId = "ios";
  64. #elif UNITY_ANDROID
  65. string platformId = "android";
  66. #elif UNITY_STANDALONE_OSX
  67. string platformId = "osx";
  68. #elif UNITY_STANDALONE_WIN
  69. string platformId = "windows";
  70. #elif UNITY_WEBPLAYER
  71. string platformId = "web";
  72. #elif UNITY_WII
  73. string platformId = "wii";
  74. #elif UNITY_PS3
  75. string platformId = "ps3";
  76. #elif UNITY_XBOX360
  77. string platformId = "xbox360";
  78. #elif UNITY_FLASH
  79. string platformId = "flash";
  80. #elif UNITY_BLACKBERRY
  81. string platformId = "blackberry";
  82. #elif UNITY_WP8
  83. string platformId = "windows-phone-8";
  84. #elif UNITY_METRO
  85. string platformId = "windows-metro";
  86. #else
  87. string platformId = "unknown-" + Application.platform;
  88. #endif
  89. trackCustomEvent("info.platform",
  90. "id", platformId, // "editor-WindowsEditor", "android"
  91. "os", SystemInfo.operatingSystem, // "Windows 7 Service Pack 1 (6.1.7601) 64bit", "Android OS 5.1 / API-22 (LMY47D/1743759)"
  92. "unity_runtime_version", Application.unityVersion, // "5.0.1f1"
  93. "internet", Application.internetReachability // "ReachableViaLocalAreaNetwork"
  94. );
  95. }
  96. private void trackCustomEventDevice() {
  97. trackCustomEvent("info.device",
  98. "device_model", SystemInfo.deviceModel, // "AMD Phenom(tm) II X4 955 Processor (8191 MB)", "LGE Nexus 5"
  99. // "device_name", SystemInfo.deviceName, // "ZEH-PC7"
  100. "device_type", SystemInfo.deviceType, // "Desktop", "Handheld"
  101. "system_memory", "~" + SystemInfo.systemMemorySize.ToString() + "MB", // 8191 as number
  102. "graphics_memory", "~" + SystemInfo.graphicsMemorySize.ToString(),
  103. "is_mobile", Application.isMobilePlatform,
  104. "is_console", Application.isConsolePlatform,
  105. // TODO: SystemInfo.processorType, processorCount
  106. "dpi", "~" + Screen.dpi.ToString(),
  107. "screen_width", "~" + Screen.width.ToString(),
  108. "screen_height", "~" + Screen.height.ToString(),
  109. "screen_size", "~" + (Math.Round(Mathf.Sqrt(Screen.width*Screen.width+Screen.height*Screen.height)/Screen.dpi*10f)/10f).ToString() + "in"
  110. );
  111. }
  112. private void trackCustomEventUser() {
  113. trackCustomEvent("info.user",
  114. "os_language", Application.systemLanguage // "English"
  115. );
  116. }
  117. private void trackUACustomEvent(string eventType, Dictionary<string, object> parameters) {
  118. // Track a custom event using Unity Analytics
  119. //https://analytics.cloud.unity3d.com/docs
  120. // Max 10 params per custom event
  121. var result = Analytics.CustomEvent(eventType, parameters);
  122. if (result != AnalyticsResult.Ok) {
  123. Debug.LogWarning("TRACKING :: Error: tracking custom event [" + eventType + "] didn't work, returned [" + result + "]");
  124. }
  125. }
  126. private void trackGACustomEvent(string eventType, Dictionary<string, object> parameters) {
  127. foreach (var entry in parameters) {
  128. googleAnalyticsTracker.LogEvent(new EventHitBuilder()
  129. .SetEventCategory(eventType)
  130. .SetEventAction(entry.Key)
  131. .SetEventLabel(Convert.ToString(entry.Value)));
  132. //.SetEventValue(5));
  133. }
  134. }
  135. // ================================================================================================================
  136. // PUBLIC INTERFACE -----------------------------------------------------------------------------------------------
  137. public static TrackingManager getInstance() {
  138. return instance;
  139. }
  140. public void trackScreen(string screenId) {
  141. /*
  142. if (useGameAnalytics) {
  143. GA.API.Design.NewEvent("navigation:screen:" + screenId);
  144. }
  145. */
  146. if (!trackingEnabled) return;
  147. if (loggingEnabled) {
  148. Debug.Log("TRACKING :: Screen : Screen id [" + screenId + "]");
  149. }
  150. if (useGoogleAnalytics && googleAnalyticsTracker != null) {
  151. googleAnalyticsTracker.LogScreen(screenId);
  152. // //Builder Hit with all App View parameters (all parameters required):
  153. //googleAnalytics.LogScreen(new AppViewHitBuilder() .SetScreenName("Main Menu"));
  154. }
  155. if (useUnityAnalytics) {
  156. trackUACustomEvent("event.navigation.screen", new Dictionary<string, object>{{"id", screenId}});
  157. }
  158. }
  159. private void trackCustomEvent(string eventType, params object[] paramValues) {
  160. if (!trackingEnabled) return;
  161. var parametersDict = new Dictionary<string, object>();
  162. for (var i = 0; i < paramValues.Length; i += 2) {
  163. parametersDict.Add(paramValues[i] as string, Convert.ToString(paramValues[i+1]));
  164. }
  165. if (loggingEnabled) {
  166. string paramList = "";
  167. for (var i = 0; i < paramValues.Length; i += 2) {
  168. if (i > 0) paramList += ",";
  169. paramList += (paramValues[i] as string) + ":" + paramValues[i + 1];
  170. }
  171. Debug.Log("TRACKING :: Custom Event :: Event [" + eventType + "], parameters [" + paramList + "]");
  172. }
  173. if (useGoogleAnalytics && googleAnalyticsTracker) {
  174. trackGACustomEvent(eventType, parametersDict);
  175. }
  176. if (useUnityAnalytics) {
  177. trackUACustomEvent(eventType, parametersDict);
  178. }
  179. }
  180. /* Exceptions
  181. * public void LogException(string exceptionDescription, bool isFatal);
  182. *
  183. * googleAnalytics.LogException("Incorrect input exception", true);
  184. //Builder Hit with all Exception parameters
  185. googleAnalytics.LogException(new ExceptionHitBuilder()
  186. .SetExceptionDescription("Incorrect input exception")
  187. .SetFatal(true));
  188. //Builder Hit with minimum required Exception parameters
  189. googleAnalytics.LogException(new ExceptionHitBuilder());
  190. * */
  191. /*
  192. * Timings
  193. *
  194. * googleAnalytics.LogTiming("Loading", 50L, "Main Menu", "First Load");
  195. //Builder Hit with all Timing parameters
  196. googleAnalytics.LogTiming(new TimingHitBuilder()
  197. .SetTimingCategory("Loading")
  198. .SetTimingInterval(50L)
  199. .SetTimingName("Main Menu")
  200. .SetTimingLabel("First load"));
  201. //Builder Hit with minimum required Timing parameters
  202. googleAnalytics.LogTiming(new TimingHitBuilder()
  203. .SetTimingCategory("Loading"));
  204. * */
  205. /* Social
  206. *
  207. * googleAnalytics.LogSocial("twitter", "retweet", "twitter.com/googleanalytics/status/482210840234295296");
  208. //Builder Hit with all Social parameters (all parameters required)
  209. googleAnalytics.LogSocial(new SocialHitBuilder()
  210. .SetSocialNetwork("Twitter")
  211. .SetSocialAction("Retweet")
  212. .SetSocialTarget("twitter.com/googleanalytics/status/482210840234295296"));
  213. * */
  214. public void trackTransaction(string productId, string purchaseMethod, float price, string currency) {
  215. if (!trackingEnabled) return;
  216. if (loggingEnabled) {
  217. Debug.Log("TRACKING :: Transaction : Product [" + productId + "], purchase method [" + purchaseMethod + "], price [" + price + ", currency [" + currency + "]");
  218. }
  219. if (useGoogleAnalytics && googleAnalyticsTracker != null) {
  220. googleAnalyticsTracker.LogTransaction(productId, purchaseMethod, price, 0.0, 0.0, currency);
  221. }
  222. if (useUnityAnalytics) {
  223. Analytics.Transaction(purchaseMethod + "-" + productId, Convert.ToDecimal(price), currency);
  224. }
  225. }
  226. /* Ecommerce - transaction
  227. *
  228. * googleAnalytics.LogTransaction("TRANS001", "Coin Store", 3.0, 0.0, 0.0);
  229. googleAnalytics.LogTransaction("TRANS001", "Coin Store", 3.0, 0.0, 0.0, "USD");
  230. //Builder Hit with all Transaction parameters
  231. googleAnalytics.LogTransaction(new TransactionHitBuilder()
  232. .SetTransactionID("TRANS001")
  233. .SetAffiliation("Coin Store")
  234. .SetRevenue(3.0)
  235. .SetTax(0)
  236. .SetShipping(0.0)
  237. .SetCurrencyCode("USD"));
  238. //Builder Hit with minimum required Transaction parameters
  239. googleAnalytics.LogTransaction(new TransactionHitBuilder()
  240. .SetTransactionID("TRANS001")
  241. .SetAffiliation("Coin Store"));
  242. *
  243. * Ecommerce - item hit
  244. *
  245. * googleAnalytics.LogItem("TRANS001", "Sword", "SWORD1223", "Weapon", 3.0, 2);
  246. googleAnalytics.LogItem("TRANS001", "Sword", "SWORD1223", "Weapon", 3.0, 2, "USD");
  247. //Builder Hit with all Item parameters
  248. googleAnalytics.LogItem(new ItemHitBuilder()
  249. .SetTransactionID("TRANS001")
  250. .SetName("Sword")
  251. .SetSKU("SWORD1223")
  252. .SetCategory("Weapon")
  253. .SetPrice(3.0)
  254. .SetQuantity(2)
  255. .SetCurrencyCode("USD"));
  256. //Builder Hit with minimum required Item parameters
  257. googleAnalytics.LogItem(new ItemHitBuilder()
  258. .SetTransactionID("TRANS001")
  259. .SetName("Sword")
  260. .SetSKU("SWORD1223"));
  261. *
  262. */
  263. /* Custom dimensions, as part of an event
  264. *
  265. * public T SetCustomDimension(int dimensionNumber, string value);
  266. *
  267. * googleAnalytics.LogScreen(new AppViewHitBuilder()
  268. .SetScreenName("Another screen")
  269. .SetCustomDimension(1, "200"));
  270. * */
  271. /* Custom metrics
  272. *
  273. * public T SetCustomMetric(int metricNumber, string value);
  274. Sample Hit:
  275. googleAnalytics.LogEvent(new EventHitBuilder()
  276. .SetEventCategory("Achievement")
  277. .SetEventAction("Unlocked")
  278. .SetEventLabel("Slay 10 dragons")
  279. .SetEventValue(5)
  280. .SetCustomMetric(3, "200"));
  281. * */
  282. /* Campaign parameters, as part of an event
  283. *
  284. * googleAnalytics.LogTiming(new TimingHitBuilder()
  285. .SetTimingCategory("Loading")
  286. .SetTimingInterval(50L)
  287. .SetTimingName("Main Menu")
  288. .SetTimingLabel("First load")
  289. .SetCampaignName("Summer Campaign")
  290. .SetCampaignSource("google")
  291. .SetCampaignMedium("cpc")
  292. .SetCampaignKeyword("games")
  293. .SetCampaignContent("Free power ups")
  294. .SetCampaignId("Summer1"));
  295. //Builder Hit with minimum required Campaign parameters
  296. googleAnalytics.LogTiming(new TimingHitBuilder()
  297. .SetTimingCategory("Loading")
  298. .SetTimingInterval(50L)
  299. .SetTimingName("Main Menu")
  300. .SetTimingLabel("First load")
  301. .SetCampaignSource("google");
  302. * */
  303. // ================================================================================================================
  304. // INTERNAL INTERFACE ---------------------------------------------------------------------------------------------
  305. }