总结 #
Tenjin Unity SDK 允许客户使用 Unity 开发工具来跟踪应用程序中的事件和安装。 要了解有关 Tenjin 和我们的产品的更多信息,请访问 https://www.tenjin.com.
- 请查看我们的发行说明中的版本详情和变化。
- Tenjin Unity SDK 支持 iOS 和 Android.
- 可查看iOS, Android文档,并根据需求采用适合的项目。
- 如果有任何技术问题或需要支持,请邮件至 support@tenjin.com, 我们有遍布全球的支持团队为你服务。
如果你使用 Unity SDK v1.12.29 或者更低版本,请在集成前参考这里 。
如果从低于v1.12.30的版本升级,请在安装最新Unity版本之前先删除Tenjin的binary文件。
如果你运行 iOS 的时候遇到以下错误:
Library not loaded: @rpath/TenjinSDK.framework/TenjinSDK
你需要到 “Frameworks, Libraries and Embedded Content” 添加 TenjinSDK, 并选择 'Embed & Sign'
如果项目中从旧版本的 Tenjin SDK 带来了 libTenjinSDK.a 和libTenjinSDKUniversal.a,请删除旧的版本,并运行pod install进行 iOS集成。
Unity Package Manager (UPM) #
从Git URL安装UPM包的步骤:
- 如果尚未打开,请先打开Package Manager窗口
- 打开Package Manager工具栏中的Add (+) 菜单。
- 在安装菜单中,选择Install package from git URL,会出现一个文本输入框和一个“安装”按钮。
- 在文本框中输入以下有效的Git URL(注意:必须在末尾追加
#符号及版本号标签):https://github.com/tenjin/tenjin-unity-sdk.git#1.16.3 - 点击 Install(安装)
手动安装 (.unitypackage) #
- 下载最新版本 Unity SDK这里.
- 将
TenjinUnityPackage.unitypackage导入你的项目: Assets -> Import Package。
Android重要提示 #
为确保Tenjin完美兼容最新功能与修复,请确保您的Maven (Gradle) dependencies更新至最新版本,我们通过Maven分发Tenjin Android SDK,注意到部分开发者仍在使用过时版本,非最新版本可能会引发问题。
若使用Android Studio构建,请执行Gradle Sync同步操作以更新dependencies
若未使用Android Studio,请按以下步骤在Unity内更新:
- 打开Unity
- 进入Assets > External Dependency Manager > Android Resolver
- 点击Force Resolve,更新Gradle dependencies至最新版本
Google Play #
App Store 默认值为unspecified。 如果你在谷歌应用商店推广,请将此值设为unspecified
将 App Store Type 值设为 googleplay:
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetAppStoreType(AppStoreType.googleplay);Tenjin SDK需要以下权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Required to get network connectivity (i.e. wifi vs. mobile) -->谷歌商店要求所有Android 13系统(API级别32)并使用广告ID(AAID)的应用,在 manifest file中声明谷歌商店AD_ID的权限(如下所示)。 为了使用以下权限,您需要将 tenjin-android-sdk 更新到 1.12.8 版本。
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>AndroidAdvertising ID (AAID)和Install Referrer #
在你的build.gradle文件中添加Android Advertising ID (AAID) 和 Install Referrer库。
dependencies {
implementation 'com.google.android.gms:play-services-ads-identifier:{version}'
implementation 'com.android.installreferrer:installreferrer:{version}'
}为了能够收集Meta’s Install Referrer, 请将以下查询添加到您的Android Manifest中
<queries>
<package android:name="com.facebook.katana" />
</queries>
<queries>
<package android:name="com.instagram.android" />
</queries>接下来,在你的 strings.xml 文件中添加以下值,请记得替换为您相应的 Facebook APP ID。(你可以根据这个文档创建模板文件,用于存储字符串数值)
<string name="facebook_app_id" translatable="false">YOUR_META_APP_ID</string>Amazon store #
App Store 默认值为unspecified。 如果你在亚马逊应用商店推广,请将此值设为amazon
将 App Store Type 值设为 amazon:
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetAppStoreType(AppStoreType.amazon);OAID 及其他安卓应用商店 #
Tenjin 支持使用 OAID 在其他非 Google Play 商店渠道进行推广,您需要集成以下 OAID 库。 如果您需要在安卓中国、华为海外等应用商店推广,请集成以下这些 OAID 库。
MSA OAID #
集成MSA library库,你需要下载 oaid\_sdk\_1.0.25.aar
将oaid_sdk_1.0.25.aar文件置于你项目中安卓库路径下: /Assets/Plugins/Android
将 App Store Type 值设为 other:
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetAppStoreType(AppStoreType.other);Huawei OAID (华为海外) #
对于在华为海外应用商店的推广,你可以集成华为 OAID 库来获取 OAID。可将Huawei OAID库,在项目中添加以下内容:Huawei AAR file: huawei-ads-identifier.aar如果你的应用在Huawei App Gallery华为海外应用商店 上架,请下载 Huawei Install Referrer 文件:huawei-ads-installreferrer.aar
将华为文件置于你项目中安卓库路径下: /Assets/Plugins/Android
将 App Store Type 值设为 other:
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetAppStoreType(AppStoreType.other);Proguard设置 #
-keep class com.tenjin.** { *; }
-keep public class com.google.android.gms.ads.identifier.** { *; }
-keep public class com.google.android.gms.common.** { *; }
-keep public class com.android.installreferrer.** { *; }
-keep class * extends java.util.ListResourceBundle {
protected java.lang.Object[][] getContents();
}
-keepattributes *Annotation*如果你使用华为库,你可以使用下面设置:
-keep class com.huawei.hms.ads.** { *; }
-keep interface com.huawei.hms.ads.** { *; }App初始化 #
- 您可以在App页面获取
SDK_KEY。 请注意:每个应用的SDK_KEY都是唯一的,您可以为每个应用生成最多3个SDK_KEY。

- 在你项目中的首个
Start()方法里,添加以下代码行。如果你希望在用户从后台恢复使用应用时发送会话数据,也请将其添加到OnApplicationPause()中。
using UnityEngine;
using System.Collections;
public class TenjinExampleScript : MonoBehaviour {
void Start() {
TenjinConnect();
}
void OnApplicationPause(bool pauseStatus) {
if (!pauseStatus) {
TenjinConnect();
}
}
public void TenjinConnect() {
BaseTenjin instance = Tenjin.getInstance(" ");
// Sends Install/open event to Tenjin
instance.Connect();
}
}NOTE: Please ensure to implement this code on every Start() and OnApplicationPause(), not only on the first app open of the app.
应用商店类型 #
我们支持以下应用商店选项,
- googleplay
- amazon
- other
默认情况下, 应用商店类型设置为unspecified 请根据自身应用推广情况设置相应的值。安卓中国及华为海外商店推广请设置为other
AndroidManifest.xml:
<meta-data
android:name="TENJIN_APP_STORE"
android:value="{{SET_APP_STORE_TYPE_VALUE}}" />SetAppStoreType():
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetAppStoreType(AppStoreType.{{SET_APP_STORE_TYPE_VALUE}});ATTrackingManager (iOS) #
- 从 iOS 14 开始,你可以选择初始话并显示 ATTrackingManager权限提示,让用户选择允许或不允许。
- 如果用户选择不允许追踪,IDFA 的值将会是0,如果用户选择同意追踪,
Connect()方法就会发送 IDFA 到我们的服务器。 - 即便不使用 ATTrackingManager,你也可以调用
connect()。如果您不打算获取用户的IDFA或将其传给Tenjin,可以选择不启用ATT。
using UnityEngine;
using System.Collections;
using UnityEngine.iOS;
public class TenjinExampleScript : MonoBehaviour {
void Start() {
TenjinConnect();
}
void OnApplicationPause(bool pauseStatus) {
if (!pauseStatus) {
TenjinConnect();
}
}
public void TenjinConnect() {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
#if UNITY_IOS
if (new Version(Device.systemVersion).CompareTo(new Version("14.0")) >= 0) {
// Tenjin wrapper for requestTrackingAuthorization
instance.RequestTrackingAuthorizationWithCompletionHandler((status) => {
Debug.Log("===> App Tracking Transparency Authorization Status: " + status);
// Sends Install/open event to Tenjin
instance.Connect();
});
}
else {
instance.Connect();
}
#elif UNITY_ANDROID
// Sends Install/open event to Tenjin
instance.Connect();
#endif
}
}显示ATT权限请求弹窗 #
为遵守Apple的ATT指南,你需要为ATT权限请求弹窗提供说明,并在你的应用中实现该权限请求。
注意:在您的游戏中投放广告之前,您必须执行权限请求。
设定用户跟踪描述 #
Apple 需要开发者描述 ATT 提示的用途。您需要在 Xcode 项目的Info.plist文件中使用 NSUserTrackingUsageDescription设置描述。您必须提供一条消息,告知用户您为何请求使用设备跟踪数据的权限:
- 在您的 Xcode 项目导航器中,打开
Info.plist文件。 - 单击属性列表编辑器中任意键旁边的添加按钮 (+) 以创建新的属性键。
- 输入键名
NSUserTrackingUsageDescription. - 选择字符串 String 值类型。
- 在值字段中输入应用跟踪透明度消息。一些例子包括:
- “我们将使用您的数据来提供更好的个性化广告体验。”
- “我们会尝试根据您使用的应用程序、您使用的设备以及您所在的国家/地区展示您最感兴趣的应用程序和产品的广告。”
- “我们会尝试根据您使用的应用为您最感兴趣的应用和产品展示广告。”
注意:Apple 提供了特定的应用商店指南,为所有面向最终用户的隐私相关功能定义了可接受的使用和消息传递。Tenjin 不提供法律意见。因此,此页面上的信息不能替代您寻求自己的法律顾问来确定您的业务和流程的法律要求以及如何解决这些要求。
SKAdNetwork 和 Conversion Values 转化值 #
作为SKAdNetwork的一部分,我们为 updatePostbackConversionValue(_:) 创建的封装方案,可以注册等效的 SKAdNetwork 方案并同时发送 conversion values 到我们的服务器。
updatePostbackConversionValue(_:) 6位值来对应应用内事件,不能二进制形式输入,而应为 0-63 的整数。我们的服务器将拒绝任何无效值。
对于支持 SKAdNetwork 4.0 的 iOS 16.1 之后的版本,现可通过发送coarseValue (String 字符串格式,可能的变体为 "low","medium" 或者 "high")以及lockWindow(Boolean 布尔值)作为更新版回传方法的参数
updatePostbackConversionValue(conversionValue: Integer, coarseValue: String)
updatePostbackConversionValue(conversionValue: Integer, coarseValue: String, lockWindow: Bool)
- 对于 iOS 版本为 16.1+,即支持 SKAdNetwork 4.0,您可以根据需要多次调用此方法,并可以使转换值低于或高于上一个值。
- 对于 iOS 版本低于 16.1,即所支持的 SKAdnetWork 版本低于 4.0,您仍可以调用此方法,我们的 SDK 将自动检测 iOS 版本并仅更新
conversionValue转换值。
using UnityEngine;
using System.Collections;
public class TenjinExampleScript : MonoBehaviour {
void Start() {
TenjinConnect();
}
void OnApplicationPause(bool pauseStatus) {
if (!pauseStatus) {
TenjinConnect();
}
}
public void TenjinConnect() {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
#if UNITY_IOS
// Sends Install/open event to Tenjin
instance.Connect();
// Sets SKAdNetwork Conversion Value
// You will need to use a value between 0-63
instance.updatePostbackConversionValue(<Integer between 0 and 63>);
// For iOS 16.1+ (SKAN 4.0)
instance.updatePostbackConversionValue(<Integer between 0 and 63>, "medium");
instance.updatePostbackConversionValue(<Integer between 0 and 63>, "medium", true);
#elif UNITY_ANDROID
// Sends Install/open event to Tenjin
instance.Connect();
#endif
}
}SKAdNetwork 和 iOS 15+ 广告主回调 #
要将Tenjin指定为你的SK Ad Network回调接收方,请执行以下操作:
- 在 Xcode 的项目导航器中选择
Info.plist。 - 单击"属性/Property"列表编辑器中某个键旁边的添加按钮 (+),然后按回车键。
- 输入名称
NSAdvertisingAttributionReportEndpoint. - 从"类型/Type"列的弹出菜单中选择"String"。
- 输入
https://tenjin-skan.com
这些步骤来自Apple的文档: https://developer.apple.com/documentation/storekit/skadnetwork/configuring_an_advertised_app.
GDPR #
作为GDPR合规的一部分,使用Tenjin的SDK,你可以选择设备/用户的同意(opt-in)或拒绝(opt-out),或者选择针对哪些具体的设备相关参数进行同意或拒绝。
调用OptOut()时,将不会向Tenjin发送任何API请求,也不会处理任何事件。
选择opt-in/opt-out:
void Start () {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
boolean userOptIn = CheckOptInValue();
if (userOptIn) {
instance.OptIn();
}
else {
instance.OptOut();
}
instance.Connect();
}
boolean CheckOptInValue()
{
// check opt-in value
// return true; // if user opted-in
return false;
}- 若您希望选择特定设备相关参数的启用或禁用,您可使用
OptInParams()或OptOutParams(). OptInParams()只会发送设备相关的指定参数,而OptInParams()则会发送除指定参数之外的其他所有与设备相关的参数- -敬请注意,为了在Tenjin系统中准确地追踪设备,我们需要您提供以下重要参数。如有任何一项必要参数未被提供,将导致无法正常处理或记录有关事件。
- 对于Android
advertising_id
- 对于iOS
developer_device_id
- 如果你使用 IMEI 或 OAID, 请添加:
imeioaid
- 如果你使用 Google Ads 投放,请添加以下字段:
platformos_versionapp_versionlocaledevice_modelbuild_idadvertising_iddeveloper_device_id(for iOS)
如果只想使用OptInParams()获取与设备相关的特定参数,在下面的样例中, 我们只发送这些设备相关的参数: ip_address, advertising_id, developer_device_id, limit_ad_tracking, 和referrer:
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
List<string> optInParams = new List<string> {"ip_address", "advertising_id", "developer_device_id", "limit_ad_tracking", "referrer", "iad"};
instance.OptInParams(optInParams);
instance.Connect();如果要使用OptOutParams()发送除特定设备相关参数以外的所有参数,如下样例中,我们会发送除了 locale, timezone, 和 build_id之外的所有相关的参数。
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
List<string> optOutParams = new List<string> {"locale", "timezone", "build_id"};
instance.OptOutParams(optOutParams);
instance.Connect();Opt in/out using CMP #
您可以使用CMP (目的 1)的条款,实现自动选择opt in/out功能,并返回布尔值(boolean)。该功能基于用户设备中已存储的信息,无需额外交互。
OptInOutUsingCMP()
BaseTenjin instance = Tenjin.getInstance(" ");
optInOut = instance.OptInOutUsingCMP(); 设备层级数据 #
| 参数 | 说明 | 平台 |
|---|---|---|
| ip_address | IP 地址 | All |
| advertising_id | 设备的广告标识符 | All |
| developer_device_id | ID for Vendor | iOS |
| oaid | 启用 Advertising ID 广告标识符 | Android |
| imei | 设备的 IMEI | Android |
| limit_ad_tracking | 设备是否限制广告追踪 | All |
| platform | platform | All |
| referrer | Google Play Install Referrer | Android |
| os_version | 操作系统版本 | All |
| device | 设备名称 | All |
| device_manufacturer | 设备商 | Android |
| device_model | 设备型号 | All |
| device_brand | 设备品牌 | Android |
| device_product | 设备产品 | Android |
| device_model_name | 设备型号 | iOS |
| device_cpu | 设备CPU | iOS |
| carrier | 电话运营商 | Android |
| connection_type | 移动流量或 Wifi | Android |
| screen_width | 设备屏幕宽度 | Android |
| screen_height | 设备屏幕高度 | Android |
| os_version_release | 操作系统版本 | All |
| build_id | 包名 | All |
| locale | 设备区域设置 | All |
| country | 设备国家设置 | All |
| timezone | timezone | All |
购买事件 #
iOS 内购验证 #
iOS 验证 receipt 需要 transactionId 和 receipt (signature 将设置为 null). 对与 receipt,请确保从 unity 发送Payload的receipt(以 base64 编码的 ASN.1 receipt)。
重要提示: 如果你有内购订阅,你需要添加 App 的 share secret 到 Tenjin面板。你可以在通过以下途径获取 iOS 的共享密钥iTunes Connect Console >iTunes Connect Console > Select your app > App Information > App-Specific Shared Secret.
Android 内购验证 #
Google Play App Store
Google Play 的 receipt 验证必须提供 receipt 和 signature , (transactionId 设置为 null).
重要提示: 你需要在Tenjin面板app的“edit”页面中添加app的 public key。获取Base64-encoded RSA public key的路径为Google Play Developer Console > Select your app > Monetize > Monetization setup > Google Play Billing > Licensing: Base64-encoded RSA public key.
注意
在谷歌商店中,请确保在发送购买事件给Tenjin前已确认该事件。更多信息可参考这个链接。
Amazon 商店
Amazon商店内购收据验证需要receiptId 和 userId字段.
重要提示: 你需要将 Amazon 密钥添加至Tenjin面板。 你可以在开发者账户 Amazon Appstore account里查看相应的密钥。
iOS 和 Android内购集成示例 #
在以下示例中,我们使用通用的MiniJSON库做 JSON 处理。
如果你用的是Unity IAP版本5及以上:
针对消耗型商品(Consumable Products), 收据仅在待处理订单(PendingOrder)状态下可用。一旦订单进入已确认 (ConfirmedOrder)状态,收据信息将会被清空。因此,对于消耗型商品,请务必在OnPurchasePending回调阶段处理购买操作并将其发送给Tenjin。
public static void OnPurchasePending(PendingOrder pendingOrder) {
ProcessOrder(pendingOrder);
// Confirm the purchase after processing
UnityIAPServices.DefaultPurchase().ConfirmPurchase(pendingOrder);
}
public static void ProcessOrder(Order order) {
// Get the first item from the cart
var item = order.CartOrdered.Items().FirstOrDefault();
if (item == null) return;
var product = item.Product;
var price = product.metadata.localizedPrice;
double lPrice = decimal.ToDouble(price);
var currencyCode = product.metadata.isoCurrencyCode;
var productId = product.definition.id;
var info = order.Info;
#if UNITY_ANDROID
// Parse the unified receipt JSON
var wrapper = Json.Deserialize(info.Receipt) as Dictionary<string, object>; // https://gist.github.com/darktable/1411710
if (wrapper == null) return;
var store = (string)wrapper["Store"];
var payload = (string)wrapper["Payload"];
if (store.Equals("GooglePlay")) {
var googleDetails = Json.Deserialize(payload) as Dictionary<string, object>;
var googleJson = (string)googleDetails["json"];
var googleSig = (string)googleDetails["signature"];
CompletedAndroidPurchase(productId, currencyCode, 1, lPrice, googleJson, googleSig);
}
if (store.Equals("AmazonAppStore")) {
var amazonDetails = Json.Deserialize(payload) as Dictionary<string, object>;
var amazonReceiptId = (string)amazonDetails["receiptId"];
var amazonUserId = (string)amazonDetails["userId"];
CompletedAmazonPurchase(productId, currencyCode, 1, lPrice, amazonReceiptId, amazonUserId);
}
#elif UNITY_IOS
// Try SK2 first (Unity IAP 5.1+ on iOS 15+), fall back to SK1
var receipt = info.Apple?.jwsRepresentation;
if (string.IsNullOrEmpty(receipt)) {
receipt = info.Apple?.AppReceipt;
}
if (string.IsNullOrEmpty(receipt)) {
Debug.LogError("No receipt available");
return;
}
var transactionId = info.TransactionID;
CompletedIosPurchase(productId, currencyCode, 1, lPrice, transactionId, receipt);
#endif
}
private static void CompletedAndroidPurchase(string ProductId, string CurrencyCode, int Quantity,
double UnitPrice, string Receipt, string Signature)
{
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.Transaction(ProductId, CurrencyCode, Quantity, UnitPrice, null, Receipt, Signature);
}
private static void CompletedIosPurchase(string ProductId, string CurrencyCode, int Quantity,
double UnitPrice, string TransactionId, string Receipt)
{
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.Transaction(ProductId, CurrencyCode, Quantity, UnitPrice, TransactionId, Receipt, null);
}
private static void CompletedAmazonPurchase(string ProductId, string CurrencyCode, int Quantity,
double UnitPrice, string ReceiptId, string UserId)
{
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.TransactionAmazon(ProductId, CurrencyCode, Quantity, UnitPrice, ReceiptId, UserId);
}如果你用的是Unity IAP版本4或以下:
public static void OnProcessPurchase(PurchaseEventArgs purchaseEventArgs) {
var price = purchaseEventArgs.purchasedProduct.metadata.localizedPrice;
double lPrice = decimal.ToDouble(price);
var currencyCode = purchaseEventArgs.purchasedProduct.metadata.isoCurrencyCode;
var wrapper = Json.Deserialize(purchaseEventArgs.purchasedProduct.receipt) as Dictionary<string, object>;
// https://gist.github.com/darktable/1411710
if (null == wrapper) {
return;
}
var store = (string)wrapper["Store"]; // GooglePlay, AmazonAppStore, AppleAppStore, etc.
var payload = (string)wrapper["Payload"]; // For Apple: base64 encoded ASN.1 receipt. For Android: raw JSON receipt.
var productId = purchaseEventArgs.purchasedProduct.definition.id;
#if UNITY_ANDROID
if (store.Equals("GooglePlay")) {
var googleDetails = Json.Deserialize(payload) as Dictionary<string, object>;
var googleJson = (string)googleDetails["json"];
var googleSig = (string)googleDetails["signature"];
CompletedAndroidPurchase(productId, currencyCode, 1, lPrice, googleJson, googleSig);
}
if (store.Equals("AmazonApps")) {
var amazonDetails = Json.Deserialize(payload) as Dictionary<string, object>;
var amazonReceiptId = (string)amazonDetails["receiptId"];
var amazonUserId = (string)amazonDetails["userId"];
CompletedAmazonPurchase(productId, currencyCode, 1, lPrice, amazonReceiptId, amazonUserId);
}
#elif UNITY_IOS
var transactionId = purchaseEventArgs.purchasedProduct.transactionID;
CompletedIosPurchase(productId, currencyCode, 1, lPrice, transactionId, payload);
#endif
}
private static void CompletedAndroidPurchase(string ProductId, string CurrencyCode, int Quantity, double UnitPrice, string Receipt, string Signature) {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.Transaction(ProductId, CurrencyCode, Quantity, UnitPrice, null, Receipt, Signature);
}
private static void CompletedIosPurchase(string ProductId, string CurrencyCode, int Quantity, double UnitPrice, string TransactionId, string Receipt) {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.Transaction(ProductId, CurrencyCode, Quantity, UnitPrice, TransactionId, Receipt, null);
}
private static void CompletedAmazonPurchase(string ProductId, string CurrencyCode, int Quantity, double UnitPrice, string ReceiptId, string UserId) {
BaseTenjin instance = Tenjin.getInstance("SDK_KEY");
instance.TransactionAmazon(ProductId, CurrencyCode, Quantity, UnitPrice, ReceiptId, UserId);
}(灵活的应用商店佣金设置)您可以在Tenjin面板上选择0%、15%或30%的应用商店收入佣金。操作步骤如下:
- 前往CONFIGURE –> Apps
- 单击您想要更改的应用程序
- 在“App Store Commission”部分下单击“Edit”
- 在0%、15%或30%中选择您想要的应用商店佣金比例。
- 选择开始日期和结束日期(或者,如果您不需要结束日期,可以将结束日期留空)
- 点击“Save”保存(注意:佣金设置只会应用于变更日期之后的数据,历史数据不会受影响。因此请将开始日期设置为修改当天及之后的日期)。
订阅服务 #
- 你需要在每个订阅间隔内发送一次订阅交易(例如,对于每月订阅,你需要每月向我们发送1笔交易)。在下面的示例时间轴中,交易事件仅应在“首次收费”和“续订”事件中发送。在试用期间,请勿将交易事件发送给 Tenjin。
- Tenjin不会对重复交易进行重复数据删除。
- 如果你有 iOS 内购订阅,你需要添加 App 的 share secret 的 public key。iOS 的 Shared Secret 获取路径为iTunes Connect Console >iTunes Connect Console >Select your app > Features > In-App Purchases > App-Specific Shared Secret。
- 有关 iOS 订阅的更多信息,请参阅: Apple 关于使用订阅的文档
- 关 Android 订阅的更多信息,请参阅: Google Play 收费订阅文档
自定义事件 #
重要:自定义事件名称请限制在80个字符以内。自定义事件的数量不得超过500个。
- 在 Unity project 中包含 Assets 文件夹
- 在自定义事件的 projects method 中为命名事件编写以下内容:
Tenjin.getInstance("").SendEvent("name")以及需为整数值的命名事件的以下内容:Tenjin.getInstance("").SendEvent("nameWithValue","value") - 确保传递的code data-no-translation="" data-no-auto-translation="">value是整数值(例如“2000”,而不是“0.02”)。如果code data-no-translation="" data-no-auto-translation="">value不是整数值,则将省略值参数。
代码示例:
void MethodWithCustomEvent(){
//event with name
BaseTenjin instance = Tenjin.getInstance ("SDK_KEY");
instance.SendEvent("name");
//event with name and integer value
instance.SendEvent("nameWithValue", "value");
}.SendEvent("name")可发送应用内关键节点,如 tutorial_complete, registration, 或 level_1.
.SendEvent("name", "value")可发送带参数的关键事件。比如,("coins_purchased", "100")) 可用来分析金币购买的总数及平均数。
S2S 服务端集成 #
Tenjin提供s2s服务端集成。这允许你直接从自己的服务器向Tenjin服务器发送安装和安装后事件,无需集成SDK。
应用子版本及 A/B 测试(需要DataVault) #
如果你想进行 A/B 测试并查看差异报告,我们可以使用appendAppSubversion方法将数字值附加到你的应用程序版本中。例如,如果你的应用程序版本 1.0.1设置了appendAppSubversion: @8888,就可以上报 App version 为1.0.1.8888的数据。
这些数据将在 DataVault 中,你可以通对应的过 subversion 值来查看报告。
BaseTenjin instance = Tenjin.getInstance(" ");
instance.AppendAppSubversion(8888);
instance.Connect();动态运营LiveOps #
Tenjin 支持在 SDK 层面获取用户的来源信息,包括买量渠道及广告计划等。如有需要,请联系您的客户经理。 这将允许广告主实时收集和分析这些用户级归因数据。以下是使用 Tenjin LiveOps 动态运营的实用案例:
- 如果您有自己的数据分析工具,S2S回调将允许您将归因数据与设备级别的游戏内数据联系起来,也就是将推广数据与应用内事件数据相联系。
- 根据用户的来源显示不同的应用程序内容。例如,用户 A 是自然量用户,而用户 B 是 Facebook 买量用户。由于用户 B 可能更喜欢您的应用程序,因此您可能希望为用户 B 显示游戏内的特别优惠,这时就可以使用归因信息回调。如果您想讨论更多具体的用例,请联系 Tenjin 成功经理。
LiveOps相关文档请参考这里。
用户ID #
您发送事件时可以设置自定义的用户ID。
.SetCustomerUserId("user_id")
.GetCustomerUserId()
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetCustomerUserId("user_id");
string userId = instance.GetCustomerUserId(); 分析ID Analytics Installation ID #
您可以在设备的本地储备中获取分析ID(Analytics Installation ID),该ID是随机生成的。 GetAnalyticsInstallationId()
BaseTenjin instance = Tenjin.getInstance(" ");
analyticsId = instance.GetAnalyticsInstallationId; 重试/缓存事件 #
当请求失败或用户没有网络连接时,您可以启用/禁用重试和缓存所有事件。 这些事件将在新事件添加到队列并且用户恢复连接后发送。
.SetCacheEventSetting(true)
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetCacheEventSetting(true); Google DMA 参数 #
若您已集成CMP的模式,Google DMA参数将由Tenjin SDK自动采集,且无需额外操作。若您希望取代CMP,或者构建自己的用户协议机制,您可以使用以下方法:
SetGoogleDMAParameters(bool, bool)
BaseTenjin instance = Tenjin.getInstance(" ");
instance.SetGoogleDMAParameters(adPersonalization, adUserData); 您可以选择加入或退出谷歌 DMA 参数的收集,从而管理谷歌DMA参数的收集。默认情况下会加入,但您可以使用 optInGoogleDMA 或 optOutGoogleDMA 方法轻松更改您的偏好,从而完全控制您的数据隐私设置。
instance.OptInGoogleDMA();
instance.OptOutGoogleDMA(); 用户画像–LiveOps指标 #
Tenjin SDK会自动跟踪并汇总用户的Session和收入指标,这些数据可用于LiveOps活动、用户分群和数据分析。User Profile功能可为单个用户提供这些指标的实时访问。
跟踪指标 #
SDK会自动追踪每位用户的以下指标:
| Metric | 说明 | 类型 |
|---|---|---|
session_count | 会话总次数 | 整数 |
total_session_time | 累计会话时长(单位:毫秒) | 数字 |
average_session_length | 平均会话时长(单位:毫秒) | 数字 |
last_session_length | 末次会话时长(单位:毫秒) | 数字 |
iap_transaction_count | IAP交易总数 | 整数 |
total_ilrd_revenue_usd | 总的ILRD广告收入(美元) | 数字 |
first_session_date | 首次会话的ISO8601时间戳 | 字符串 |
last_session_date | 最近一次已完成会话的ISO8601时间戳 | 字符串 |
current_session_length | 当前活跃会话时长(单位:毫秒) | 数字 |
iap_revenue_by_currency | 按货币代码划分收入 | JSON字符串 |
purchased_product_ids | 已购商品ID数组 | JSON字符串 |
ilrd_revenue_by_network | 按广告渠道划分的ILRD收入 | JSON字符串 |
注意:条件字段(日期、当前会话、收入映射、产品数组)仅在存在数据时才会包含在Dictionary中。
可用方法 #
获取用户档案字典 #
返回一个包含当前用户所有跟踪指标的字典。所有值均以字符串形式返回(数值、JSON数组及JSON对象将被转换为字符串)。
BaseTenjin instance = Tenjin.getInstance("<SDK_KEY>");
Dictionary<string, string> profile = instance.GetUserProfileDictionary();
if (profile != null && profile.Count > 0)
{
Debug.Log("Session Count: " + profile["session_count"]);
Debug.Log("Total Session Time (ms): " + profile["total_session_time"]);
Debug.Log("Average Session Length (ms): " + profile["average_session_length"]);
Debug.Log("Last Session Length (ms): " + profile["last_session_length"]);
Debug.Log("IAP Transaction Count: " + profile["iap_transaction_count"]);
Debug.Log("Total ILRD Revenue USD: " + profile["total_ilrd_revenue_usd"]);
// Convert milliseconds to seconds if needed
long totalTimeMs = long.Parse(profile["total_session_time"]);
Debug.Log($"Total Session Time: {totalTimeMs / 1000.0:F1} seconds");
// Revenue by currency is a JSON string (conditional)
if (profile.ContainsKey("iap_revenue_by_currency"))
{
Debug.Log("IAP Revenue by Currency: " + profile["iap_revenue_by_currency"]);
// Example: {"USD":99.99,"EUR":49.99}
}
// Product IDs is a JSON array string (conditional)
if (profile.ContainsKey("purchased_product_ids"))
{
Debug.Log("Purchased Products: " + profile["purchased_product_ids"]);
// Example: ["com.app.coins100","com.app.coins500"]
}
}
else
{
Debug.Log("User profile not available yet");
}重置用户档案 #
清除当前用户的所有跟踪指标(适用于测试场景或用户注销)。
BaseTenjin instance = Tenjin.getInstance("<SDK_KEY>");
instance.ResetUserProfile();
Debug.Log("User profile has been reset");平台相关说明 #
数据可用性:
用户资料数据会在首次会话被跟踪后可用。
GetUserProfileDictionary()方法会返回来自SDK内存缓存的实时数据。
时间单位:
- 为确保跨平台一致性,iOS和Android系统上的所有时间值现均已统一为毫秒单位。
- 如需转换为秒,请计算:毫秒数/1000.0
milliseconds / 1000.0
复杂数据类型:
- 收入映射(
iap_revenue_by_currency、ilrd_revenue_by_network)会以JSON字符串形式返回:{"USD":99.99,"EUR":49.99}。 - 产品ID数组(
purchased_product_ids)会以JSON字符串形式返回:["product1","product2"]。
广告展示层级收益集成 #
Tenjin目前支持与以下聚合平台展示数据的集成:
- AppLovin MAX
- Unity LevelPlay
- HyperBid
- AdMob
- TopOn
- CAS
- TradPlus
此功能将允许您获取每一个广告展示的明细数据,该功能可用于广告投放渠道基于广告收益的优化策略,以及更精确的用户层级收益计算等。相关文档请查看这里。
集成测试 #
You can verify if the integration is working correctly with our Live Test Device Data Tool. Add your advertising_id 或 IDFA/GAID to the list of test devices. You can find this under Support -> Test Devices. Go to the Live Event Tool page and send the test events from your app. You should see live events come in:
