The Tenjin iOS SDK allows users to track events and installs in their iOS apps. 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.
- For Unity-specific instructions, please visit https://github.com/tenjin/tenjin-unity-sdk.
- For any issues or support, please contact: [email protected]
- Xcode 13 requirement, if you’re using iOS SDK v1.12.17 and higher.
- 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+.
- SDK Integration
- Purchase Events
- Custom Events
- Deferred Deeplink
- Server-to-server integration
- App Subversion
- Impression Level Ad Revenue Integration
- Attribution Info
- Customer User ID
If you use pods, add pod 'TenjinSDK'
to your Podfile
then run pod install
and skip to step 5.
-
Download the latest SDK release here.
-
Drag
libTenjinSDK.a
andTenjinSDK.h
to your project under build phases -> "Link Binary With Libraries". Note: If you are testing with 32-bit iOS Simulator devices (i386), you will need to uselibTenjinSDKUniversal.a
instead oflibTenjinSDK.a
. -
Add the following Frameworks to your project:
AdServices.framework
AdSupport.framework
AppTrackingTransparency.framework
iAd.framework
StoreKit.framework
-
Go to your AppDelegate file, by default
AppDelegate.m
, and#import "TenjinSDK.h"
. -
Get your
SDK_KEY
from your app page. Note:SDK_KEY
is unique for each of your app. You can create up to 3 keys for the same app. -
In your
didFinishLaunchingWithOptions
method add:[TenjinSDK initialize:@"<SDK_KEY>"]; [TenjinSDK connect];
-
To enable Tenjin iOS SDK debug logs add:
[TenjinSDK debugLogs];
Here's an example of what your integration in Objective-C projects should look like in your
AppDelegate.m
file:#import "TenjinSDK.h" @implementation TJNAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [TenjinSDK initialize:@"<SDK_KEY>"]; [TenjinSDK connect]; //All your other stuff ... }
-
Add Objective-C Bridging Header file for swift projects,
- Create a header file
- File -> New -> File -> “Sources”
- Choose “Header” File - > Click Next
- The header file name should “YourProjectName-Bridging-Header” -> Under “Targets” -> Select the app target -> Click "Next"
- In the header file - “YourProjectName-Bridging-Header.h”
- Add - `#import "TenjinSDK.h"`
- Go to the app target and under “Build Settings”
- Go to the section “Swift Compiler - General”
- Go to the sub-section “Objective-C Bridging Header” and drag the header file - “YourProjectName-Bridging-Header.h” to the field.
- Create a header file
-
Get your
SDK_KEY
from your Tenjin Organization tab. -
In your
didFinishLaunchingWithOptions
method add:TenjinSDK.getInstance("<SDK_KEY>") TenjinSDK.connect()
If you are using Swift 5, use the
getInstance()
method instead ofinit()
. See our sample Swift app. -
To enable Tenjin iOS SDK debug logs add:
TenjinSDK.debugLogs();
Here's an example of what your integration in Swift projects should look like in your
AppDelegate.swift
file:func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. TenjinSDK.getInstance("<SDK_KEY>") TenjinSDK.connect() return true }
NOTE: Please ensure you implement this code on every didFinishLaunchingWithOptions
, 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 under suspension.
In the step 7, you can also try alternate initialization to handle deep links from other services. If you use other services to produce deferred deep links, you can pass Tenjin those deep links to handle the attribution logic with your Tenjin enabled deep links.
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
//get your deep link from your other 3rd party service
NSURL *url = [NSURL withString: @"your_deep_link"];
//if you have a deep link that's generated from a third party service then pass it to tenjin to handle the attribution of deep links holistically
if(url) {
[TenjinSDK connectWithDeferredDeeplink:url];
}
else{
[TenjinSDK connect];
}
//All your other stuff
//...
}
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:
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, only in below iOS 14. ATTrackingManager permissions prompt is obligatory from the end of spring 2021.
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
[TenjinSDK connect];
}];
} else {
[TenjinSDK connect];
}
}
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 a wrapper method for updatePostbackConversionValue(_:)
.
Our method will register the equivalent SKAdNetwork methods and also send the conversion values to our servers.
updatePostbackConversionValue(\_:)
6 bit value should correspond to the in-app event and shouldn’t be entered as binary representation but 0-63 integer. Please refer to this page for how to implement conversion values.
As of iOS 16.1, which supports SKAdNetwork 4.0, you can now send coarseValue
(String, with possible variants being "low", "medium" or "high") and lockWindow
(Boolean) as parameters on the update postback method:
updatePostbackConversionValue(_ conversionValue: Integer, coarseValue: String)
updatePostbackConversionValue(_ conversionValue: Integer, coarseValue: String, lockWindow: Bool)
-
For iOS version 16.1+ which supports SKAdNetwork 4.0, you can call this method as many times as you want and can make the conversion value lower or higher than the previous value.
-
For iOS versions lower than 16.1 supporting SKAdnetWork versions lower than 4.0, you can call this method and our SDK will automatically detect the iOS version and update
conversionValue
only.
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK connect];
//
// This will call [SKAdNetwork updatePostbackConversionValue: <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 updatePostbackConversionValue: <YOUR 6 bit value>];
// For iOS 16.1+ (SKAN 4.0)
[TenjinSDK updatePostbackConversionValue: <YOUR 6 bit value> coarseValue:@"medium"];
[TenjinSDK updatePostbackConversionValue: <YOUR 6 bit value> coarseValue:@"medium" lockWindow:true];
}
}
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 an adaption from Apple's instructions at https://developer.apple.com/documentation/storekit/skadnetwork/configuring_an_advertised_app.
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:
#import "TenjinSDK.h"
@implementation TJNAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TenjinSDK initialize:@"<SDK_KEY>"];
if ([self checkOptInValue]) {
[TenjinSDK optIn];
}
else {
[TenjinSDK optOut];
}
[TenjinSDK connect];
//All your other stuff
//..
}
-(BOOL) checkOptInValue
{
// check opt-in value
// return YES; // if user opted-in
return NO;
}
To opt-in/opt-out specific device-related parameters, you can use the OptInParams()
or OptOutParams()
. 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 parameter to properly track devices in Tenjin's system. If the mandatory parameter is missing, the event will not be processed or recorded.
developer_device_id
If you intend to use Google Ads, you will also need to add: platform
, os_version
, locale
, device_model
, and 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
, and iad
:
[TenjinSDK initialize:@"<SDK_KEY>"];
NSArray *optInParams = @[@"ip_address", @"advertising_id", @"developer_device_id", @"limit_ad_tracking", @"iad"];
[TenjinSDK optInParams:optInParams];
[TenjinSDK 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.
[TenjinSDK initialize:@"<SDK_KEY>"];
NSArray *optOutParams = @[@"country", @"timezone", @"language"];
[TenjinSDK optOutParams:optOutParams];
[TenjinSDK connect];
Param | Description | Reference |
---|---|---|
ip_address | IP Address | |
advertising_id | Device Advertising ID | iOS |
developer_device_id | ID for Vendor | iOS |
limit_ad_tracking | limit ad tracking enabled | iOS |
platform | platform | iOS |
iad | Apple Search Ad parameters | iOS |
os_version | operating system version | iOS |
device | device name | iOS (hw.machine) |
device_model | device model | iOS (hw.model) |
device_model_name | device machine | iOS (hw.model) |
device_cpu | device cpu name | iOS (hw.cputype) |
os_version_release | operating system version | iOS |
build_id | build ID | iOS (kern.osversion) |
locale | device locale | iOS |
country | locale country | iOS |
timezone | timezone | iOS |
Pass (SKPaymentTransaction *) transaction
and (NSData *)receipt
object, after the verification of the purchase, and then you can pass SKPaymentTransactionStatePurchased
to Tenjin for the transaction which was purchased:
//Get the NSData receipt
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
//Pass the transaction and the receiptData to Tenjin
[TenjinSDK transaction: transaction andReceipt: receiptData];
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.
IMPORTANT: If you have 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.
Kindly note that 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.
For more information on subscriptions, please see: Apple documentation on Working with Subscriptions
IMPORTANT: DO NOT SEND CUSTOM EVENTS BEFORE THE CONNECT/INITIALIZATION event (above). The initialization must come before sending any custom events.
IMPORTANT: Limit custom event names to less than 80 characters. Do not exceed 500 unique custom event names.
You can also use the Tenjin SDK to pass a custom event:
sendEventWithName: (NSString *)eventName
and
You can use these to pass Tenjin custom interactions with your app to tie this to user level cost from each acquisition source that you use through Tenjin's platform. Here are some examples of usage:
//send a particular event for when someone swipes on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right"];
Custom events can also pass an NSString
eventValue
. Tenjin will use this eventValue
as a count or sum for all custom events with the same eventName
. The eventValue
MUST BE AN INTEGER. If the eventValue
is not an integer, we will not send the event.
//send a particular event for when someone swipes and an event value on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right" andEventValue:@"1"];
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.
Tenjin offers server-to-server integration. If you want to access to the documentation, please send email to [email protected].
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 as 1.0.1.8888
.
This data will appear within DataVault, where you will be able to run reports using the app subversion values.
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK appendAppSubversion:@8888];
[TenjinSDK connect];
Tenjin supports the ability to integrate with the Impression Level Ad Revenue (ILRD) feature from,
- AppLovin
- Unity LevelPlay
- HyperBid
- AdMob
- TopOn
This feature allows you to receive events which correspond to your ad revenue that is affected by each advertisement show to a user. To enable this feature, follow the below instructions.
Tenjin supports retrieving of attributes, which are required for developers to get analytics installation id (previously known as tenjin reference id). This parameter can be used when there is no advertising id.
You can set and get customer user id to send as a parameter on events.
setCustomerUserId(userId: "user_id")
getCustomerUserId()
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK setCustomerUserId:@"user_id"];
userId = [TenjinSDK getCustomerUserId];