Tenjin Unity 插件
- 允许 Unity 的开发商快速集成 Tenjin 的 install API。
- 查看 iOS 和 Android 文档,并将合适的平台设置应用于您的 builds。最重要的是:
- iOS: 确保您具有正确的 build 设置,并且包括所需的 iOS 框架。
- Android: 如果您已经集成的 SDK 中有安装 Google Play Services 或者使用 PlayServicesResolver, 则可能需要删除以下文件:
/Assets/Plugins/Android/play-services-basement-11.0.4.aar
- 您需要的 "API_KEY" 在 Organizations 标签页
请参阅我们的 Release Notes 查看详细的历史版本。
有任何技术问题,请邮件至: support@tenjin.com
Tenjin Unity
- Tenjin 可以使用 Unity SDK 同时支持 iOS 和 Android.
- 您的 "API_KEY" 位于您的账号 Organizations tab
- 请查看 iOS 和 Android 文档来确认哪种方案适用您的产品。
- iOS Notes:
- 如果您集成 iOS SDK v1.12.0 或以上版本,请使用 Xcode 12。
- 对于 iOS 版本,请确认以下 frameworks 是否已经自动添加至 Xcode,如有任何缺失,您需要手动添加至 Xcode。
- AdSupport.framework
- AppTrackingTransparency.framework
- iAd.framework
- StoreKit.framework
- 针对 ATT(AppTrackingTransparency),请确保更新您的
.plist
文件,并在添加Privacy - Tracking Usage Description
(NSUserTrackingUsageDescription) 的同时,向用户展示您认为需要展示的文字信息。
Android Notes:
- 如果您有其他 SDK 已经有 Google Play Services installed 或使用 PlayServicesResolver,您需要删除
/Assets/Plugins/Android/play-services-ads-identifier--*.aar
和/Assets/Plugins/Android/play-services-basement---*.aar
如果您使用的 Unity SDK 版本为 1.12.4 或以下版本,并在应用初始时看到以下错误提示,请将 tenjin.aar文件从 /Assets/Plugins/Android/Tenjin/libs 挪至 /Assets/Plugins/Android/.
AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='setWrapperVersion'
或
AndroidJavaException: java.lang.ClassNotFoundException: com.tenjin.android.TenjinSDK
- 如果您有其他 SDK 已经有 Google Play Services installed 或使用 PlayServicesResolver,您需要删除
Tenjin 安装/会话(install/session)集成:
- 在您的Unity项目中包含Assets文件夹
- 在项目的第一个
Start()
方法中加入BaseTenjin instance = Tenjin.getInstance("API_KEY")
和instance.Connect()
代码示例:
using UnityEngine;
using System.Collections;
public class TenjinExampleScript : MonoBehaviour {
// Use this for initialization
void Start () {
BaseTenjin instance = Tenjin.getInstance("API_KEY");
instance.Connect();
}
// Update is called once per frame
void Update () {
}
void OnApplicationPause(bool pauseStatus){
if (pauseStatus) {
//do nothing
}
else {
BaseTenjin instance = Tenjin.getInstance("API_KEY");
instance.Connect();
}
}
}
ATTrackingManager 初始化
从 iOS 14 开始,您可以选择初始话并显示 ATTrackingManager 权限提示,让用户选择允许或不允许。如果用户选择不允许追踪,IDFA 的值将会是0,如果用户选择同意追踪, connect()
方法就会发送 IDFA 到我们的服务器。即便不使用 ATTrackingManager,您也可以调用 Tenjin connect()
, 目前 ATTrackingManager 弹窗尚未强制弹出,预计苹果会在2021年初强制推行。
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK init:@"<API_KEY>"];
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
[TenjinSDK connect];
}];
} else {
[TenjinSDK connect];
}
}
SKAdNetwork 和 Conversion value:
作为 SKAdNetwork 的一部分,我们为 registerAppForAdNetworkAttribution()
和 updateConversionValue(_:)
创建的封装方案,可以注册等效的 SKAdNetwork 方案并同时发送 conversion values 到我们的服务器。
updateConversionValue(_:) 6位值来对应应用内事件,不能二进制形式输入,而应为 0-63 的整数。我们的服务器将拒绝任何无效值。
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK init:@"<API_KEY>"];
//
// This will call [SKAdNetwork registerAppForAdNetworkAttribution]
//
[TenjinSDK registerAppForAdNetworkAttribution];
[TenjinSDK connect];
//
// This will call [SKAdNetwork updateConversionValue: <YOUR 6 bit value>]
// and also send conversion value to our servers.
//
// You will need to use a value between 0-63 for <YOUR 6 bit value>.
//
[TenjinSDK updateConversionValue: <YOUR 6 bit value>];
}
您可以通过 Live Test Device Data Tool.来验证集成是否正常运行。 添加 advertising_id
或者 IDFA/GAID
到测试设备列表中。你可以在 Support -> Test Devices找到内容。转到 SDK Live page 然后从 App 发送测试事件,您可以看到即时的数据如下:
Tenjin 和 GDPR:
作为 GDPR 合规的一部分,使用 Tenjin 的 SDK,您可以选择加入和退出设备/用户,或选择要加入或退出的特定于设备的相关参数。OptOut()
不会向 Tenjin 发送任何 API 请求,我们也不会处理任何事件。
To opt-in/opt-out:
void Start () {
BaseTenjin instance = Tenjin.getInstance("API_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()
将仅发送指定的设备相关参数. OptOutParams()
将发送除指定参数外的所有与设备相关的参数。 请注意,我们需要至少 ip_address
, advertising_id
, developer_device_id
, limit_ad_tracking
, referrer
(Android), 和 iad
(iOS) 来正确地跟踪在 Tenjin 系统中的设备。如果您打算使用 Google,则还需要添加: platform
, os_version
, locale
, device_model
, 和 build_id
.
如果只想使用 OptInParams()
获取与设备相关的特定参数,在下面的样例中, 我们只发送这些设备相关的参数: ip_address
, advertising_id
, developer_device_id
, limit_ad_tracking
, referrer
, 和 iad
:
BaseTenjin instance = Tenjin.getInstance("API_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("API_KEY");
List<string> optOutParams = new List<string> {"locale", "timezone", "build_id"};
instance.OptOutParams(optOutParams);
instance.Connect();
设备相关参数
参数 | 描述 | 平台 | 索引 |
---|---|---|---|
advertising_id | 设备 Advertising ID | All | Android), iOS |
developer_device_id | ID for Vendor | iOS | iOS |
limit_ad_tracking | 开启限制广告追踪 | All | Android), iOS |
platform | 平台 | All | iOS or Android |
referrer | Google Play Install Referrer | Android | Android |
iad | Apple Search Ad parameters | iOS | iOS |
os_version | 操作系统版本 | All | Android, iOS |
device | 设备名称 | All | Android, iOS (hw.machine) |
device_manufacturer | 设备制造商 | Android | Android |
device_model | 设备型号 | All | Android, iOS (hw.model) |
device_brand | 设备品牌 | Android | Android |
device_product | 设备产品 | Android | Android |
device_model_name | device machine | iOS | iOS (hw.model) |
device_cpu | 设备cpu名称 | iOS | iOS (hw.cputype) |
carrier | 运营商 | Android | Android) |
connection_type | 移动数据或 wifi | Android | Android) |
screen_width | 设备屏幕宽度 | Android | Android |
screen_height | 设备屏幕高度 | Android | Android |
os_version_release | 操作系统版本 | All | Android, iOS |
build_id | build ID | All | Android, iOS (kern.osversion) |
locale | 设备区域 | All | Android), iOS |
country | 区域国家 | All | Android), iOS |
timezone | 时区 | All | Android, iOS |
Tenjin 安装/会话集成处理其他服务的深度链接:
如果您使用其他服务产生延迟的深度链接,您可以向 Tenjin 发送这个链接,来处理已经已经打开 Tenjin 归因的深度链接。
using UnityEngine;
using System.Collections;
public class TenjinExampleScript : MonoBehaviour {
// Use this for initialization
void Start () {
BaseTenjin instance = Tenjin.getInstance("API_KEY");
instance.Connect("your_deeplink://path?test=123");
}
}
购买相关事件集成说明:
iOS 内购 IAP 验证
iOS 验证 receipt 需要 transactionId
和 receipt
(signature
将设置为 null
). 对与 receipt
,请确保从 unity 发送Payload
的receipt(以 base64 编码的 ASN.1 receipt)。
重要提示: 如果您有订阅内购(subscription IAP),您需要在, you will need to add your app's shared secret in the Tenjin dashboard添加您 App 的共享密钥(shared secret)。您的 iOS App-Specific Shared Secret 获取路径: iTunes Connect Console > Select your app > Features > In-App Purchases > App-Specific Shared Secret.
Android 内购验证 IAP Validation
Android 的 receipt 验证必须提供 receipt
和 signature
, (transactionId
设置为 to null
).
重要提示: 您需要在 Tenjin dashboard添加 App 的 public key。获取 Base64-encoded RSA public key 的路径为 Google Play Developer Console > Select your app > Development Tools > Services & APIs。
iOS 和 Android 示例:
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 payload = (string)wrapper["Payload"]; // For Apple this will be the base64 encoded ASN.1 receipt
var productId = purchaseEventArgs.purchasedProduct.definition.id;
#if UNITY_ANDROID
var gpDetails = Json.Deserialize(payload) as Dictionary<string, object>;
var gpJson = (string)gpDetails["json"];
var gpSig = (string)gpDetails["signature"];
CompletedAndroidPurchase(productId, currencyCode, 1, lPrice, gpJson, gpSig);
#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("API_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("API_KEY");
instance.Transaction(ProductId, CurrencyCode, Quantity, UnitPrice, TransactionId, Receipt, null);
}
订阅内购 Subscription IAP
重要提示: 如果您有订阅内购,则需要在 Tenjin dashboard添加 App 的 public key。iOS 的 Shared Secret 获取路径为 iTunes Connect Console > Select your app > Features > In-App Purchases > App-Specific Shared Secret。
请注意,您有责任在每个订阅间隔内发送一次订阅交易(例如,对于每月订阅,您需要每月向我们发送1笔交易)。
在下面的示例时间轴中,交易事件仅应在“首次收费”和“续订”事件中发送。在试用期间,请勿将交易事件发送给 Tenjin。Tenjin不 会对重复交易进行重复数据删除。
有关订阅的更多信息,请参阅: Apple documentation on Working with Subscriptions
Tenjin 自定义事件集成说明:
- 在 Unity project 中包含 Assets 文件夹
- 在自定义事件的 projects method 中为命名事件编写以下内容:
Tenjin.getInstance("<API_KEY>").SendEvent("name")
以及需为整数值的命名事件的以下内容:Tenjin.getInstance("<API_KEY>").SendEvent("nameWithValue","value")
- 确保传递的
value
为整数,如果不是整数,则无法被传递。
代码示例:
void MethodWithCustomEvent(){
//event with name
BaseTenjin instance = Tenjin.getInstance ("API_KEY");
instance.SendEvent("name");
//event with name and integer value
instance.SendEvent("nameWithValue", "value");
}
.SendEvent("name")
is for events that are static markers or milestones. This would include things like tutorial_complete
, registration
, or level_1
.
.SendEvent("name", "value")
is for events that you want to do math on a property of that event. For example, ("coins_purchased", "100")
will let you analyze a sum or average of the coins that have been purchased for that event.
Tenjin 延迟深度链接(deferred deeplink)集成说明:
通过 Tenjin 生成的广告活动追踪链接(campaign tracking URLs),有将用户指向 App 特定部分的功能。您可以利用 getDeeplink
获得延迟的深度链接,这里有详细的说明 here.
public class TenjinExampleScript : MonoBehaviour {
// Use this for initialization
void Start () {
BaseTenjin instance = Tenjin.getInstance("API_KEY");
instance.Connect();
instance.GetDeeplink(DeferredDeeplinkCallback);
}
public void DeferredDeeplinkCallback(Dictionary<string, string> data) {
bool clicked_tenjin_link = false;
bool is_first_session = false;
if (data.ContainsKey("clicked_tenjin_link")) {
//clicked_tenjin_link is a BOOL to handle if a user clicked on a tenjin link
clicked_tenjin_link = (data["clicked_tenjin_link"] == "true");
Debug.Log("===> DeferredDeeplinkCallback ---> clicked_tenjin_link: " + data["clicked_tenjin_link"]);
}
if (data.ContainsKey("is_first_session")) {
//is_first_session is a BOOL to handle if this session for this user is the first session
is_first_session = (data["is_first_session"] == "true");
Debug.Log("===> DeferredDeeplinkCallback ---> is_first_session: " + data["is_first_session"]);
}
if (data.ContainsKey("ad_network")) {
//ad_network is a STRING that returns the name of the ad network
Debug.Log("===> DeferredDeeplinkCallback ---> adNetwork: " + data["ad_network"]);
}
if (data.ContainsKey("campaign_id")) {
//campaign_id is a STRING that returns the tenjin campaign id
Debug.Log("===> DeferredDeeplinkCallback ---> campaignId: " + data["campaign_id"]);
}
if (data.ContainsKey("advertising_id")) {
//advertising_id is a STRING that returns the advertising_id of the user
Debug.Log("===> DeferredDeeplinkCallback ---> advertisingId: " + data["advertising_id"]);
}
if (data.ContainsKey("deferred_deeplink_url")) {
//deferred_deeplink_url is a STRING that returns the deferred_deeplink of the campaign
Debug.Log("===> DeferredDeeplinkCallback ---> deferredDeeplink: " + data["deferred_deeplink_url"]);
}
if (clicked_tenjin_link && is_first_session) {
//use the deferred_deeplink_url to direct the user to a specific part of your app
if (String.IsNullOrEmpty(data["deferred_deeplink_url"]) == false) {
}
}
}
}
用于 A/B 测试的 App Subversion 参数 (需要使用 DataVault)
如果您想运行 A/B 测试和差异报告,我们可以使用 appendAppSubversion
方法将数字值附加到您的应用程序版本中。例如,如果您的应用程序版本 1.0.1
设置了 appendAppSubversion: @8888
,报告中将为1.0.1.8888
。
这些数据将在 DataVault 中,您可以通过 subversion 值来运行报告。
BaseTenjin instance = Tenjin.getInstance("<API KEY>");
instance.AppendAppSubversion(8888);
instance.Connect();
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 Object[][] getContents();
}
-keepattributes *Annotation*