[1020027] [中台] [打点] 规范 iap_ret_true 打点参数 --story=1020027 --user=yufei.hu

Signed-off-by: huyufei <yufei.hu@castbox.fm>
deeplink
胡宇飞 2024-05-10 21:31:14 +08:00
parent 4fd0f8fec4
commit 4c899f9aeb
8 changed files with 194 additions and 93 deletions

View File

@ -76,9 +76,6 @@ namespace Guru
public static readonly string ParameterAdUnitName = "ad_unit_name";
public static readonly string ParameterAdCreativeId = "ad_creative_id";
// 评价参数
public static readonly string EventRateImp = "rate_imp"; // 评价弹窗展示
public static readonly string EventRateNow = "rate_now"; // 点击评分引导弹窗中的评分

View File

@ -397,15 +397,15 @@ namespace Guru
var data = new Dictionary<string, dynamic>()
{
{ ParameterAdPlatform, platform },
{ ParameterCurrency, USD },
{ ParameterValue, value },
{ ParameterCurrency, USD },
};
//--------- Extra data for IAP receipt ---------------
if(!string.IsNullOrEmpty(orderType)) data.Add("order_type", orderType);
if(!string.IsNullOrEmpty(productId)) data.Add("product_id", productId);
if(!string.IsNullOrEmpty(orderId)) data.Add("order_id", orderId);
if(!string.IsNullOrEmpty(timestamp)) data.Add("payed_date", timestamp);
if(!string.IsNullOrEmpty(orderType)) data["order_type"] = orderType;
if(!string.IsNullOrEmpty(productId)) data["product_id"] = productId;
if(!string.IsNullOrEmpty(orderId)) data["order_id"] = orderId;
if(!string.IsNullOrEmpty(timestamp)) data["trans_ts"] = timestamp;
//--------- Extra data for IAP receipt ---------------
LogEvent(evtName, data);
@ -527,21 +527,23 @@ namespace Guru
/// <summary>
/// "app 内弹出的付费引导IAP付费或试用成功打点"
/// </summary>
/// <param name="itemCategory">界面跳转的来源</param>
/// <param name="productID">product id,多个产品用逗号分隔第一个商品id放主推商品id</param>
/// <param name="scene">界面跳转的来源</param>
/// <param name="productId">product id,多个产品用逗号分隔第一个商品id放主推商品id</param>
/// <param name="value">产品的价格</param>
/// <param name="currency">用户的付费币种</param>
/// <param name="orderId">订单 ID</param>
/// <param name="type">付费类型订阅/产品subscription/product</param>
/// <param name="isfree">是否为试用1试用0付费</param>
public static void IAPRetTrue(string itemCategory, string productID, double value, string currency, string type, bool isfree)
public static void IAPRetTrue(string scene, string productId, double value, string currency, string orderId, string type, bool isfree)
{
LogEvent(EventIAPReturnTrue, new Dictionary<string, object>()
{
{ ParameterItemCategory, itemCategory },
{ ParameterItemName, productID },
{ ParameterItemCategory, scene },
{ ParameterItemName, productId },
{ ParameterValue, value },
{ ParameterCurrency, currency },
{ "type", type},
{ "order_id", orderId },
{ "type", type },
{ "isfree", isfree ? 1 : 0 },
});
}
@ -596,7 +598,53 @@ namespace Guru
{ ParameterCurrency, currency },
});
}
/// <summary>
/// 支付成功后统一上报所有点位数据
/// </summary>
/// <param name="productId"></param>
/// <param name="usdPrice"></param>
/// <param name="userCurrency"></param>
/// <param name="payPrice"></param>
/// <param name="orderId"></param>
/// <param name="orderType"></param>
/// <param name="orderDate"></param>
/// <param name="scene"></param>
/// <param name="isFree"></param>
public static void ReportIAPSuccessEvent(double usdPrice, string productId, BaseOrderData orderData)
{
string userCurrency = orderData.userCurrency;
double payPrice = orderData.payPrice;
string orderType = orderData.OrderType();
string orderType2 = orderData.OrderTypeII();
string orderId = orderData.orderId;
string orderDate = orderData.payedDate;
string scene = orderData.scene;
bool isFree = orderData.isFree;
// TCH 001
Tch001IAPRev(usdPrice, productId, orderId, orderType, orderDate);
// TCH 020
Tch02IAPRev(usdPrice);
// Adjust Track IAP Purchase
AdjustService.TrackIAPPurchase(usdPrice, productId); // 上报 IAP 支付事件
if (orderData.orderType == 1)
{
// sub_pruchase
SubPurchase(usdPrice, productId, orderId, orderDate);
}
else
{
// iap_purchase
IAPPurchase(usdPrice, productId, orderId, orderDate);
}
// IAP Ret true
IAPRetTrue(scene, productId, payPrice, userCurrency, orderType2, orderType, isFree);
}
#endregion
#region IAP_PURCHASE
@ -606,18 +654,20 @@ namespace Guru
/// </summary>
/// <param name="value"></param>
/// <param name="productId"></param>
public static void IAPPurchase(double value, string productId)
/// <param name="orderId"></param>
/// <param name="orderDate"></param>
public static void IAPPurchase(double value, string productId, string orderId, string orderDate)
{
IAPPurchaseReport(EventIAPPurchase, value, productId);
IAPPurchaseReport(EventIAPPurchase, value, productId, orderId, "IAP", orderDate);
}
public static void SubPurchase(double value, string productId)
public static void SubPurchase(double value, string productId, string orderId, string orderDate)
{
IAPPurchaseReport(EventSubPurchase, value, productId);
IAPPurchaseReport(EventSubPurchase, value, productId, orderId, "SUB", orderDate);
}
private static void IAPPurchaseReport(string eventName, double value, string productId)
private static void IAPPurchaseReport(string eventName, double value, string productId, string orderId, string orderType, string orderDate)
{
LogEvent(eventName, new Dictionary<string, dynamic>()
{
@ -625,8 +675,15 @@ namespace Guru
[ParameterPlatform] = IAPPlatform,
[ParameterCurrency] = USD,
[ParameterValue] = value,
[ParameterProductId] = productId,
}, new EventSetting() { EnableFirebaseAnalytics = true });
["product_id"] = productId,
["order_id"] = orderId,
["order_type"] = orderType,
["trans_ts"] = orderDate
}, new EventSetting()
{
EnableFirebaseAnalytics = true,
EnableAdjustAnalytics = true,
});
}
#endregion

View File

@ -21,7 +21,9 @@ namespace Guru
public string country; // 用户商店的国家2字大写代码
public AppleOrderData(int orderType, string productId, string receipt, string orderId,
string date, int level, string offerId = "", string basePlanId = "") : base(orderType, productId, orderId, date, level, offerId, basePlanId)
string date, int level, string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
:base(orderType, productId, orderId, date, level, userCurrency, payPrice, scene, isFree, offerId, basePlanId)
{
this.receipt = receipt;
bundleId = GuruSettings.Instance.GameIdentifier;

View File

@ -12,29 +12,33 @@ namespace Guru
public class BaseOrderData
{
[JsonIgnore]
public string guid; // 唯一标识
public string productId; // 商品ID 当orderType=0时传递该参数
[JsonIgnore]
public string guid; // 唯一标识
public int level; // 关卡 ID
public int orderType; // 订单类型可选值0:IAP 订单 1:SUB 订阅订单
public Dictionary<string, object> userInfo; // 当前用户信息。目前包含: level: 用户属性中的"b_level"的值
public EventConfig eventConfig; // 事件打点所需信息
//---- Offer Data -------
[JsonIgnore]
public string userCurrency; // 用户商店货币
public double payPrice; // 用户支付的费用
public string scene; // 用户支付的场景
public bool isFree; // 是否是试用道具
// ---- Offer Data -------
public string orderId; // 订单的 OrderID
[JsonIgnore]
public string payedDate; // 支付时间 (13位时间戳)
public int orderType; // 订单类型可选值0:IAP 订单 1:SUB 订阅订单
public string basePlanId; // 订阅商品的planId
public string offerId; // 订阅商品的offerId
public Dictionary<string, object> userInfo; // 当前用户信息。目前包含: level: 用户属性中的"b_level"的值
public EventConfig eventConfig; // 事件打点所需信息
public BaseOrderData(int orderType, string productId, string orderId,
string payedDate, int level, string offerId = "", string basePlanId = "")
string payedDate, int level, string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
{
guid = GetGuid();
this.userCurrency = userCurrency;
this.payPrice = payPrice;
this.scene = scene;
this.isFree = isFree;
this.orderType = orderType;
this.productId = productId;
this.orderId = orderId;
@ -48,7 +52,8 @@ namespace Guru
protected string GetGuid() => Guid.NewGuid().ToString();
public string OrderType() => orderType == 0 ? "IAP" : "SUB";
public string OrderType() => orderType == 1 ? "SUB": "IAP";
public string OrderTypeII() => orderType == 1 ? "subscription" : "product";
public override string ToString()
{

View File

@ -18,8 +18,11 @@ namespace Guru
public string packageName; //应用包名
public string token; // 应用商店里面的购买token
public GoogleOrderData(int orderType, string productId, string token, string orderId,
string date, int level, string offerId = "", string basePlanId = "") : base(orderType, productId, orderId, date, level, offerId, basePlanId)
public GoogleOrderData(int orderType, string productId, string token,
string orderId, string date, int level,
string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
:base(orderType, productId, orderId, date, level, userCurrency, payPrice, scene, isFree, offerId, basePlanId)
{
_productId = productId;
this.packageName = GuruSettings.Instance.GameIdentifier;

View File

@ -10,33 +10,11 @@ namespace Guru
public class AppleOrderRequest : RequestBase
{
public int orderType;
public string productId;
public string receipt;
public AppleOrderData orderData;
public AppleOrderRequest(){}
public static AppleOrderRequest Build(int orderType, string productId, string receipt, string orderId, string date, int level)
{
var request = new AppleOrderRequest()
{
orderType = orderType,
productId = productId,
receipt = receipt,
orderData = new AppleOrderData(orderType, productId, receipt, orderId, date, level),
};
return request;
}
public static AppleOrderRequest Build(AppleOrderData orderData)
{
return Build(orderData.orderType,
orderData.productId,
orderData.receipt,
orderData.orderId,
orderData.payedDate,
orderData.level);
}
protected override string RequestURL => IPMConfig.IPM_URL + "order/api/v1/orders/ios";
protected override UnityWebRequest CreateRequest()
@ -59,13 +37,16 @@ namespace Guru
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
if (responseData != null && responseData.data != null)
{
double usdPrice = responseData.data.usdPrice;
double usdPrice = responseData.data.usdPrice;
string productId = orderData.productId;
Analytics.Tch001IAPRev(usdPrice, productId, orderData.orderId, orderData.OrderType(), orderData.payedDate);
Analytics.Tch02IAPRev(usdPrice);
// Analytics.Tch001IAPRev(usdPrice, productId, orderData.orderId, orderData.OrderType(), orderData.payedDate);
// Analytics.Tch02IAPRev(usdPrice);
//
// AdjustService.TrackSubPurchase(usdPrice, productId);
// Analytics.SubPurchase(usdPrice, productId);
AdjustService.TrackSubPurchase(usdPrice, productId);
Analytics.SubPurchase(usdPrice, productId);
Analytics.ReportIAPSuccessEvent(usdPrice, productId, orderData);
}
}
catch (Exception ex)
@ -74,5 +55,28 @@ namespace Guru
}
}
public static AppleOrderRequest Build(int orderType, string productId,
string receipt, string orderId, string date, int level,
string userCurrency, double payPrice, string scene, bool isFree = false)
{
var request = new AppleOrderRequest()
{
receipt = receipt,
orderData = new AppleOrderData(orderType, productId, receipt, orderId, date, level,
userCurrency, payPrice, scene, isFree),
};
return request;
}
public static AppleOrderRequest Build(AppleOrderData data)
{
var request = new AppleOrderRequest()
{
orderData = data,
receipt = data.receipt,
};
return request;
}
}
}

View File

@ -13,13 +13,6 @@ namespace Guru
public GoogleOrderRequest(){}
public GoogleOrderRequest(int orderType, string productId, string subscriptionId, string token, string orderId,
string date, int level, string offerId = "", string basePlanId = "")
{
this.token = token;
orderData = new GoogleOrderData(orderType, productId, token, orderId, date, level, offerId, basePlanId);
}
protected override string RequestURL => IPMConfig.IPM_URL + "order/api/v1/orders/android";
protected override UnityWebRequest CreateRequest()
{
@ -41,17 +34,18 @@ namespace Guru
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
if (responseData != null && responseData.data != null)
{
// Analytics.Tch001IAPRev(responseData.data.usdPrice);
double usdPrice = responseData.data.usdPrice;
string productId = orderData.RealProductId;
Analytics.Tch001IAPRev(usdPrice, productId, orderData.orderId, orderData.OrderType(), orderData.payedDate); // TCH 001
// Analytics.Tch02IAPRev(usdPrice, productId, orderId, orderTypeString, timestamp);
Analytics.Tch02IAPRev(usdPrice); // TCH 020
// Analytics.Tch001IAPRev(usdPrice, productId, orderId, orderType, orderDate); // TCH 001
// // Analytics.Tch02IAPRev(usdPrice, productId, orderId, orderTypeString, timestamp);
// Analytics.Tch02IAPRev(usdPrice); // TCH 020
//
// // Adjust Track IAP Purchase
// AdjustService.TrackIAPPurchase(usdPrice, productId); // 上报 IAP 支付事件
// Analytics.IAPPurchase(usdPrice, productId);
// Adjust Track IAP Purchase
AdjustService.TrackIAPPurchase(usdPrice, productId); // 上报 IAP 支付事件
Analytics.IAPPurchase(usdPrice, productId);
Analytics.ReportIAPSuccessEvent(usdPrice, productId, orderData);
}
}
catch (Exception ex)
@ -61,12 +55,15 @@ namespace Guru
}
public static GoogleOrderRequest Build(int orderType, string productId,
string token, string orderId, string date, int level, string offerId = "", string basePlanId = "")
public static GoogleOrderRequest Build(int orderType, string productId,
string token, string orderId, string date, int level,
string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
{
var request = new GoogleOrderRequest()
{
orderData = new GoogleOrderData(orderType, productId, token, orderId, date, level, offerId, basePlanId),
orderData = new GoogleOrderData(orderType, productId, token, orderId, date, level,
userCurrency, payPrice, scene, isFree, offerId, basePlanId),
token = token,
};
return request;

View File

@ -576,7 +576,6 @@ namespace Guru
// 真实购买后上报对应的事件
if (IsFirstIAP) Analytics.FirstIAP(info.Id, info.Price, info.CurrencyCode); // 上报首次支付打点
Analytics.ProductIAP(info.Id,info.Id, info.Price, info.CurrencyCode);
Analytics.IAPRetTrue(_curProductCategory, info.Id, info.Price, info.CurrencyCode, info.Type, info.IsFree);
}
var pp = purchaseEvent.purchasedProduct;
@ -723,20 +722,26 @@ namespace Guru
Analytics.LogCrashlytics(new Exception($"IAPService can not report order because Validator is null!"));
return false;
}
//---------------- All Report Information --------------------
int level = GetBLevel();
int orderType = args.purchasedProduct.definition.type == ProductType.Subscription ? 1 : 0;
string productId = args.purchasedProduct.definition.id;
string appleReceiptString = "";
// ----- 支付后的b_level上报逻辑
LogI($"--- Report b_level:[{level}] with product id:{args.purchasedProduct.definition.id} ");
// string appleReceiptString = "";
string userCurrency = args.purchasedProduct.metadata.isoCurrencyCode;
double payPrice = decimal.ToDouble(args.purchasedProduct.metadata.localizedPrice);
string scene = _curProductCategory ?? "Store";
bool isFree = false;
if (orderType == 1) isFree = IsSubscriptionFreeTrailById(productId);
//---------------- All Report Information --------------------
LogI($"--- Report b_level:[{level}] with product id:{args.purchasedProduct.definition.id} ");
#if UNITY_EDITOR
// // Editor 不做上报逻辑
LogI($"--- Editor Validate Success. But Editor can't report order.");
return true;
#endif
IPurchaseReceipt[] allReceipts = null;
try
@ -769,7 +774,9 @@ namespace Guru
googleReceipt.purchaseToken,
googleReceipt.orderID,
googleReceipt.purchaseDate,
level, offerId, basePlanId);
level,
userCurrency, payPrice, scene, isFree,
offerId, basePlanId);
}
else if (receipt is AppleInAppPurchaseReceipt appleReceipt)
{
@ -777,7 +784,9 @@ namespace Guru
appleReceipt.productID,
args.purchasedProduct.receipt,
appleReceipt.transactionID,
appleReceipt.purchaseDate, level);
appleReceipt.purchaseDate,
level,
userCurrency, payPrice, scene, isFree);
}
else
{
@ -938,10 +947,13 @@ namespace Guru
/// <param name="basePlanId"></param>
/// <param name="orderId"></param>
private void ReportGoogleOrder(int orderType, string productId, string token,
string orderId, DateTime date, int level, string offerId = "", string basePlanId = "")
string orderId, DateTime date, int level,
string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
{
var payedDate = TimeUtil.GetTimeStampString(date);
var request = GoogleOrderRequest.Build(orderType, productId, token, orderId, payedDate, level, offerId, basePlanId);
var request = GoogleOrderRequest.Build(orderType, productId, token, orderId, payedDate, level,
userCurrency, payPrice, scene, isFree, offerId, basePlanId);
ReportNextOrder(request);
}
private void ReportGoogleOrder(GoogleOrderData data)
@ -962,10 +974,12 @@ namespace Guru
/// <param name="offerId"></param>
/// <param name="basePlanId"></param>
private void ReportAppleOrder(int orderType, string productId, string receipt,
string orderId, DateTime date,int level, string offerId = "", string basePlanId = "")
string orderId, DateTime date,int level, string userCurrency, double payPrice, string scene, bool isFree = false,
string offerId = "", string basePlanId = "")
{
var payedDate = TimeUtil.GetTimeStampString(date);
var request = AppleOrderRequest.Build(orderType, productId, receipt, orderId, payedDate, level);
var request = AppleOrderRequest.Build(orderType, productId, receipt, orderId, payedDate, level,
userCurrency, payPrice, scene, isFree);
ReportNextOrder(request);
}
@ -1105,6 +1119,16 @@ namespace Guru
}
return null;
}
private SubscriptionManager GetSubManagerById(string productId)
{
var product = _storeController.products.WithID(productId);
if (product != null && product.definition.type == ProductType.Subscription)
{
return new SubscriptionManager(product, null);
}
return null;
}
public bool IsSubscriptionFreeTrail(string productName)
@ -1118,6 +1142,18 @@ namespace Guru
}
return false;
}
public bool IsSubscriptionFreeTrailById(string productId)
{
if(!IsInitialized) return false;
var smgr = GetSubManagerById(productId);
if (smgr != null)
{
return smgr.getSubscriptionInfo().isFreeTrial() == Result.True;
}
return false;
}
public bool IsSubscriptionCancelled(string productName)