From 85c8058158c39a193a2f551ffa5d34ad38d3f088 Mon Sep 17 00:00:00 2001 From: huyufei Date: Thu, 25 Jul 2024 22:59:47 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E6=89=93=E7=82=B9=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E9=87=8D=E6=9E=84=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --story=1021118 --user=yufei.hu 【中台】【打点】打点初始化重构,添加日志缓存功能 https://www.tapd.cn/33527076/s/1159704 Signed-off-by: huyufei --- Runtime/ABTest/ABTestManager.cs | 2 +- Runtime/GuruAdjust/AdjustService.cs | 26 +- .../Runtime/Script/GuruAnalytics.cs | 189 +++++------ .../Runtime/Script/IAnalyticsAgent.cs | 4 +- .../Script/Impl/AnalyticsAgentAndroid.cs | 8 +- .../Runtime/Script/Impl/AnalyticsAgentIOS.cs | 7 +- ...ticsAgentStub.cs => AnalyticsAgentMock.cs} | 13 +- ...tub.cs.meta => AnalyticsAgentMock.cs.meta} | 0 ...uAnalyticsDemo.cs => GuruAnalyticsDemo.cs} | 33 +- ...Demo.cs.meta => GuruAnalyticsDemo.cs.meta} | 0 .../Runtime/Script/Consent/GoogleDMAHelper.cs | 2 +- Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs | 173 ++++++++-- .../Runtime/Analytics/AdImpressionData.cs | 40 +++ .../Analytics/AdImpressionData.cs.meta | 3 + .../Analytics/Analytics.AdjustToken.cs | 2 +- .../Runtime/Analytics/Analytics.Ads.cs | 40 +-- .../Runtime/Analytics/Analytics.Const.cs | 6 + .../Runtime/Analytics/Analytics.Custom.cs | 32 +- .../Runtime/Analytics/Analytics.Economic.cs | 4 +- .../Analytics/Analytics.TemplateDefine.cs | 67 ++-- .../GuruCore/Runtime/Analytics/Analytics.cs | 309 +++++++----------- .../GuruCore/Runtime/Analytics/Events.meta | 3 + .../Analytics/Events/AbstractEventDriver.cs | 46 +++ .../Events/AbstractEventDriver.cs.meta | 3 + .../Analytics/Events/AdjustEventDriver.cs | 35 ++ .../Events/AdjustEventDriver.cs.meta | 3 + .../Runtime/Analytics/Events/FBEventDriver.cs | 21 ++ .../Analytics/Events/FBEventDriver.cs.meta | 3 + .../Analytics/Events/FirebaseEventDriver.cs | 55 ++++ .../Events/FirebaseEventDriver.cs.meta | 3 + .../Analytics/Events/GuruEventBuffer.cs | 55 ++++ .../Analytics/Events/GuruEventBuffer.cs.meta | 3 + .../Analytics/Events/GuruEventDriver.cs | 11 + .../Analytics/Events/GuruEventDriver.cs.meta | 3 + .../Runtime/Data/StandardProperties.cs | 6 +- Runtime/GuruCore/Runtime/FB/FBService.cs | 54 ++- .../GuruCore/Runtime/Firebase/FirebaseUtil.cs | 4 +- .../Runtime/Reporter/CrashlyticsAgent.cs | 49 +-- .../GuruCore/Runtime/Settings/GuruSettings.cs | 4 + .../GuruIAP/Runtime/Code/IAPServiceBase.cs | 4 +- 40 files changed, 829 insertions(+), 496 deletions(-) rename Runtime/GuruAnalytics/Runtime/Script/Impl/{AnalyticsAgentStub.cs => AnalyticsAgentMock.cs} (94%) rename Runtime/GuruAnalytics/Runtime/Script/Impl/{AnalyticsAgentStub.cs.meta => AnalyticsAgentMock.cs.meta} (100%) rename Runtime/GuruAnalytics/~Sample/{CuruAnalyticsDemo.cs => GuruAnalyticsDemo.cs} (79%) rename Runtime/GuruAnalytics/~Sample/{CuruAnalyticsDemo.cs.meta => GuruAnalyticsDemo.cs.meta} (100%) create mode 100644 Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs.meta create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs create mode 100644 Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs.meta diff --git a/Runtime/ABTest/ABTestManager.cs b/Runtime/ABTest/ABTestManager.cs index 97c82e1..337d26a 100644 --- a/Runtime/ABTest/ABTestManager.cs +++ b/Runtime/ABTest/ABTestManager.cs @@ -72,7 +72,7 @@ namespace Guru for (int i = 0; i < _params.Count; i++) { // 上报实验AB属性 - GuruAnalytics.SetUserProperty(_params[i].id, _params[i].group); + GuruAnalytics.Instance.SetUserProperty(_params[i].id, _params[i].group); #if UNITY_EDITOR Debug.Log($"[AB] --- Add AB Param {_params[i].ToString()}"); #else diff --git a/Runtime/GuruAdjust/AdjustService.cs b/Runtime/GuruAdjust/AdjustService.cs index 4959ea7..1bb2697 100644 --- a/Runtime/GuruAdjust/AdjustService.cs +++ b/Runtime/GuruAdjust/AdjustService.cs @@ -18,7 +18,7 @@ namespace Guru public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件 public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件 - private static Action _onSessionSuccessCallback; + private static Action _onInitComplete; private static string _adId = ""; @@ -42,6 +42,9 @@ namespace Guru return _adjustId; // Adjust AdId; } } + + private static bool _isReady = false; + public static bool IsReady => _isReady; #region 启动服务 @@ -50,9 +53,9 @@ namespace Guru /// /// /// MIR 追踪 AppID - /// + /// /// - public static void StartService(string appToken, string fbAppId = "", Action onSessionSuccess = null, Action onDeeplinkCallback = null) + public static void StartService(string appToken, string fbAppId = "", Action onInitComplete = null, Action onDeeplinkCallback = null) { if (string.IsNullOrEmpty(appToken)) { @@ -60,7 +63,7 @@ namespace Guru return; } - _onSessionSuccessCallback = onSessionSuccess; + _onInitComplete = onInitComplete; InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数 @@ -173,7 +176,8 @@ namespace Guru var adid = sessionSuccessData.Adid; _adjustId = adid; - _onSessionSuccessCallback?.Invoke(adid); + _isReady = true; + _onInitComplete?.Invoke(adid); } @@ -367,16 +371,16 @@ namespace Guru /// 广告收入上报 (Adjust 特有的接口) /// /// - public static void TrackADRevenue(MaxSdkBase.AdInfo adInfo) + public static void TrackADRevenue(AdImpressionData impressionData) { - if (adInfo == null) + if (impressionData == null) return; var adRevenue = new AdjustAdRevenue(AdjustConfig.AdjustAdRevenueSourceAppLovinMAX); - adRevenue.setRevenue(adInfo.Revenue, "USD"); - adRevenue.setAdRevenueNetwork(adInfo.NetworkName); - adRevenue.setAdRevenueUnit(adInfo.AdUnitIdentifier); - adRevenue.setAdRevenuePlacement(adInfo.Placement); + adRevenue.setRevenue(impressionData.value, "USD"); + adRevenue.setAdRevenueNetwork(impressionData.ad_source); + adRevenue.setAdRevenueUnit(impressionData.ad_unit_name); + adRevenue.setAdRevenuePlacement(impressionData.ad_placement); Adjust.trackAdRevenue(adRevenue); } diff --git a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs index 708dc45..6708a08 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs @@ -18,33 +18,56 @@ namespace Guru public static readonly string Tag = "[ANU]"; private static readonly string ActionName = "logger_error"; - internal const int EventPriorityDefault = 10; + private const int EventPriorityDefault = 10; + + + private static GuruAnalytics _instance; + public static GuruAnalytics Instance + { + get + { + if (_instance == null) + { + throw new Exception("GuruAnalytics not initialized. Please call first."); + } + return _instance; + } + } + + + private bool _isReady = false; + public bool IsReady => _isReady; - private static IAnalyticsAgent _agent; - - public static IAnalyticsAgent Agent + private IAnalyticsAgent _agent; + private IAnalyticsAgent Agent { get { if (_agent == null) { - #if UNITY_EDITOR - _agent = new AnalyticsAgentStub(); - #elif UNITY_ANDROID +#if UNITY_EDITOR + _agent = new AnalyticsAgentMock(); +#elif UNITY_ANDROID _agent = new AnalyticsAgentAndroid(); - #elif UNITY_IOS +#elif UNITY_IOS _agent = new AnalyticsAgentIOS(); - #endif +#endif } + + if (_agent == null) + { + throw new NotImplementedException("You Should Implement IAnalyticsAgent on platform first."); + } + return _agent; } } - private static Dictionary _userProperties; + private Dictionary _userProperties; /// /// 用户属性缓存字典 /// - public static Dictionary UserProperties + private Dictionary UserProperties { get { @@ -59,13 +82,13 @@ namespace Guru /// /// 错误 code 表 /// - public static List ErrorCodeList = new List(); - private static bool _enableErrorLog = false; + public List ErrorCodeList = new List(); + private bool _enableErrorLog = false; /// /// 启动日志错误上报 /// - public static bool EnableErrorLog + public bool EnableErrorLog { get => _enableErrorLog; set @@ -81,35 +104,40 @@ namespace Guru /// /// 初始化接口 /// - public static void Init(string appId, string deviceInfo, bool isDebug = false, + public static void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false, bool enableErrorLog = false) { Debug.Log($"{Tag} --- Guru Analytics [{Version}] initialing..."); - _enableErrorLog = enableErrorLog; - Agent?.Init(appId, deviceInfo, isDebug); - if(_enableErrorLog) InitCallbacks(); // 激活错误日志回调 + + if (_instance == null) + { + _instance = new GuruAnalytics(); + _instance.Agent.Init(appId, deviceInfo, onInitComplete, isDebug); + _instance.EnableErrorLog = enableErrorLog; + _instance._isReady = true; + } } /// /// 设置视图名称 /// /// - public static void SetScreen(string screenName) + public void SetScreen(string screenName) { if (string.IsNullOrEmpty(screenName)) return; CacheUserProperty($"screen_name", screenName); - Agent?.SetScreen(screenName); + Agent.SetScreen(screenName); } /// /// 设置广告ID /// /// - public static void SetAdId(string id) + public void SetAdId(string id) { if (string.IsNullOrEmpty(id)) return; CacheUserProperty($"ad_id", id); - Agent?.SetAdId(id); + Agent.SetAdId(id); } /// @@ -117,59 +145,59 @@ namespace Guru /// /// /// - public static void SetUserProperty(string key, string value) + public void SetUserProperty(string key, string value) { if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return; CacheUserProperty(key, value); // 添加用户属性 - Agent?.SetUserProperty(key, value); + Agent.SetUserProperty(key, value); } /// /// 设置Firebase ID /// /// - public static void SetFirebaseId(string id) + public void SetFirebaseId(string id) { if (string.IsNullOrEmpty(id)) return; CacheUserProperty($"firebase_id", id); - Agent?.SetFirebaseId(id); + Agent.SetFirebaseId(id); } /// /// 设置Adjust ID /// /// - public static void SetAdjustId(string id) + public void SetAdjustId(string id) { if (string.IsNullOrEmpty(id)) return; CacheUserProperty($"adjust_id", id); - Agent?.SetAdjustId(id); + Agent.SetAdjustId(id); } /// /// 设置设备ID /// /// - public static void SetDeviceId(string deviceId) + public void SetDeviceId(string deviceId) { if (string.IsNullOrEmpty(deviceId)) return; CacheUserProperty($"device_id", deviceId); - Agent?.SetDeviceId(deviceId); + Agent.SetDeviceId(deviceId); } - public static void SetAndroidID(string androidId) + public void SetAndroidID(string androidId) { if (string.IsNullOrEmpty(androidId)) return; CacheUserProperty(Analytics.PropertyAndroidID, androidId); } - public static void SetIDFV(string idfv) + public void SetIDFV(string idfv) { if (string.IsNullOrEmpty(idfv)) return; CacheUserProperty(Analytics.PropertyIDFV, idfv); } - public static void SetIDFA(string idfa) + public void SetIDFA(string idfa) { if (string.IsNullOrEmpty(idfa)) return; CacheUserProperty(Analytics.PropertyIDFA, idfa); @@ -180,17 +208,17 @@ namespace Guru /// 设置用户ID /// /// - public static void SetUid(string uid) + public void SetUid(string uid) { if (string.IsNullOrEmpty(uid)) return; CacheUserProperty($"uid", uid); - Agent?.SetUid(uid); + Agent.SetUid(uid); } /// /// 上报事件成功率 /// - public static void ReportEventSuccessRate() => Agent?.ReportEventSuccessRate(); + public void ReportEventSuccessRate() => Agent.ReportEventSuccessRate(); /// /// 上报打点事件 @@ -198,7 +226,7 @@ namespace Guru /// 事件名称 /// INT类型的值 /// - public static void LogEvent(string eventName, Dictionary data = null, int priority = -1) + public void LogEvent(string eventName, Dictionary data = null, int priority = -1) { string raw = ""; if (data != null && data.Count > 0) @@ -207,9 +235,10 @@ namespace Guru } if (priority < 0) priority = EventPriorityDefault; Debug.Log($"{Tag} --- LogEvent GuruAnalytics:{eventName} | raw: {raw} | priority: {priority}"); - Agent?.LogEvent(eventName, raw, priority); + Agent.LogEvent(eventName, raw, priority); } + /* private static string BuildParamsString(Dictionary data) { string raw = ""; @@ -221,8 +250,9 @@ namespace Guru } return raw; } + */ - private static string BuildParamsJson(Dictionary data) + private string BuildParamsJson(Dictionary data) { try { @@ -240,6 +270,7 @@ namespace Guru return ""; } + /* /// /// 构建带有类型格式的Str值 /// @@ -260,15 +291,16 @@ namespace Guru return $"{kvp.Key}:s{kvp.Value}"; } + */ /// /// 设置太极02值 /// /// - public static void SetTch02Value(double value) + public void SetTch02Value(double value) { Debug.Log($"{Tag} set tch_02_value:{value}"); - Agent?.SetTch02Value(value); + Agent.SetTch02Value(value); } #endregion @@ -289,37 +321,19 @@ namespace Guru /// /// /// - private static void CacheUserProperty(string key, string value) + private void CacheUserProperty(string key, string value) { - bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value; + // bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value; UserProperties[key] = value; // if (needUpdate) UpdateAllUserProperties(); } - private static void UpdateAllUserProperties() - { - if (UserProperties != null && UserProperties.Count > 0) - { - var keys = UserProperties.Keys.ToArray(); - int i = 0; - string key = ""; - while (i < keys.Length) - { - key = keys[i]; - if(!string.IsNullOrEmpty(key)) SetUserProperty(key, UserProperties[key]); - i++; - } - keys = null; - } - } - - #endregion #region 日志回调 - private static void InitCallbacks() + private void InitCallbacks() { try { @@ -339,8 +353,8 @@ namespace Guru /// /// 获取SDK回调 /// - /// - private static void OnSDKCallback(string raw) + /// + private void OnSDKCallback(string raw) { if (string.IsNullOrEmpty(raw)) return; if (!raw.Contains($"\"{ActionName}\"")) return; // 不对其他行为的日志进行过滤 @@ -352,7 +366,7 @@ namespace Guru /// /// /// - private static void OnLoggerErrorEvent(int code, string errorInfo = "") + private void OnLoggerErrorEvent(int code, string errorInfo = "") { // Debug.Log($"{Tag} --- OnLoggerErrorEvent: code:{code}\tinfo:{errorInfo}"); @@ -381,17 +395,13 @@ namespace Guru parameters["err"] = errorInfo; Debug.Log($"{Tag} ------ ErrorLogInfo:: code:{codeString}\tinfo:{errorInfo}"); - -#if !UNITY_EDITOR + // Only for firebase GA - Analytics.LogEvent("dev_audit", parameters, - new Analytics.EventSetting() { EnableFirebaseAnalytics = true }); -#endif - + Analytics.TrackEvent("dev_audit", parameters, new Analytics.EventSetting() { EnableFirebaseAnalytics = true }); } - private static bool ParseWithJson(string json) + private bool ParseWithJson(string json) { Debug.Log($"{Tag} ------ ParseWithJson: json:\n{json}"); @@ -428,7 +438,7 @@ namespace Guru { string p = "\"msg\":\""; string m = json; - if (json.Contains(p)) m = json.Substring(json.IndexOf(p) + p.Length); + if (json.Contains(p)) m = json.Substring(json.IndexOf(p, StringComparison.Ordinal) + p.Length); info = $"JsonEX:{m}"; // Debug.Log($"{Tag} --- {info}"); Analytics.LogCrashlytics(json, false); @@ -438,22 +448,17 @@ namespace Guru return false; } - private static void ParseWithRaw(string raw) + /** + private void ParseWithRaw(string raw) { - int code = (int)AnalyticsCode.Unknown; - string info = raw; + var code = (int)AnalyticsCode.Unknown; + string info; //------- message send to unity ---------- Debug.Log($"{Tag} get callback errorInfo:\n{raw}"); - string patten = ""; - string patten2 = ""; - int idx = 0; - int idx2 = 0; - int len = 0; - - patten = "msg\":\""; + var patten = "msg\":\""; if (raw.Contains(patten)) { @@ -476,16 +481,16 @@ namespace Guru try { - idx = raw.IndexOf(patten, StringComparison.Ordinal) + patten.Length; + var idx = raw.IndexOf(patten, StringComparison.Ordinal) + patten.Length; string act = raw.Substring(idx, ActionName.Length); if (act == ActionName) { patten = "code\":"; - patten2 = ",\"msg"; - idx = raw.IndexOf(patten); - idx2 = raw.IndexOf(patten2); + var patten2 = ",\"msg"; + idx = raw.IndexOf(patten, StringComparison.Ordinal); + var idx2 = raw.IndexOf(patten2, StringComparison.Ordinal); - len = idx2 - (idx + patten.Length); + var len = idx2 - (idx + patten.Length); if (len > 0) { string c = raw.Substring(idx + patten.Length, len); @@ -524,12 +529,12 @@ namespace Guru { Analytics.LogCrashlytics(raw, false); Analytics.LogCrashlytics($"{Tag} --- format error:{raw}"); - OnLoggerErrorEvent(code, raw.Substring(raw.IndexOf("msg\":" ) + 5)); + OnLoggerErrorEvent(code, raw.Substring(raw.IndexOf("msg\":", StringComparison.Ordinal) + 5)); } } + **/ - - private static void ReportCodeInfo(int code, string info) + private void ReportCodeInfo(int code, string info) { var ac = (AnalyticsCode)code; Debug.Log($"{Tag} ------ Get Code And Info: code:{code}[{ac}] \tinfo:{info}"); @@ -585,7 +590,7 @@ namespace Guru public static void TestOnCallback(string msg) { - OnSDKCallback(msg); + Instance.OnSDKCallback(msg); } #endif diff --git a/Runtime/GuruAnalytics/Runtime/Script/IAnalyticsAgent.cs b/Runtime/GuruAnalytics/Runtime/Script/IAnalyticsAgent.cs index 3f3382e..e73e0ac 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/IAnalyticsAgent.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/IAnalyticsAgent.cs @@ -1,11 +1,13 @@ namespace Guru { + using System; + /// /// 自打点代理接口 /// public interface IAnalyticsAgent { - void Init(string appId, string deviceInfo, bool isDebug = false); + void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false); void SetScreen(string screenName); void SetAdId(string id); void SetUserProperty(string key, string value); diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs index 6364315..079be01 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs @@ -1,5 +1,7 @@ +using System.Threading.Tasks; + namespace Guru { using System; @@ -76,12 +78,16 @@ namespace Guru #region 接口实现 - public void Init(string appId, string deviceInfo, bool isDebug = false) + public async void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false) { _isDebug = isDebug; string bundleId = Application.identifier; // public static void init(String appId, String deviceInfo, String bundleId, boolean isDebug, boolean useWorker, boolean useCronet, String baseUrl) + + // TODO: 将来把 CallStatic 转为异步实现 CallStatic("init", appId, deviceInfo, bundleId, isDebug, UseWorker, UseCronet, BaseUrl); // 调用接口 + + onInitComplete?.Invoke(); } public void SetScreen(string screenName) diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentIOS.cs b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentIOS.cs index 26bbc94..9bcd582 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentIOS.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentIOS.cs @@ -1,7 +1,9 @@ -using System.Runtime.InteropServices; namespace Guru { + using System; + using System.Runtime.InteropServices; + public class AnalyticsAgentIOS: IAnalyticsAgent { @@ -55,13 +57,14 @@ namespace Guru } - public void Init(string appId, string deviceInfo, bool isDebug = false) + public void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false) { _isDebug = isDebug; #if UNITY_IOS unityInitAnalytics(appId, deviceInfo, isDebug); unityInitException(); // 初始化报错守护进程 #endif + onInitComplete?.Invoke(); } public void SetScreen(string screenName) diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentStub.cs b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentMock.cs similarity index 94% rename from Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentStub.cs rename to Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentMock.cs index 567a384..3c5e26b 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentStub.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentMock.cs @@ -1,9 +1,12 @@ -using System.Text; -using UnityEngine; + namespace Guru { - public class AnalyticsAgentStub: IAnalyticsAgent + using System.Text; + using UnityEngine; + using System; + + public class AnalyticsAgentMock: IAnalyticsAgent { public static readonly string TAG = "[EDT]"; @@ -24,7 +27,7 @@ namespace Guru } - public void Init(string appId, string deviceInfo, bool isDebug = false) + public void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false) { #if UNITY_EDITOR _isShowLog = true; @@ -32,6 +35,8 @@ namespace Guru _isDebug = isDebug; if(_isShowLog) Debug.Log($"{TAG} init with Debug: {isDebug} appId:{appId} deviceInfo:{deviceInfo}"); + + onInitComplete?.Invoke(); } diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentStub.cs.meta b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentMock.cs.meta similarity index 100% rename from Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentStub.cs.meta rename to Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentMock.cs.meta diff --git a/Runtime/GuruAnalytics/~Sample/CuruAnalyticsDemo.cs b/Runtime/GuruAnalytics/~Sample/GuruAnalyticsDemo.cs similarity index 79% rename from Runtime/GuruAnalytics/~Sample/CuruAnalyticsDemo.cs rename to Runtime/GuruAnalytics/~Sample/GuruAnalyticsDemo.cs index 0d4842c..ec471ff 100644 --- a/Runtime/GuruAnalytics/~Sample/CuruAnalyticsDemo.cs +++ b/Runtime/GuruAnalytics/~Sample/GuruAnalyticsDemo.cs @@ -5,7 +5,7 @@ using UnityEngine.UI; namespace Guru { - public class CuruAnalyticsDemo: MonoBehaviour + public class GuruAnalyticsDemo: MonoBehaviour { [SerializeField] private bool _isDebug = true; [SerializeField] private Button _btnInitSDK; @@ -54,17 +54,22 @@ namespace Guru private void OnClickInit() { Debug.Log($"---- [DEMO] Call Analytics init"); - GuruAnalytics.Init(AppID, DeviceInfo, _isDebug); + GuruAnalytics.Init(AppID, DeviceInfo, OnGuruAnalyticsInitComplete, _isDebug); } - + + private void OnGuruAnalyticsInitComplete() + { + + } + private void OnClickStatus() { Debug.Log($"---- [DEMO] Report Stats IDs: UID:{UID} DeviceID:{DeviceID} FirebaseID:{FirebaseID} AdID:{AdID} AdjustID:{AdjustID}"); - GuruAnalytics.SetUid(UID); - GuruAnalytics.SetDeviceId(DeviceID); - GuruAnalytics.SetFirebaseId(FirebaseID); - GuruAnalytics.SetAdId(AdID); - GuruAnalytics.SetAdjustId(AdjustID); + GuruAnalytics.Instance.SetUid(UID); + GuruAnalytics.Instance.SetDeviceId(DeviceID); + GuruAnalytics.Instance.SetFirebaseId(FirebaseID); + GuruAnalytics.Instance.SetAdId(AdID); + GuruAnalytics.Instance.SetAdjustId(AdjustID); } private void OnClickUserProperties() @@ -72,14 +77,14 @@ namespace Guru string item_category = "main"; int level = 7; Debug.Log($"---- [DEMO] Call SetUserProperty: item_category:{item_category} level:{level}"); - GuruAnalytics.SetUserProperty("item_category", item_category); - GuruAnalytics.SetUserProperty("level", level.ToString()); + GuruAnalytics.Instance.SetUserProperty("item_category", item_category); + GuruAnalytics.Instance.SetUserProperty("level", level.ToString()); } private void OnClickEvents() { Debug.Log($"---- [DEMO] Report Screen: {ScreenName}"); - GuruAnalytics.SetScreen(ScreenName); + GuruAnalytics.Instance.SetScreen(ScreenName); string eventName = "user_get_coin"; Dictionary data = new Dictionary() @@ -99,19 +104,19 @@ namespace Guru Debug.Log(s); Debug.Log($"---- [DEMO] Call LogEvent"); - GuruAnalytics.LogEvent(eventName, data); + GuruAnalytics.Instance.LogEvent(eventName, data); } private void OnClickEvents2() { string eventName = "user_data_loaded"; - GuruAnalytics.LogEvent(eventName); + GuruAnalytics.Instance.LogEvent(eventName); } private void OnClickReport() { - GuruAnalytics.ReportEventSuccessRate(); + GuruAnalytics.Instance.ReportEventSuccessRate(); } diff --git a/Runtime/GuruAnalytics/~Sample/CuruAnalyticsDemo.cs.meta b/Runtime/GuruAnalytics/~Sample/GuruAnalyticsDemo.cs.meta similarity index 100% rename from Runtime/GuruAnalytics/~Sample/CuruAnalyticsDemo.cs.meta rename to Runtime/GuruAnalytics/~Sample/GuruAnalyticsDemo.cs.meta diff --git a/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs b/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs index 177ef5e..14b70ea 100644 --- a/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs +++ b/Runtime/GuruConsent/Runtime/Script/Consent/GoogleDMAHelper.cs @@ -140,7 +140,7 @@ namespace Guru DmaResult = result; //----------- Guru Analytics report --------------- - Analytics.LogEvent("dma_gg", new Dictionary() + Analytics.TrackEvent("dma_gg", new Dictionary() { { "purpose", purposeStr }, { "result", result } diff --git a/Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs b/Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs index 7169ba6..3f6dcdf 100644 --- a/Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs +++ b/Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs @@ -1,3 +1,5 @@ +using System.Linq; + namespace Guru { using System; @@ -18,7 +20,7 @@ namespace Guru } } - protected static readonly string Tag = "[Ads]"; + protected static readonly string Tag = "[SDK][ADS]"; public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted; protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable; @@ -40,7 +42,10 @@ namespace Guru public static Action OnRewardLoaded; public static Action OnRewardFailed; public static Action OnRewardClosed; - + + private Dictionary _reviewCreativeIds = new Dictionary(10); // Creative ID 缓存: Cid : RCid + private Dictionary _impressionCache = new Dictionary(10); + protected AdsModel _model; protected AdsInitSpec _initSpec = null; @@ -89,10 +94,12 @@ namespace Guru MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent; MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerRevenuePaidEvent; MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent; + //--------------- Banner 回调 ----------------- MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerLoadedEvent; MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerFailedEvent; MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerClickedEvent; + MaxSdkCallbacks.Banner.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent; //--------------- IV 回调 ----------------- MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent; MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialFailedEvent; @@ -100,6 +107,7 @@ namespace Guru MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickEvent; MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayEvent; MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent; + MaxSdkCallbacks.Interstitial.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent; //--------------- RV 回调 ----------------- MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent; MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent; @@ -108,7 +116,12 @@ namespace Guru MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent; MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent; MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent; - + MaxSdkCallbacks.Rewarded.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent; + + //--------------- Creative 回调 ----------------- + + + //-------------- SDK 初始化 ------------------- MaxSdk.SetExtraParameter("enable_black_screen_fixes", "true"); // 修复黑屏 } @@ -174,7 +187,7 @@ namespace Guru #endregion - #region ILRD + #region 收益打点 private double TchAD001RevValue { @@ -188,25 +201,46 @@ namespace Guru set => _model.TchAD02RevValue = value; } - public void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) + /// + /// 上报广告收益 + /// + /// + /// + private void ReportAdsRevenue(AdImpressionData impressionData) + { + // #1 ad_impression + Analytics.ADImpression(impressionData); + + // #2 tch_001 + double revenue = impressionData.value; + CalcTaichi001Value(revenue); + CalcTaichi02Value(revenue); + + // #3 adjust_ad_revenue + AdjustService.TrackADRevenue(impressionData); + } + + + + + private void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) { if (adInfo == null) return; - + Debug.Log( $"{Tag} --- [Revenue] > [{adInfo.AdFormat}] --- adUnitId:{adUnitId}: UnitID:{adInfo.AdUnitIdentifier} Revenue:{adInfo.Revenue} CreativeId:{adInfo.CreativeIdentifier}"); + try { - Log.I( $"[ADRevenue] - adUnitId:{adUnitId}, Revenue:{adInfo?.Revenue : 0}"); - - // #1 ad_impression - OnAdImpression(adInfo); - - // #2 tch_001 - double revenue = adInfo.Revenue; - CalcTaichi001Value(revenue); - CalcTaichi02Value(revenue); - - // #3 adjust_ad_revenue - AdjustService.TrackADRevenue(adInfo); - + if (_reviewCreativeIds.TryGetValue(adInfo.CreativeIdentifier, out var reviewCreativeId)) + { + // 找到 RCid 的话则直接上报广告收益 + TryReportImpression(adInfo, reviewCreativeId); + } + else + { + // 找不到的话会缓存 adInfo, 等待获取 RCid + _impressionCache[adInfo.CreativeIdentifier] = CreateImpressionData(adInfo, "", Analytics.AdMAX); + } + } catch (Exception ex) { @@ -216,13 +250,30 @@ namespace Guru } /// - /// 广告ARO收益打点 + /// 构建 Impression 数据 /// /// + /// /// - private void OnAdImpression(MaxSdkBase.AdInfo adInfo, string platform = "") + /// + private AdImpressionData CreateImpressionData(MaxSdkBase.AdInfo adInfo, string reviewCreativeId = "", string platform = "") { - Analytics.ADImpression(adInfo, platform); + if (string.IsNullOrEmpty(platform)) platform = Analytics.AdMAX; + + var impression = new AdImpressionData() + { + value = adInfo.Revenue, + currency = Analytics.USD, + ad_platform = platform, + ad_format = adInfo.AdFormat, + ad_unit_name = adInfo.AdUnitIdentifier, + ad_source = adInfo.NetworkName, + ad_placement = adInfo.NetworkPlacement, + ad_creative_id = adInfo.CreativeIdentifier, + review_creative_id = reviewCreativeId + }; + + return impression; } @@ -386,6 +437,7 @@ namespace Guru // --- fixed by Yufei 2024-5-29 为 don't report bads_loaded any more. --- // Analytics.ADBadsLoaded(AdParams.Build(adUnitId, adInfo, // duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory)); + Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}"); OnBadsLoaded(); } @@ -509,6 +561,8 @@ namespace Guru duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory)); _interstitialRetryAttempt = 0; + Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}"); + OnInterstitialLoaded?.Invoke(); } @@ -660,6 +714,8 @@ namespace Guru Analytics.ADRadsLoaded(AdParams.Build(adUnitId, duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _iadsCategory)); _rewardRetryAttempt = 0; + + Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}"); OnRewardLoaded?.Invoke(); } @@ -782,5 +838,78 @@ namespace Guru } #endregion + + #region CreativeID + + /// + /// 获取 AdReviewCreativeId + /// + /// + /// + /// + private void OnAdReviewCreativeIdGeneratedEvent(string adUnitId, string reviewCreativeId, MaxSdkBase.AdInfo adInfo) + { + Debug.Log($"{Tag} --- ReviewCreativeId:{reviewCreativeId} adUnitId: {adUnitId} Type:{adInfo?.AdFormat ?? "NULL"} CreativeId: {adInfo?.CreativeIdentifier ?? "NULL"} Revenue:{adInfo.Revenue}"); + if (adInfo == null || string.IsNullOrEmpty(adInfo.CreativeIdentifier)) + { + Debug.LogError($"{Tag} --- Get ReviewCreativeId:{reviewCreativeId} but CreativeIdentifier is null"); + return; + } + + if (_reviewCreativeIds == null) _reviewCreativeIds = new Dictionary(10); + + + // 尝试直接上报广告收益 (可能存在异步上报的情况) + if (!TryReportImpression(adInfo, reviewCreativeId)) + { + _reviewCreativeIds[adInfo.CreativeIdentifier] = reviewCreativeId; // 如果上报未成功, 则缓存reviewCreativeId + } + } + + /// + /// 尝试上报数据 + /// + /// + /// + /// + private bool TryReportImpression(MaxSdk.AdInfo adInfo, string reviewCreativeId = "") + { + string creativeId = adInfo.CreativeIdentifier; + bool result = false; + List removeList = new List(); + + if (_impressionCache.TryGetValue(creativeId, out var impressionData)) + { + if(string.IsNullOrEmpty(impressionData.review_creative_id)) + impressionData.review_creative_id = reviewCreativeId; + + ReportAdsRevenue(impressionData); + removeList.Add(creativeId); + result = true; + } + + // 清理超过 3 秒未上报的数据 + foreach (var imp in _impressionCache.Values) + { + if (imp.GetPassedSecond() > 3.0) + { + ReportAdsRevenue(imp); + removeList.Add(imp.ad_creative_id); + } + } + + if (removeList.Count > 0) + { + foreach (var k in removeList) + { + _impressionCache.Remove(k); + _reviewCreativeIds.Remove(k); + } + } + + return result; + } + + #endregion } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs b/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs new file mode 100644 index 0000000..77b86b3 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs @@ -0,0 +1,40 @@ + + +namespace Guru +{ + using System; + + /// + /// AdImpression 对象 + /// + public class AdImpressionData + { + public double value; + public string currency = "USD"; + public string ad_platform = "MAX"; + public string ad_source; + public string ad_format; + public string ad_unit_name; + public string ad_placement; + public string ad_creative_id; + public string review_creative_id; + + public DateTime createTime; + + public AdImpressionData() + { + createTime = DateTime.UtcNow; + } + + /// + /// 获取自创建开始经过的秒数 + /// + /// + public double GetPassedSecond() + { + return (DateTime.UtcNow - createTime).TotalSeconds; + } + + + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs.meta b/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs.meta new file mode 100644 index 0000000..aa0e087 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/AdImpressionData.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1aca2a4507b94dfe9f88040125708edb +timeCreated: 1721883318 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.AdjustToken.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.AdjustToken.cs index b603242..ad29979 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.AdjustToken.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.AdjustToken.cs @@ -22,7 +22,7 @@ namespace Guru } } - private static AdjustEvent CreateAdjustEvent(string eventName) + internal static AdjustEvent CreateAdjustEvent(string eventName) { string tokenID = GetAdjustEventToken(eventName); if (string.IsNullOrEmpty(tokenID)) diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Ads.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Ads.cs index 776f663..7db0b7d 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Ads.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Ads.cs @@ -59,26 +59,26 @@ namespace Guru //---------------------- BANNER ------------------------- public static void ADBadsLoad(AdParams adParams) { - LogEvent(EventBadsLoad, BuildAdEventData(adParams)); + TrackEvent(EventBadsLoad, BuildAdEventData(adParams)); } public static void ADBadsLoaded(AdParams adParams) { - LogEvent(EventBadsLoaded, BuildAdEventData(adParams)); + TrackEvent(EventBadsLoaded, BuildAdEventData(adParams)); } public static void ADBadsFailed(AdParams adParams) { - LogEvent(EventBadsFailed, BuildAdEventData(adParams)); + TrackEvent(EventBadsFailed, BuildAdEventData(adParams)); } /// /// 广告点击 /// public static void ADBadsClick(AdParams adParams) { - LogEvent(EventBadsClick, BuildAdEventData(adParams)); + TrackEvent(EventBadsClick, BuildAdEventData(adParams)); } public static void ADBadsImp(AdParams adParams) { - LogEvent(EventBadsImp, BuildAdEventData(adParams)); + TrackEvent(EventBadsImp, BuildAdEventData(adParams)); } public static void ADBadsHide( int loadedTimes, int failTimes) @@ -88,7 +88,7 @@ namespace Guru ["loaded_times"] = loadedTimes, ["fail_times"] = failTimes }; - LogEvent(EventBadsHide, dict); + TrackEvent(EventBadsHide, dict); } //---------------------- INTERSTITIAL ------------------------- /// @@ -96,7 +96,7 @@ namespace Guru /// public static void ADIadsLoad(AdParams adParams) { - LogEvent(EventIadsLoad, BuildAdEventData(adParams)); + TrackEvent(EventIadsLoad, BuildAdEventData(adParams)); } /// @@ -104,7 +104,7 @@ namespace Guru /// public static void ADIadsLoaded(AdParams adParams) { - LogEvent(EventIadsLoaded, BuildAdEventData(adParams)); + TrackEvent(EventIadsLoaded, BuildAdEventData(adParams)); } /// @@ -112,7 +112,7 @@ namespace Guru /// public static void ADIadsFailed(AdParams adParams) { - LogEvent(EventIadsFailed, BuildAdEventData(adParams)); + TrackEvent(EventIadsFailed, BuildAdEventData(adParams)); } /// @@ -120,7 +120,7 @@ namespace Guru /// public static void ADIadsImp(AdParams adParams) { - LogEvent(EventIadsImp, BuildAdEventData(adParams)); + TrackEvent(EventIadsImp, BuildAdEventData(adParams)); } /// @@ -128,7 +128,7 @@ namespace Guru /// public static void ADIadsClick(AdParams adParams) { - LogEvent(EventIadsClick, BuildAdEventData(adParams)); + TrackEvent(EventIadsClick, BuildAdEventData(adParams)); } /// @@ -136,7 +136,7 @@ namespace Guru /// public static void ADIadsClose(AdParams adParams) { - LogEvent(EventIadsClose, BuildAdEventData(adParams)); + TrackEvent(EventIadsClose, BuildAdEventData(adParams)); } //---------------------- REWARDS ------------------------- @@ -145,28 +145,28 @@ namespace Guru /// public static void ADRadsLoad(AdParams adParams) { - LogEvent(EventRadsLoad, BuildAdEventData(adParams)); + TrackEvent(EventRadsLoad, BuildAdEventData(adParams)); } /// /// 广告拉取成功 /// public static void ADRadsLoaded(AdParams adParams) { - LogEvent(EventRadsLoaded, BuildAdEventData(adParams)); + TrackEvent(EventRadsLoaded, BuildAdEventData(adParams)); } /// /// 广告拉取失败 /// public static void ADRadsFailed(AdParams adParams) { - LogEvent(EventRadsFailed, BuildAdEventData(adParams)); + TrackEvent(EventRadsFailed, BuildAdEventData(adParams)); } /// /// 广告展示 /// public static void ADRadsImp(AdParams adParams) { - LogEvent(EventRadsImp, BuildAdEventData(adParams)); + TrackEvent(EventRadsImp, BuildAdEventData(adParams)); } /// /// 广告完成观看发奖励 @@ -174,7 +174,7 @@ namespace Guru public static void ADRadsRewarded(AdParams adParams) { var data = BuildAdEventData(adParams); - LogEvent(EventRadsRewarded, data); + TrackEvent(EventRadsRewarded, data); if (RadsRewardCount == 0) { @@ -195,7 +195,7 @@ namespace Guru /// public static void ADRadsFirstRewarded(Dictionary data) { - LogEvent(EventFirstRadsRewarded, data); + TrackEvent(EventFirstRadsRewarded, data); } /// @@ -203,7 +203,7 @@ namespace Guru /// public static void ADRadsClick(AdParams adParams) { - LogEvent(EventRadsClick, BuildAdEventData(adParams)); + TrackEvent(EventRadsClick, BuildAdEventData(adParams)); } /// @@ -211,7 +211,7 @@ namespace Guru /// public static void ADRadsClose(AdParams adParams) { - LogEvent(EventRadsClose, BuildAdEventData(adParams)); + TrackEvent(EventRadsClose, BuildAdEventData(adParams)); } #endregion diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs index 73bed60..f236857 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs @@ -16,6 +16,7 @@ namespace Guru public static readonly string USD = "USD"; // 广告平台 public static readonly string AdMAX = "MAX"; + public static readonly string AdIronSource = "IronSource"; //IAP打点事件 public static readonly string EventIAPFirst = "first_iap"; @@ -42,6 +43,7 @@ namespace Guru public static readonly string EventIadsFailed = "iads_failed"; public static readonly string EventIadsImp = "iads_imp"; public static readonly string EventIadsClick = "iads_clk"; + public static readonly string EventIadsPaid = "iads_paid"; public static readonly string EventIadsClose = "iads_close"; //激励视频广告打点事件 @@ -51,6 +53,7 @@ namespace Guru public static readonly string EventRadsImp = "rads_imp"; public static readonly string EventRadsRewarded = "rads_rewarded"; public static readonly string EventRadsClick = "rads_clk"; + public static readonly string EventRadsPaid = "rads_paid"; public static readonly string EventRadsClose = "rads_close"; public static readonly string EventFirstRadsRewarded = "first_rads_rewarded"; @@ -78,7 +81,10 @@ namespace Guru public static readonly string ParameterReplay = "replay"; // 游戏重玩 public static readonly string ParameterContinue = "continue"; // 游戏继续 public static readonly string ParameterAdUnitName = "ad_unit_name"; + public static readonly string ParameterAdPlacement = "ad_placement"; public static readonly string ParameterAdCreativeId = "ad_creative_id"; + public static readonly string ParameterReviewCreativeId = "review_creative_id"; + // 评价参数 public static readonly string EventRateImp = "rate_imp"; // 评价弹窗展示 diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs index d1f54a3..49e328c 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs @@ -26,9 +26,7 @@ namespace Guru public static bool IsDebug { get; set; } = false; - private static bool _hasInited = false; - - public static bool IsReady => _hasInited; + private static bool _isGuruAnalyticInitOnce = false; /// /// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用) @@ -36,7 +34,7 @@ namespace Guru public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false) { - if (_hasInited) return; + if (_isGuruAnalyticInitOnce) return; try { @@ -47,7 +45,7 @@ namespace Guru #endif string appId = IPMConfig.IPM_X_APP_ID; string deviceInfo = new DeviceInfoData().ToString(); - GuruAnalytics.Init(appId, deviceInfo, IsDebug, enableErrorLog); // 初始化(带Header) + GuruAnalytics.Init(appId, deviceInfo, OnGuruAnalyticsInitComplete, IsDebug, enableErrorLog); // 初始化(带Header) _hasGotFirebaseId = false; _hasGotAdId = false; @@ -59,7 +57,7 @@ namespace Guru UpdateAllValues(); - _hasInited = true; + _isGuruAnalyticInitOnce = true; } catch (Exception ex) { @@ -79,7 +77,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.IPM_UID)) { Debug.Log($"---[ANA] UID: {IPMConfig.IPM_UID}"); - GuruAnalytics.SetUid(IPMConfig.IPM_UID); + GuruAnalytics.Instance.SetUid(IPMConfig.IPM_UID); FirebaseAnalytics.SetUserProperty(PropertyUserID, IPMConfig.IPM_UID); _hasGotUid = true; } @@ -95,7 +93,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.IPM_DEVICE_ID)) { - GuruAnalytics.SetDeviceId(IPMConfig.IPM_DEVICE_ID); + GuruAnalytics.Instance.SetDeviceId(IPMConfig.IPM_DEVICE_ID); FirebaseAnalytics.SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); _hasGotDeviceId = true; } @@ -121,7 +119,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID)) { - GuruAnalytics.SetAdjustId(IPMConfig.ADJUST_ID); + GuruAnalytics.Instance.SetAdjustId(IPMConfig.ADJUST_ID); _hasGotAdjustId = true; } else @@ -152,7 +150,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ADID)) { - GuruAnalytics.SetAdId(IPMConfig.ADJUST_ADID); + GuruAnalytics.Instance.SetAdId(IPMConfig.ADJUST_ADID); _hasGotAdId = true; } @@ -171,7 +169,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.FIREBASE_ID)) { - GuruAnalytics.SetFirebaseId(IPMConfig.FIREBASE_ID); + GuruAnalytics.Instance.SetFirebaseId(IPMConfig.FIREBASE_ID); _hasGotFirebaseId = true; } else @@ -243,7 +241,7 @@ namespace Guru /// private static void SetAndroidId() { - GuruAnalytics.SetAndroidID(DeviceIDHelper.AndroidID); + GuruAnalytics.Instance.SetAndroidID(DeviceIDHelper.AndroidID); } #endif @@ -278,7 +276,7 @@ namespace Guru var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds; if (interval > _reportSuccessInterval) { - GuruAnalytics.ReportEventSuccessRate(); + GuruAnalytics.Instance.ReportEventSuccessRate(); _lastReportRateDate = DateTime.Now; } } @@ -296,7 +294,7 @@ namespace Guru { try { - GuruAnalytics.SetUserProperty(key, value); + GuruAnalytics.Instance.SetUserProperty(key, value); UpdateAllValues(); // 同步所有的ID } catch (Exception e) @@ -311,12 +309,12 @@ namespace Guru /// /// /// - private static void CustomLogEvent(string key, Dictionary data = null, int priority = -1) + private static void TrackEventGuru(string key, Dictionary data = null, int priority = -1) { try { if (data == null) data = new Dictionary(); - GuruAnalytics.LogEvent(key, data, priority); + GuruAnalytics.Instance.LogEvent(key, data, priority); UpdateAllValues(); // 同步所有的ID } catch (Exception e) @@ -339,7 +337,7 @@ namespace Guru if (Math.Abs(_tch02TargetValue - value) > 0.001d) { _tch02TargetValue = value; - GuruAnalytics.SetTch02Value(value); + GuruAnalytics.Instance.SetTch02Value(value); } } } diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Economic.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Economic.cs index c7ee71d..5c48dd5 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Economic.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Economic.cs @@ -103,7 +103,7 @@ namespace Guru if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景 if (extra != null) data.AddRange(extra, isOverride: true); - LogEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); + TrackEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); // FB 上报收入点 FBService.LogEvent(EventEarnVirtualCurrency, value, data); @@ -131,7 +131,7 @@ namespace Guru if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景 - LogEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); + TrackEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); // FB 上报消费点 FBService.LogEvent(EventSpendVirtualCurrency, value, data); diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.TemplateDefine.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.TemplateDefine.cs index b2d7204..1f4b2b0 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.TemplateDefine.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.TemplateDefine.cs @@ -27,7 +27,7 @@ namespace Guru }; if (extra != null) dict.AddRange(extra, isOverride:true); - LogEvent(EventLevelUp, dict); + TrackEvent(EventLevelUp, dict); } /// @@ -42,7 +42,7 @@ namespace Guru }; if (extra != null) dict.AddRange(extra, isOverride:true); - LogEvent(EventUnlockAchievement, dict); + TrackEvent(EventUnlockAchievement, dict); } /// @@ -53,7 +53,7 @@ namespace Guru [Obsolete("Obsolete method, please use instead. will be discard in next version.")] public static void LevelStart(int level) { - LogEvent(EventLevelStart, new Dictionary() + TrackEvent(EventLevelStart, new Dictionary() { { ParameterLevel, level }, { ParameterItemCategory, "main" }, @@ -91,7 +91,7 @@ namespace Guru dict.AddRange(extra, isOverride:true); } - LogEvent(EventLevelStart, dict); + TrackEvent(EventLevelStart, dict); } /// @@ -131,7 +131,7 @@ namespace Guru if(extra != null) dict.AddRange(extra, isOverride:true); - LogEvent(EventLevelEnd, dict); + TrackEvent(EventLevelEnd, dict); // if (isSuccess) // { @@ -160,7 +160,7 @@ namespace Guru ["level"] = level, }; } - LogEvent(eventName, extra, new EventSetting() + TrackEvent(eventName, extra, new EventSetting() { EnableFirebaseAnalytics = true, EnableFacebookAnalytics = true, @@ -188,7 +188,7 @@ namespace Guru if (extra != null) dict.AddRange(extra, isOverride: true); - LogEvent(EventLevelFirstEnd, dict); + TrackEvent(EventLevelFirstEnd, dict); } #endregion @@ -215,7 +215,7 @@ namespace Guru }; if(extra != null) dict.AddRange(extra, isOverride: true); - LogEvent(EventEarnVirtualCurrency, dict); + TrackEvent(EventEarnVirtualCurrency, dict); } /// @@ -237,7 +237,7 @@ namespace Guru }; if(extra != null) dict.AddRange(extra, isOverride: true); - LogEvent(EventSpendVirtualCurrency, dict); + TrackEvent(EventSpendVirtualCurrency, dict); } #endregion @@ -260,7 +260,7 @@ namespace Guru }; if(extra != null) dict.AddRange(extra, isOverride: true); - LogEvent("hit_points", dict); + TrackEvent("hit_points", dict); } #endregion @@ -387,7 +387,7 @@ namespace Guru //--------- Extra data for IAP receipt --------------- - LogEvent(evtName, data); + TrackEvent(evtName, data); } @@ -416,7 +416,6 @@ namespace Guru /// Google ARO买量点 /// /// 广告收入数据 - /// 广告平台 /// ///
  • /// value double eg:0.002 @@ -427,25 +426,25 @@ namespace Guru /// ad_unit_name string 广告位名称 /// ad_creative_id string 广告素材id ///
  • - public static void ADImpression(MaxSdkBase.AdInfo impressionData, string platform = "") + public static void ADImpression(AdImpressionData impressionData) { - if (string.IsNullOrEmpty(platform)) platform = AdMAX; - double revenue = impressionData.Revenue; - LogEvent(EventAdImpression, new Dictionary() + TrackEvent(EventAdImpression, new Dictionary() { - [ParameterValue] = revenue, - [ParameterCurrency] = USD, - [ParameterAdPlatform] = platform, - [ParameterAdSource] = impressionData.NetworkName, - [ParameterAdFormat] = impressionData.AdFormat, - [ParameterAdUnitName] = impressionData.AdUnitIdentifier, - [ParameterAdCreativeId] = impressionData.CreativeIdentifier, + [ParameterValue] = impressionData.value, + [ParameterCurrency] = impressionData.currency, + [ParameterAdPlatform] = impressionData.ad_platform, + [ParameterAdSource] = impressionData.ad_source, + [ParameterAdFormat] = impressionData.ad_format, + [ParameterAdUnitName] = impressionData.ad_unit_name, + [ParameterAdPlacement] = impressionData.ad_placement, + [ParameterAdCreativeId] = impressionData.ad_creative_id, + [ParameterReviewCreativeId] = impressionData.review_creative_id, }); } public static void TchAdAbnormalEvent(double value) { - LogEvent(EventTchAdRevAbnormal, new Dictionary() + TrackEvent(EventTchAdRevAbnormal, new Dictionary() { { ParameterAdPlatform, AdMAX }, { ParameterCurrency, USD }, @@ -470,7 +469,7 @@ namespace Guru }; if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); - LogEvent(EventIAPImp, dict); + TrackEvent(EventIAPImp, dict); } /// @@ -486,7 +485,7 @@ namespace Guru }; if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); - LogEvent(EventIAPClose, dict); + TrackEvent(EventIAPClose, dict); } /// @@ -512,7 +511,7 @@ namespace Guru }; if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); - LogEvent(EventIAPClick, dict); + TrackEvent(EventIAPClick, dict); } /// @@ -543,7 +542,7 @@ namespace Guru if(!string.IsNullOrEmpty(offerId)) dict["basePlan"] = offerId; - LogEvent(EventIAPReturnTrue, dict, new EventSetting() + TrackEvent(EventIAPReturnTrue, dict, new EventSetting() { EnableFirebaseAnalytics = true, EnableAdjustAnalytics = true, @@ -559,7 +558,7 @@ namespace Guru /// internal static void IAPRetFalse(string itemCategory, string productId, string failReason) { - LogEvent(EventIAPReturnFalse, new Dictionary() + TrackEvent(EventIAPReturnFalse, new Dictionary() { { ParameterItemCategory, itemCategory }, { ParameterItemName, productId }, @@ -576,7 +575,7 @@ namespace Guru /// 币种 public static void FirstIAP(string itemName, double value, string currency) { - LogEvent(EventIAPFirst, new Dictionary() + TrackEvent(EventIAPFirst, new Dictionary() { { ParameterItemName, itemName }, { ParameterValue, value }, @@ -597,7 +596,7 @@ namespace Guru if (productName.Contains(".")) productName = productName.Replace(".", "_"); string eventName = $"iap_{productName}"; - LogEvent(eventName, new Dictionary() + TrackEvent(eventName, new Dictionary() { { ParameterItemName, itemName }, { ParameterValue, value }, @@ -724,10 +723,8 @@ namespace Guru ["sandbox"] = isSandbox? "true": "false" }; - - // 上报Firebase + 自打点 - LogEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true }); + TrackEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true }); // 上报 Adjust 支付事件 LogAdjustRevenueEvent(eventName, value, productId, orderId, purchaseToken, receipt, dict); @@ -746,7 +743,7 @@ namespace Guru if (data == null) return; data["country"] = IPMConfig.IPM_COUNTRY_CODE; data["network"] = Application.internetReachability.ToString(); - LogEvent(EventDevAudit, data, new EventSetting() { EnableFirebaseAnalytics = true }); + TrackEvent(EventDevAudit, data, new EventSetting() { EnableFirebaseAnalytics = true }); } #endregion diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs index 02c9e94..3f87206 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs @@ -1,5 +1,7 @@ +using System.Threading; + namespace Guru { using System; @@ -40,18 +42,18 @@ namespace Guru private static EventSetting DefaultEventSetting => EventSetting.GetDefaultSetting(); - private static bool _isInited; //Analytics是否初始化完成 + private static bool _isInitOnce; //Analytics是否初始化完成 public static bool EnableDebugAnalytics; //允许Debug包上报打点 public static bool IsDebugMode => PlatformUtil.IsDebug(); private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized; - private static bool IsEnable + private static bool IsReady { get { //Analytics没有初始化不上报打点 - if (!_isInited) return false; + if (!_isInitOnce) return false; //Firebase服务没有初始化完成不上报打点 if (!IsFirebaseReady) return false; @@ -65,42 +67,62 @@ namespace Guru } } + + private static AdjustEventDriver _adjustEventDriver; + private static FBEventDriver _fbEventDriver; + private static FirebaseEventDriver _firebaseEventDriver; + private static GuruEventDriver _guruEventDriver; + + #region 初始化 public static void InitAnalytics() { - if (_isInited) return; - _isInited = true; + if (_isInitOnce) return; + _isInitOnce = true; - // -------- 初始化 Exception ---------- - CrashlyticsAgent.Install(); + _adjustEventDriver = new AdjustEventDriver(); + _fbEventDriver = new FBEventDriver(); + _firebaseEventDriver = new FirebaseEventDriver(); + _guruEventDriver = new GuruEventDriver(); // ------- 初始化自打点 ---------- InstallGuruAnalytics(IsDebug); - - FirebaseUtil.onInitComplete += OnFirebaseCompleted; } - private static void OnFirebaseCompleted(bool success) + + + public static void OnFirebaseInitCompleted() { - FirebaseUtil.onInitComplete -= OnFirebaseCompleted; - - Debug.Log($"[SDK] --- Analytics Init After FirebaseCompleted: {success}"); + Debug.Log($"[SDK] --- Analytics Init After FirebaseReady:{IsFirebaseReady}"); - ConsumeAllCachedEvent(); + // -------- 初始化 Crashlytics ---------- + CrashlyticsAgent.Init(); + FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); + FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0)); + SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google"); + SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); + // SetUserProperty(PropertyFirstOpenTime, FirstOpenTime); - if (success) - { - Crashlytics.IsCrashlyticsCollectionEnabled = true; - - FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); - FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0)); - SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google"); - SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); - // SetUserProperty(PropertyFirstOpenTime, FirstOpenTime); - - } + _firebaseEventDriver.TriggerFlush(); } + + + public static void OnFBInitComplete() + { + _fbEventDriver.TriggerFlush(); + } + + public static void OnAdjustInitComplete() + { + _adjustEventDriver.TriggerFlush(); + } + + private static void OnGuruAnalyticsInitComplete() + { + _guruEventDriver.TriggerFlush(); + } + #endregion @@ -109,9 +131,9 @@ namespace Guru public static void SetCurrentScreen(string screenName, string className) { Log.I(TAG,$"SetCurrentScreen -> screenName:{screenName}, className:{className}"); - GuruAnalytics.SetScreen(screenName); + GuruAnalytics.Instance.SetScreen(screenName); - if (!IsEnable) return; + if (!IsReady) return; FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventScreenView, new Parameter(FirebaseAnalytics.ParameterScreenClass, className), new Parameter(FirebaseAnalytics.ParameterScreenName, screenName) @@ -129,7 +151,7 @@ namespace Guru public static void SetUserIDProperty(string userID) { Log.I(TAG,$"SetUserIDProperty -> userID:{userID}"); - if (!IsEnable) return; + if (!IsReady) return; FirebaseAnalytics.SetUserId(userID); } @@ -141,7 +163,7 @@ namespace Guru { Log.I(TAG,$"SetUserProperty -> propertyName:{propertyName}, propertyValue:{propertyValue}"); - if (!IsEnable) + if (!IsReady) return; FirebaseAnalytics.SetUserProperty(propertyName, propertyValue); @@ -151,119 +173,62 @@ namespace Guru #endregion #region 打点上报 - - /// - /// 打点上报 - /// - /// - /// - internal static void LogEvent(string eventName, EventSetting eventSetting = null, int priority = -1) - { - - if (eventSetting == null) eventSetting = DefaultEventSetting; - - if(eventSetting.EnableGuruAnalytics) - CustomLogEvent(eventName, null, priority); // 自定义打点上报 - - CheckLogCache(eventName, null, eventSetting); // log缓存和消费 - - if (!IsEnable) return; - - Log.I(TAG, $" --- logEvent:{eventName}, eventSetting:{eventSetting}"); - - if (eventSetting.EnableFirebaseAnalytics) - { - FirebaseAnalytics.LogEvent(eventName); - } - - if (eventSetting.EnableAdjustAnalytics) - { - Adjust.trackEvent(CreateAdjustEvent(eventName)); - } - - if (eventSetting.EnableFacebookAnalytics) - { - FBService.LogEvent(eventName); - } - } + /// /// 打点上报 (带参数) /// /// - /// + /// /// /// - internal static void LogEvent(string eventName, Dictionary extras, EventSetting eventSetting = null, int priority = -1) + internal static void TrackEvent(string eventName, Dictionary data, + EventSetting eventSetting = null, int priority = -1) { + if (!_isInitOnce) + { + throw new Exception($"【SDK] Analytics did not initialized, Call first!"); + } + if (eventSetting == null) eventSetting = DefaultEventSetting; - - if(eventSetting.EnableGuruAnalytics) - CustomLogEvent(eventName, extras, priority); // 自定义打点上报 - - CheckLogCache(eventName, extras, eventSetting); // log缓存和消费 - - if (!IsEnable) return; - - if (extras == null) - { - LogEvent(eventName, eventSetting, priority); // 防空判定 - return; - } - string paramStr = string.Join(",", extras); - Log.I(TAG, $" --- logEvent:{eventName}, params:{paramStr}, eventSetting:{eventSetting}"); + var dataStr = ""; + if (data != null) dataStr = JsonParser.ToJson(data); + Debug.Log($"{TAG} --- [SDK] TrackEvent: {eventName} | priority: {priority} | data:{dataStr} | eventSetting: {eventSetting}"); - if (eventSetting.EnableFirebaseAnalytics) + try { - List parameters = new List(); - foreach (var kv in extras) + // 填充相关的追踪事件 + if (eventSetting.EnableGuruAnalytics) { - if(kv.Value is string strValue) - parameters.Add(new Parameter(kv.Key, strValue)); - else if (kv.Value is bool boolValue) - parameters.Add(new Parameter(kv.Key, boolValue ? "true" : "false")); - else if (kv.Value is int intValue) - parameters.Add(new Parameter(kv.Key, intValue)); - else if (kv.Value is long longValue) - parameters.Add(new Parameter(kv.Key, longValue)); - else if (kv.Value is float floatValue) - parameters.Add(new Parameter(kv.Key, floatValue)); - else if (kv.Value is double doubleValue) - parameters.Add(new Parameter(kv.Key, doubleValue)); - else if (kv.Value is decimal decimalValue) - parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue))); - else - parameters.Add(new Parameter(kv.Key, kv.Value.ToString())); + _guruEventDriver.Append(new TrackingEvent(eventName, data, eventSetting, priority)); } - - FirebaseAnalytics.LogEvent(eventName, parameters.ToArray()); - } - - Dictionary dict = new Dictionary(); - GuruSDKUtils.MergeDictionary(dict, extras); - - if (eventSetting.EnableAdjustAnalytics) - { - AdjustEvent adjustEvent = Analytics.CreateAdjustEvent(eventName); - if (adjustEvent != null) + if (eventSetting.EnableFirebaseAnalytics) { - if (dict.Count > 0) - { - foreach (var kv in dict) - { - adjustEvent.AddEventParameter(kv.Key, kv.Value.ToString()); - } - } - Adjust.trackEvent(adjustEvent); + _firebaseEventDriver.Append(new TrackingEvent(eventName, data, eventSetting, priority)); + } + if (eventSetting.EnableAdjustAnalytics) + { + _adjustEventDriver.Append(new TrackingEvent(eventName, data, eventSetting, priority)); + } + if (eventSetting.EnableFacebookAnalytics) + { + _fbEventDriver.Append(new TrackingEvent(eventName, data, eventSetting, priority)); } } - - if (eventSetting.EnableFacebookAnalytics) + catch (Exception ex) { - FBService.LogEvent(eventName, null, dict); + if (FirebaseUtil.IsReady) + { + Crashlytics.LogException(ex); + } + else + { + Debug.Log($"Catch Error: {ex}"); + } } } + /// /// 上报 Adjust 事件 @@ -316,14 +281,7 @@ namespace Guru /// public static void Track(string key, Dictionary data = null, EventSetting setting = null, int priority = -1) { - if (null != data) - { - LogEvent(key, data, setting, priority); - } - else - { - LogEvent(key, setting, priority); - } + TrackEvent(key, data, setting, priority); } @@ -334,7 +292,7 @@ namespace Guru /// public static void LogCrashlytics(string msg, bool isException = true) { - if (!_isInited) return; + if (!_isInitOnce) return; if (isException) { LogCrashlytics(new Exception(msg)); @@ -348,7 +306,7 @@ namespace Guru public static void LogCrashlytics(Exception exp) { - if (!_isInited) return; + if (!_isInitOnce) return; CrashlyticsAgent.LogException(exp); } @@ -356,95 +314,58 @@ namespace Guru #region 打点缓存 - private static Queue _savedLogs; + private static Queue _savedLogs; - internal static Queue SavedLogs + internal static Queue SavedLogs { get { - if (_savedLogs == null) _savedLogs = new Queue(20); + if (_savedLogs == null) _savedLogs = new Queue(20); return _savedLogs; } } - - private static void CheckLogCache(string key, Dictionary data = null, EventSetting setting = null, int priority = -1) - { - try - { - if (!IsEnable) - { - // 保存打点 - if (data == null) data = new Dictionary(); - data["log_stamp"] = TimeUtil.GetCurrentTimeStamp().ToString(); - if (setting == null) setting = DefaultEventSetting; - setting.EnableGuruAnalytics = false; - - SavedLogs.Enqueue(new SavedLog(key, data, setting, priority)); - Log.W(TAG,$" --- LogEvent [{key}] has been cached before SDK init!"); - } - else - { - ConsumeAllCachedEvent(); - } - } - catch (Exception ex) - { - if (FirebaseUtil.IsReady) - { - Crashlytics.LogException(ex); - } - else - { - Debug.Log($"Catch Error: {ex}"); - } - } - } - - /// - /// 消耗所有的缓存日志 - /// - private static void ConsumeAllCachedEvent() - { - // 消耗打点 - int len = SavedLogs.Count; - if (len <= 0) return; - while (SavedLogs.Count > 0) - { - var log = SavedLogs.Dequeue(); - LogEvent(log.key, log.data, log.setting, log.priority); - } - } - - #endregion + + } - internal class SavedLog + public class TrackingEvent { - public string key; + public string eventName; public int priority; public Dictionary data; public Analytics.EventSetting setting; - public SavedLog() + public TrackingEvent() { } /// /// 保存打点信息 /// - /// + /// /// /// /// - public SavedLog(string _key, Dictionary _data = null, Analytics.EventSetting _setting = null, int _priority = -1) + public TrackingEvent(string eventName, Dictionary data = null, Analytics.EventSetting setting = null, int priority = -1) { - key = _key; - data = _data; - setting = _setting; - priority = _priority; + this.eventName = eventName; + this.data = data; + this.setting = setting; + this.priority = priority; + } + + + public void Flush() + { + Analytics.TrackEvent(eventName, data, setting, priority); + } + + public override string ToString() + { + return $"eventName: {eventName}, data: {data}, setting: {setting}, priority: {priority}"; } } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events.meta b/Runtime/GuruCore/Runtime/Analytics/Events.meta new file mode 100644 index 0000000..8df26c7 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d13f245a2ea24c8ebdb957ad4ba79ca4 +timeCreated: 1721908201 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs new file mode 100644 index 0000000..6bf9786 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs @@ -0,0 +1,46 @@ +namespace Guru +{ + public abstract class AbstractEventDriver: IEventDriver + { + private GuruEventBuffer _buffer = new GuruEventBuffer(); + + // Firebase 是否可用 + private bool _isDriverReady = false; + + public void TriggerFlush() + { + _isDriverReady = true; + FlushAll(); + } + public void Append(TrackingEvent trackingEvent) + { + if (_isDriverReady) + { + FlushTrackingEvent(trackingEvent); + } + else + { + _buffer.Push(trackingEvent); + } + + + } + + private void FlushAll() + { + while(_buffer.Pop(out var trackingEvent)) + { + FlushTrackingEvent(trackingEvent); + } + } + + + /// + /// 发送事件 + /// + /// + protected abstract void FlushTrackingEvent(TrackingEvent trackEvent); + + + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs.meta new file mode 100644 index 0000000..6113ae3 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fe02e66845f64aafa94654814822930a +timeCreated: 1721916181 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs new file mode 100644 index 0000000..8f93057 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs @@ -0,0 +1,35 @@ + + +using System.Collections.Generic; + +namespace Guru +{ + using com.adjust.sdk; + public class AdjustEventDriver : AbstractEventDriver + { + /// + /// 发送事件 + /// + /// + protected override void FlushTrackingEvent(TrackingEvent trackingEvent) + { + var eventName = trackingEvent.eventName; + var data = trackingEvent.data; + AdjustEvent adjustEvent = Analytics.CreateAdjustEvent(eventName); + if (adjustEvent != null) + { + UnityEngine.Debug.Log($"[SDK] --- Adjust logEvent: {trackingEvent}"); + + if (data != null && data.Count > 0) + { + foreach (var kv in data) + { + adjustEvent.AddEventParameter(kv.Key, ((object)kv.Value).ToString()); + } + } + Adjust.trackEvent(adjustEvent); + } + } + + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs.meta new file mode 100644 index 0000000..1621272 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f064544085c8401d988b9eae91bd79b1 +timeCreated: 1721910840 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs new file mode 100644 index 0000000..0467f41 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +namespace Guru +{ + public class FBEventDriver: AbstractEventDriver + { + /// + /// 发送事件 + /// + /// + protected override void FlushTrackingEvent(TrackingEvent trackingEvent) + { + var eventName = trackingEvent.eventName; + var data = trackingEvent.data; + Debug.Log($"[SDK] --- FB logEvent: {trackingEvent}"); + + FBService.LogEvent(eventName, null, data); + } + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs.meta new file mode 100644 index 0000000..f520aee --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 305a62f1c0fe4a16b7c9101264be523b +timeCreated: 1721910530 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs new file mode 100644 index 0000000..c7bb446 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs @@ -0,0 +1,55 @@ + + + +namespace Guru +{ + using Firebase.Analytics; + using System.Collections.Generic; + using UnityEngine; + + /// + /// Firebase 专用 + /// + internal class FirebaseEventDriver : AbstractEventDriver + { + + protected override void FlushTrackingEvent(TrackingEvent trackingEvent) + { + var eventName = trackingEvent.eventName; + var data = trackingEvent.data; + + Debug.Log($"[SDK] --- Firebase logEvent: {trackingEvent}"); + + if (data != null) + { + List parameters = new List(); + foreach (var kv in data) + { + if(kv.Value is string strValue) + parameters.Add(new Parameter(kv.Key, strValue)); + else if (kv.Value is bool boolValue) + parameters.Add(new Parameter(kv.Key, boolValue ? "true" : "false")); + else if (kv.Value is int intValue) + parameters.Add(new Parameter(kv.Key, intValue)); + else if (kv.Value is long longValue) + parameters.Add(new Parameter(kv.Key, longValue)); + else if (kv.Value is float floatValue) + parameters.Add(new Parameter(kv.Key, floatValue)); + else if (kv.Value is double doubleValue) + parameters.Add(new Parameter(kv.Key, doubleValue)); + else if (kv.Value is decimal decimalValue) + parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue))); + else + parameters.Add(new Parameter(kv.Key, kv.Value.ToString())); + } + + FirebaseAnalytics.LogEvent(eventName, parameters.ToArray()); + } + else + { + FirebaseAnalytics.LogEvent(eventName); + } + } + + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs.meta new file mode 100644 index 0000000..894f41d --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7a4c2262ab86431ba6d5961e7453d60f +timeCreated: 1721905429 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs new file mode 100644 index 0000000..b871ab6 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs @@ -0,0 +1,55 @@ + + +using System.Collections.Generic; + +namespace Guru +{ + using System.Collections.Concurrent; + public class GuruEventBuffer + { + private ConcurrentQueue _eventQueue; + + public int Count => _eventQueue?.Count ?? -1; + + + /// + /// 构造函数 + /// + public GuruEventBuffer() + { + _eventQueue = new ConcurrentQueue(); + } + + /// + /// 入栈 + /// + /// + public void Push(TrackingEvent trackEvent) + { + _eventQueue.Enqueue(trackEvent); + } + + /// + /// 出栈 + /// + /// + /// + public bool Pop(out TrackingEvent trackingEvent) + { + return _eventQueue.TryDequeue(out trackingEvent); + } + } + + + public interface IEventDriver + { + void TriggerFlush(); + void Append(TrackingEvent trackingEvent); + } + + + + + + +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs.meta new file mode 100644 index 0000000..9f13b0e --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventBuffer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f6dd65ae849944c59be2182eb64db34a +timeCreated: 1721899117 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs new file mode 100644 index 0000000..9eec77a --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs @@ -0,0 +1,11 @@ +namespace Guru +{ + public class GuruEventDriver: AbstractEventDriver + { + protected override void FlushTrackingEvent(TrackingEvent trackingEvent) + { + GuruAnalytics.Instance.LogEvent(trackingEvent.eventName, trackingEvent.data, trackingEvent.priority); + } + + } +} \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs.meta b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs.meta new file mode 100644 index 0000000..e3b1637 --- /dev/null +++ b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d3fee5c262ca43c387ce76d52fb149c8 +timeCreated: 1721908696 \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Data/StandardProperties.cs b/Runtime/GuruCore/Runtime/Data/StandardProperties.cs index e757754..787d04b 100644 --- a/Runtime/GuruCore/Runtime/Data/StandardProperties.cs +++ b/Runtime/GuruCore/Runtime/Data/StandardProperties.cs @@ -58,7 +58,7 @@ namespace Guru if (!string.IsNullOrEmpty(value)) { PlayerPrefs.SetString(nameof(FirebaseId), value); - GuruAnalytics.SetFirebaseId(value); + GuruAnalytics.Instance.SetFirebaseId(value); } } } @@ -73,7 +73,7 @@ namespace Guru if (!string.IsNullOrEmpty(value)) { PlayerPrefs.SetString(nameof(AdjustId), value); - GuruAnalytics.SetAdjustId(value); + GuruAnalytics.Instance.SetAdjustId(value); } } } @@ -88,7 +88,7 @@ namespace Guru if (!string.IsNullOrEmpty(value)) { PlayerPrefs.SetString(nameof(GoogleAdId), value); - GuruAnalytics.SetAdId(value); + GuruAnalytics.Instance.SetAdId(value); } } } diff --git a/Runtime/GuruCore/Runtime/FB/FBService.cs b/Runtime/GuruCore/Runtime/FB/FBService.cs index 47d20f6..74b4aba 100644 --- a/Runtime/GuruCore/Runtime/FB/FBService.cs +++ b/Runtime/GuruCore/Runtime/FB/FBService.cs @@ -1,44 +1,38 @@ -using System.Collections.Generic; -using Facebook.Unity; -using UnityEngine; - namespace Guru { + using System; + using System.Collections.Generic; + using Facebook.Unity; + using UnityEngine; + [MonoSingleton(EMonoSingletonType.CreateOnNewGameObject, false)] public class FBService : MonoSingleton { - public static readonly string LOG_TAG = "FB"; + private const string Tag = "[FB]"; + private bool _isInitOnce; + private Action _onInitComplete; - public void StartService() + public void StartService(Action onInitComplete) { - if (!FB.IsInitialized) - { - // Initialize the Facebook SDK - FB.Init(InitCallback, OnHideUnity); - } - else - { - // Already initialized, signal an app activation App Event - FB.ActivateApp(); - } + if(_isInitOnce) return; + _isInitOnce = true; + + _onInitComplete = onInitComplete; + // Initialize the Facebook SDK + FB.Init(InitCallback, OnHideUnity); } private void InitCallback() { - if (FB.IsInitialized) - { - // Signal an app activation App Event - FB.ActivateApp(); - FB.Mobile.SetAdvertiserIDCollectionEnabled(true); - FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报 + + // Signal an app activation App Event + FB.ActivateApp(); + FB.Mobile.SetAdvertiserIDCollectionEnabled(true); + FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报 #if UNITY_IOS - FB.Mobile.SetAdvertiserTrackingEnabled(true); + FB.Mobile.SetAdvertiserTrackingEnabled(true); #endif - } - else - { - Log.E(LOG_TAG, "Failed to Initialize the Facebook SDK"); - } + _onInitComplete?.Invoke(); } private void OnHideUnity(bool isGameShown) @@ -81,13 +75,13 @@ namespace Guru } - private static bool IsAvailable + public static bool IsAvailable { get { if (!FB.IsInitialized) { - Debug.LogError("[FB] FB is not initialized, please call first."); + Debug.LogError($"{Tag} FB is not initialized, please call first."); return false; } return true; diff --git a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs index 4ecbc7b..5e76bd8 100644 --- a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs +++ b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs @@ -24,7 +24,7 @@ namespace Guru public static void InitFirebase(Action callback) { _isReady = false; - Analytics.InitAnalytics(); // 打点提前初始化 + // Analytics.InitAnalytics(); // 打点提前初始化 // Loom.StartUp(); // 确保主线程开启 @@ -137,6 +137,8 @@ namespace Guru IPMConfig.ADJUST_ID = adjustId; } ReportAdjustId(adjustId); + + Analytics.OnAdjustInitComplete(); } diff --git a/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs b/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs index ef0017b..94ce176 100644 --- a/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs +++ b/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs @@ -9,9 +9,8 @@ namespace Guru public static class CrashlyticsAgent { private static bool _initOnce; - private static bool _isReady; + private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized; - private static Queue _expCache; private static bool _hasSetUser = false; /// @@ -32,45 +31,18 @@ namespace Guru LogType.Assert, }; - public static void Install() + public static void Init() { if (_initOnce) return; _initOnce = true; - _expCache = new Queue(20); Application.logMessageReceived -= OnReceivedMessage; Application.logMessageReceived += OnReceivedMessage; - // Application.logMessageReceivedThreaded -= OnReceivedMessage; - // Application.logMessageReceivedThreaded += OnReceivedMessage; - - if (FirebaseUtil.IsReady) - { - OnFirebaseComplete(true); - return; - } - - FirebaseUtil.onInitComplete -= OnFirebaseComplete; - FirebaseUtil.onInitComplete += OnFirebaseComplete; + Crashlytics.IsCrashlyticsCollectionEnabled = true; } - private static void OnFirebaseComplete(bool success) - { - FirebaseUtil.onInitComplete -= OnFirebaseComplete; - if (success) - { - _isReady = true; - Crashlytics.IsCrashlyticsCollectionEnabled = true; - if (_expCache != null && _expCache.Count > 0) - { - while (_expCache.Count > 0) - { - LogException(_expCache.Dequeue()); - } - _expCache.Clear(); - } - } - } + private static string ToLogTypeString(LogType type) { @@ -101,14 +73,8 @@ namespace Guru public static void LogException(Exception ex) { - if (!_isReady) - { - Install(); - _expCache.Enqueue(ex); - return; - } + if (!IsFirebaseReady) return; Crashlytics.LogException(ex); - // CheckSetUser(); } public static void LogException(string msg) @@ -118,15 +84,14 @@ namespace Guru public static void Log(string msg) { - if (!_isReady) return; + if (!IsFirebaseReady) return; Crashlytics.Log(msg); - // CheckSetUser(); } public static void SetCustomKey(string key, string value) { - if (!_isReady) return; + if (!IsFirebaseReady) return; Crashlytics.SetCustomKey(key, value); } diff --git a/Runtime/GuruCore/Runtime/Settings/GuruSettings.cs b/Runtime/GuruCore/Runtime/Settings/GuruSettings.cs index bf10e46..73d8c7c 100644 --- a/Runtime/GuruCore/Runtime/Settings/GuruSettings.cs +++ b/Runtime/GuruCore/Runtime/Settings/GuruSettings.cs @@ -140,9 +140,13 @@ namespace Guru public class AnalyticsSetting { [SerializeField] private int levelEndSuccessNum = 50; + [Obsolete("Will not use in next version", false)] [SerializeField] private bool enalbeFirebaseAnalytics = true; + [Obsolete("Will not use in next version", false)] [SerializeField] private bool enalbeFacebookAnalytics = true; + [Obsolete("Will not use in next version", false)] [SerializeField] private bool enalbeAdjustAnalytics = true; + [SerializeField] internal List adjustEventList; public int LevelEndSuccessNum => levelEndSuccessNum; diff --git a/Runtime/GuruIAP/Runtime/Code/IAPServiceBase.cs b/Runtime/GuruIAP/Runtime/Code/IAPServiceBase.cs index 37106dd..d2c412a 100644 --- a/Runtime/GuruIAP/Runtime/Code/IAPServiceBase.cs +++ b/Runtime/GuruIAP/Runtime/Code/IAPServiceBase.cs @@ -1132,7 +1132,7 @@ namespace Guru private void ReportGoogleOrderLost(GoogleOrderData data) { - Analytics.LogEvent("google_order_lost", new Dictionary() + Analytics.TrackEvent("google_order_lost", new Dictionary() { ["data"] = data.ToString(), }, new Analytics.EventSetting() @@ -1144,7 +1144,7 @@ namespace Guru private void ReportAppleOrderLost(AppleOrderData data) { - Analytics.LogEvent("apple_order_lost", new Dictionary() + Analytics.TrackEvent("apple_order_lost", new Dictionary() { ["data"] = data.ToString(), }, new Analytics.EventSetting()