The Unity SDK for Tenjin. To learn more about Tenjin and our product offering, please visit https://www.tenjin.com.
-
Please see our Release Notes to see detailed version history of changes.
-
Tenjin Unity SDK supports both iOS and Android.
-
Review the iOS and Android documentation and apply the proper platform settings to your builds.
-
For any issues or support, please contact: support@tenjin.com
-
iOS Notes:
- Xcode 12 requirement, if you’re using Unity iOS SDK v1.12.0 and higher.
- When building iOS, confirm that these frameworks were automatically added to the Xcode build. If any are missing, you will need to add them manually.
- AdServices.framework
- AdSupport.framework
- AppTrackingTransparency.framework
- iAd.framework
- StoreKit.framework
- For AppTrackingTransparency, be sure to update your project
.plist
file and addPrivacy - Tracking Usage Description
(NSUserTrackingUsageDescription) along with the text message you want to display to users. This library is only available in iOS 14.0+. - For Apple Search Ads Attribution support, please be sure to upgrade to v1.12.6+ and add the
AdServices.framework
library. This library is only available in iOS 14.3+.
-
Android Notes:
- If you have another SDK installed which already has Google Play Services installed or uses PlayServicesResolver, you may need to delete duplicate libraries:
/Assets/Plugins/Android/play-services-ads-identifier--*.aar
/Assets/Plugins/Android/play-services-basement---*.aar
- If you are using Tenjin Unity SDK alongside another SDK in Unity version 2019.4.21f1 and higher, and are using Gradle to build the Android App, you might face build errors such as
DuplicateMethodException
etc., or find that referrer install is not working. If that is the case, please do the following:- Remove all the
*.aar
files from theAssets/Plugins/Android
folder excepttenjin.aar
. - Add the following to your
mainTemplate.gradle
file:// Android Resolver Repos Start ([rootProject] + (rootProject.subprojects as List)).each { project -> project.repositories { def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/") maven { url "https://maven.google.com" } maven { url "https://s3.amazonaws.com/moat-sdk-builds" } maven { url 'https://developer.huawei.com/repo/' } mavenLocal() mavenCentral() google() } } // Android Resolver Repos End apply plugin: 'com.android.library' **APPLY_PLUGINS** dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Android Resolver Dependencies Start implementation 'com.android.support:multidex:1.0.3' implementation 'com.google.android.gms:play-services-analytics:{version}' implementation 'com.android.installreferrer:installreferrer:{version}' implementation 'com.huawei.hms:ads-identifier:{version}' implementation 'com.huawei.hms:ads-installreferrer:{version}' androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', { exclude group: 'com.android.support', module: 'support-annotations' }) // Android Resolver Dependencies End **DEPS**}
- Add the following entry to the
gradleTemplate.properties
file:android.useAndroidX=true
- Remove all the
- If you see the following errors on the app initialization, move tenjin.aar file from
/Assets/Plugins/Android/Tenjin/libs
to/Assets/Plugins/Android/
. Also check the Proguard Settings here.
```
AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='setWrapperVersion'
AndroidJavaException: java.lang.ClassNotFoundException: com.tenjin.android.TenjinSDK
```
- If you update SDK to v1.12.9 or higher, we are going to make version 2019.4.21f1 the minimum Unity 3D version. If you prefer to use the older version, please contact us, so we can help you with a customized solution. Furthermore, upgrade the External Dependency Manager for Unity to 1.12.167.
- SDK Integration
- Testing
-
Download the latest Unity SDK from here.
-
Import the
TenjinUnityPackage.unitypackage
into your project:Assets -> Import Package
. -
By default, we have included Google Play Services AAR files as part of our SDK. If you do not plan on using Google Play Services, you can delete these AAR files:
/Assets/Plugins/Android/play-services-*.aar
/Assets/Plugins/Android/installreferrer-*.aar
We have a demo project - tenjin-unity-sdk-demo that demonstrates the integration of tenjin-unity-sdk. You can this project as example to understand how to integrate the tenjin-unity-sdk.
By default, unspecified is the default App Store. Update the app store value to googleplay, if you distribute your app on Google Play Store.
Set your App Store Type value to googleplay
:
BaseTenjin instance = Tenjin.getInstance("<API_KEY>");
instance.SetAppStoreType(AppStoreType.googleplay);
By default, unspecified is the default App Store. Update the app store value to amazon, if you distribute your app on Amazon store.
Set your App Store Type value to amazon
:
BaseTenjin instance = Tenjin.getInstance("<API_KEY>");
instance.SetAppStoreType(AppStoreType.amazon);
Tenjin supports promoting your app on other Android App Stores using the Android OAID. We have the following requirements for integrating OAID libraries. If you plan to release your app outside of Google Play, make sure to implement these OAID libraries.
MSA OAID is an advertising ID for devices manufactured in China that the MSA (Mobile Security Alliance) provides. For integration with the MSA library, download the following oaid_sdk_1.0.25.aar.
Place the oaid_sdk_1.0.25.aar
file in your project's Android libs directory: /Assets/Plugins/Android
Set your App Store Type value to other
:
BaseTenjin instance = Tenjin.getInstance("<API_KEY>");
instance.SetAppStoreType(AppStoreType.other);
For outside of China, you can collect OAID using the library provided by Huawei. For integration with the Huawei OAID library, download the following Huawei AAR file: huawei-ads-identifier.aar. If your app is in the Huawei App Gallery, download and add the Huawei Install Referrer file: huawei-ads-installreferrer.aar.
Place the Huawei files in your project's Android libs directory: /Assets/Plugins/Android
Set your App Store Type value to other
:
BaseTenjin instance = Tenjin.getInstance("<API_KEY>");
instance.SetAppStoreType(AppStoreType.other);
-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*
If you are using Huawei libraries, you can to use these settings:
-keep class com.huawei.hms.ads.** { *; }
-keep interface com.huawei.hms.ads.** { *; }
- Get your
<API_KEY>
from your Tenjin dashboard. - In your project's first
Start()
method, add the following line of code. Also add toOnApplicationPause()
if you want to send sessions data when a user resumes using the app from the background.
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("<API_KEY>");
// Sends install/open event to Tenjin
instance.Connect();
}
}
NOTE: Please ensure you implement this code on every Start()
, not only on the first app open of the app. If we notice that you don't follow our recommendation, we can't give you the proper support or your account might be suspended.
We support three app store options,
- googleplay
- amazon
- other
By default, unspecified is the default App Store. If you are publishing in a specific App Store, update the app store value to the appropriate app store value. The app store value other is used for Huawei AppGallery and other app stores:
AndroidManifest.xml
:
<meta-data
android:name="TENJIN_APP_STORE"
android:value="{{SET_APP_STORE_TYPE_VALUE}}" />
SetAppStoreType()
:
BaseTenjin instance = Tenjin.getInstance("<API_KEY>");
instance.SetAppStoreType(AppStoreType.{{SET_APP_STORE_TYPE_VALUE}});
-
Starting with iOS 14, you have the option to show the initial ATTrackingManager permissions prompt and selection to opt in/opt out users.
-
If the device doesn't accept tracking permission, IDFA will become zero. If the device accepts tracking permission, the
Connect()
method will send the IDFA to our servers. -
You can also still call Tenjin
connect()
, without using ATTrackingManager. ATTrackingManager permissions prompt is not obligatory until the early spring of 2021.
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("API_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
}
}
To comply with Apple’s ATT guidelines, you must provide a description for the ATT permission prompt, then implement the permission request in your application.
Note: You must implement the permission request before serving ads in your game.
Apple requires a description for the ATT permission prompt. You need to set the description with the NSUserTrackingUsageDescription
key in the Info.plist
file of your Xcode project. You have to provide a message that informs the user why you are requesting permission to use device tracking data:
- In your Xcode project navigator, open the
Info.plist
file. - Click the add button (+) beside any key in the property list editor to create a new property key.
- Enter the key name
NSUserTrackingUsageDescription
. - Select a string value type.
- Enter the app tracking transparency message in the value field. Some examples include:
- "We will use your data to provide a better and personalized ad experience."
- "We try to show ads for apps and products that will be most interesting to you based on the apps you use, the device you are on, and the country you are in."
- "We try to show ads for apps and products that will be most interesting to you based on the apps you use."
Note: Apple provides specific app store guidelines that define acceptable use and messaging for all end-user facing privacy-related features. Tenjin does not provide legal advice. Therefore, the information on this page is not a substitute for seeking your own legal counsel to determine the legal requirements of your business and processes, and how to address them.
As part of SKAdNetwork, we created wrapper methods for registerAppForAdNetworkAttribution()
and updateConversionValue(_:)
.
Our methods will register the equivalent SKAdNetwork methods and also send the conversion values to our servers.
updateConversionValue(_:)
6 bit value should correspond to the in-app event and shouldn't be entered as binary representation but 0-63 integer. Our server will reject any invalid values.
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("API_KEY");
#if UNITY_IOS
// Registers SKAdNetwork app for attribution
instance.RegisterAppForAdNetworkAttribution();
// Sends install/open event to Tenjin
instance.Connect();
// Sets SKAdNetwork Conversion Value
// You will need to use a value between 0-63 for <YOUR 6 bit value>
instance.UpdateConversionValue(<your 6 bit value>);
#elif UNITY_ANDROID
// Sends install/open event to Tenjin
instance.Connect();
#endif
}
}
To specify Tenjin as the destination for your SK Ad Network postbacks, do the following:
- Select
Info.plist
in the Project navigator in Xcode. - Click the Add button (+) beside a key in the property list editor and press Return.
- Type the key name
NSAdvertisingAttributionReportEndpoint
. - Choose String from the pop-up menu in the Type column.
- Enter
https://tenjin-skan.com
These steps are adapted from Apple's instructions at https://developer.apple.com/documentation/storekit/skadnetwork/configuring_an_advertised_app.
NOTE: If you are using AppLovin MAX for mediation, their Unity SDK will overwrite any value you entered for NSAdvertisingAttributionReportEndpoint
with their own URL during the build process. You should be able to set the NSAdvertisingAttributionReportEndpoint to https://tenjin-skan.com
in XCode after it's been overwritten in the following process.
-
Export the iOS app following the steps Unity outlines here.
-
After you build the iOS app, you should have an XCode project that has this structure: https://docs.unity3d.com/Manual/StructureOfXcodeProject.html
-
Navigate to the
Info.plist
file in the XCode project to manually change the NSAdvertisingAttributionReportEndpoint tohttps://tenjin-skan.com
. Otherwise, you can ask your AppLovin account manager to set up forwarding the postbacks to us.
As part of GDPR compliance, with Tenjin's SDK you can opt-in, opt-out devices/users, or select which specific device-related params to opt-in or opt-out. OptOut()
will not send any API requests to Tenjin, and we will not process any events.
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;
}
-
To opt-in/opt-out specific device-related parameters, you can use the
OptInParams()
orOptOutParams()
. -
OptInParams()
will only send device-related parameters that are specified.OptOutParams()
will send all device-related parameters except ones that are specified. -
Kindly note that we require the following parameters to properly track devices in Tenjin's system. If one of these mandatory parameters is missing, the event will not be processed or recorded.
- For Android,
advertising_id
- For iOS
developer_device_id
- For Android,
-
If you are targeting IMEI and/or OAID Ad Networks for Android, add:
imei
oaid
-
If you intend to use Google Ad Words, you will also need to add:
platform
os_version
locale
device_model
build_id
If you want to only get specific device-related parameters, use OptInParams()
. In example below, we will only these device-related parameters: ip_address
, advertising_id
, developer_device_id
, limit_ad_tracking
, referrer
, and 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();
If you want to send ALL parameters except specific device-related parameters, use OptOutParams()
. In the example below, we will send ALL device-related parameters except: locale
, timezone
, and build_id
parameters.
BaseTenjin instance = Tenjin.getInstance("API_KEY");
List<string> optOutParams = new List<string> {"locale", "timezone", "build_id"};
instance.OptOutParams(optOutParams);
instance.Connect();
Param | Description | Platform | Reference |
---|---|---|---|
ip_address | IP Address | All | |
advertising_id | Device Advertising ID | All | Android, iOS |
developer_device_id | ID for Vendor | iOS | iOS |
oaid | Open Advertising ID | Android | Android |
imei | Device IMEI | Android | Android |
limit_ad_tracking | limit ad tracking enabled | All | Android, iOS |
platform | platform | All | iOS or Android |
referrer | Google Play Install Referrer | Android | Android |
iad | Apple Search Ad parameters | iOS | iOS |
os_version | operating system version | All | Android, iOS |
device | device name | All | Android, iOS (hw.machine) |
device_manufacturer | device manufactuer | Android | Android |
device_model | device model | All | Android, iOS (hw.model) |
device_brand | device brand | Android | Android |
device_product | device product | Android | Android |
device_model_name | device machine | iOS | iOS (hw.model) |
device_cpu | device cpu name | iOS | iOS (hw.cputype) |
carrier | phone carrier | Android | Android |
connection_type | cellular or wifi | Android | Android |
screen_width | device screen width | Android | Android |
screen_height | device screen height | Android | Android |
os_version_release | operating system version | All | Android, iOS |
build_id | build ID | All | Android, iOS (kern.osversion) |
locale | device locale | All | Android, iOS |
country | locale country | All | Android, iOS |
timezone | timezone | All | Android, iOS |
iOS receipt validation requires transactionId
and receipt
(signature
will be set to null
). For receipt
, be sure to send the receipt Payload
(the base64 encoded ASN.1 receipt) from Unity.
IMPORTANT: If you have subscription IAP, you will need to add your app's shared secret in the Tenjin dashboard. You can retrieve your iOS App-Specific Shared Secret from the iTunes Connect Console > Select your app > Features > In-App Purchases > App-Specific Shared Secret.
Android receipt validation requires receipt
and signature
are required (transactionId
is set to null
).
IMPORTANT: You will need to add your app's public key in the Tenjin dashboard. You can retrieve your Base64-encoded RSA public key from the Google Play Developer Console > Select your app > Development Tools > Services & APIs. Please note that for Android, we currently only support IAP transactions from Google Play.
In the example below, we are using the widely used MiniJSON library for JSON deserializing.
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);
}
Disclaimer: If you are implementing purchase events on Tenjin for the first time, make sure to verify the data with other tools you’re using before you start scaling up your user acquisition campaigns using purchase data.
-
You are responsible to send a subscription transaction one time during each subscription interval (i.e., For example, for a monthly subscription, you will need to send us 1 transaction per month). In the example timeline below, a transaction event should only be sent at the "First Charge" and "Renewal" events. During the trial period, do not send Tenjin the transaction event.
-
Tenjin does not de-dupe duplicate transactions.
-
If you have iOS subscription IAP, you will need to add your app's public key in the Tenjin dashboard. You can retrieve your iOS App-Specific Shared Secret from the iTunes Connect Console > Select your app > Features > In-App Purchases > App-Specific Shared Secret.
-
For more information on iOS subscriptions, please see: Apple documentation on Working with Subscriptions
-
For more information on Android subscriptions, please see: Google Play Billing subscriptions documentation
IMPORTANT: Limit custom event names to less than 80 characters. Do not exceed 500 unique custom event names.
- Include the Assets folder in your Unity project
- In your projects' method for the custom event, write the following for a named event:
Tenjin.getInstance("<API_KEY>").SendEvent("name")
and the following for a named event with an integer value:Tenjin.getInstance("<API_KEY>").SendEvent("nameWithValue","value")
- Make sure
value
passed is an integer. Ifvalue
is not an integer, your event will not be passed.
Here's an example of the code:
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 are purchased for that event.
Tenjin supports the ability to direct users to a specific part of your app after a new attributed installation via Tenjin's campaign tracking URLs. You can utilize the GetDeeplink
method and callback to access the deferred deeplink through the data object.
Tenjin offers server-to-server integration, which is a paid feature. If you want to access to the documentation, please send email to support@tenjin.com and discuss the pricing.
If you are running A/B tests and want to report the differences, we can append a numeric value to your app version using the AppendAppSubversion()
method. For example, if your app version 1.0.1
, and set AppendAppSubversion(8888)
, it will report app version as 1.0.1.8888
.
This data will appear within DataVault, where you will be able to run reports using the app subversion values.
BaseTenjin instance = Tenjin.getInstance("<API KEY>");
instance.AppendAppSubversion(8888);
instance.Connect();
Tenjin supports the ability to integrate with the Impression Level Ad Revenue (ILRD) feature from,
- AppLovin
- IronSource
- HyperBid
- AdMob
This feature allows you to receive events which correspond to your ad revenue which is affected by each advertisement show to a user. To enable this feature, follow the below instructions.
You can verify if the integration is working through our Live Test Device Data Tool. Add your advertising_id
or IDFA/GAID
to the list of test devices. You can find this under Support -> Test Devices. Go to the SDK Live page and send the test events from your app. You should see live events come in: