# Mobile Measurement Partner (MMP) SDK for iOS

Source: https://tenjin.com/docs/mmp-sdk-ios/

Integrate using LLMs (AI) – Use following prompt:

Add Tenjin SDK to my project using: [https://raw.githubusercontent.com/tenjin/sdk-llm-guides/main/guides/ios/llm-guide.md](<https://raw.githubusercontent.com/tenjin/sdk-llm-guides/main/guides/ios/llm-guide.md>)


### Summary


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](<https://github.com/tenjin/tenjin-ios-sdk/blob/master/RELEASE_NOTES.md>) 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: support@tenjin.com


### Notes:


- 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 add ` Privacy - Tracking Usage Description ` [(NSUserTrackingUsageDescription)](<https://developer.apple.com/documentation/bundleresources/information_property_list/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](<https://developer.apple.com/documentation/iad/setting_up_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


### Cocoapods


If you use pods, add ` pod 'TenjinSDK' ` to your ` Podfile ` then run ` pod Install ` and skip to step 4.


### Swift Package Manager


If you use SPM, add Tenjin’s SDK package through Xcode with this repository [here][43] and skip to step 4.


1. Download the latest SDK release [here][21].

2. Drag ` TenjinSDK.xcframework ` and ` TenjinSDK.h ` to your project under build phases -> “Link Binary With Libraries”.

3. Include the linker flags ` -ObjC ` under your Build Settings


### Steps for Objective-C projects


4. Go to your AppDelegate file, by default ` AppDelegate.m `, and ` #import "TenjinSDK.h" `.

5. Get your ` SDK_KEY ` from the SDK tab of your app page (CONFIGURE > Apps > select your app > SDK). Note: ` SDK_KEY ` is unique for each of your app. You can create up to 3 keys for the same app.


6. In your ` didFinishLaunchingWithOptions ` method add:


Objective-C

```
[TenjinSDK initialize:@""];
[TenjinSDK connect];
```


7. To enable Tenjin iOS SDK debug logs add:


Objective-C

```
[TenjinSDK debugLogs];
```


Here’s an example of what your integration in Objective-C projects should look like in your ` AppDelegate.m ` file:


Objective-C

```
#import "TenjinSDK.h"

@implementation TJNAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [TenjinSDK initialize:@"<SDK_KEY>"];
    [TenjinSDK connect];

    //All your other stuff
    ...
}
```


### Steps for Swift projects


4. Add Objective-C Bridging Header file for swift projects, If your project does not already have a bridging header, create one:

1. Create a header file

1. File -> New -> File -> “Sources”

2. Choose “Header” File – > Click Next

3. The header file name should “YourProjectName-Bridging-Header” – Under “Targets” -> Select the app target -> Click Next

2. In the header file – “YourProjectName-Bridging-Header.h”

1. Add the following: ` #import "TenjinSDK.h" `

2. Go to the app target and under “Build Settings”

1. Go to the section “Swift Compiler – General”

2. Go to the sub-section “Objective-C Bridging Header” and drag the header file – “YourProjectName-Bridging-Header.h” to the field.

5. Get your ` SDK_KEY ` from the SDK tab of your app page (CONFIGURE > Apps > select your app > SDK). Note: ` SDK_KEY ` is unique for each of your app. You can create up to 3 keys for the same app.


6. a. In your ` didFinishLaunchingWithOptions ` method add:


Swift

```
TenjinSDK.getInstance("")
TenjinSDK.connect()
```


If you are using Swift 5, use the getInstance() method instead of init(). See our [sample Swift app](<https://github.com/tenjin/tenjin-ios-sdk-swift-demo>)


7. To enable Tenjin iOS SDK debug logs add:


Swift

```
TenjinSDK.debugLogs();
```


Here’s an example of what your integration in Swift projects should look like in your ` AppDelegate.swift ` file:


Swift

```
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.


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.


Objective-C

```
#import "TenjinSDK.h"

@implementation TJNAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    [TenjinSDK init:@"<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](<https://www.tenjin.io/dashboard/sdk_diagnostics>). Add your ` advertising_id ` or ` IDFA/GAID ` to the list of test devices. You can find this under Support -\> [Test Devices](<https://www.tenjin.io/dashboard/debug_app_users>). Go to the [Live Event Tool page](<https://www.tenjin.io/dashboard/sdk_diagnostics>) and send the test events from your app. You should see live events come in:


### Tenjin initialization with ATTrackingManager


Starting with iOS 14, you have the option to show the initial [ATTrackingManager](<https://docs.tenjin.com/>) 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. You can choose not to implement ATT if you don’t intend to access or pass the IDFA for any users to Tenjin.


Objective-C

```
#import "TenjinSDK.h"

@implementation TJNAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    [TenjinSDK init:@"<SDK_KEY>"];

    if (@available(iOS 14, *)) {
        [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
            [TenjinSDK connect];
        }];
    } else {
        [TenjinSDK connect];
    }
}
```


### Displaying an ATT permission prompt


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.


### Configuring a user tracking description


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][24] 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.


### SKAdNetwork and Conversion value


As part of [SKAdNetwork](<https://developer.apple.com/documentation/storekit/skadnetwork>), we created wrapper method for [` updatePostbackConversionValue(_:) `](<https://developer.apple.com/documentation/storekit/skadnetwork/3919928-updatepostbackconversionvalue>). Our method will register the equivalent SKAdNetwork methods and also send the Conversion values to our servers.


` updatePostbackConversionValue(\_:) ` you will provide an integer between 0 and 63 (decimal value, not binary). This value should directly reflect an in-app event or user milestone based on the specific Conversion value strategy you establish for your app. We strongly recommend consulting [this][25] page o plan your Conversion value implementation before coding this logic.


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.


Objective-C

```
#import "TenjinSDK.h"

@implementation TJNAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [TenjinSDK initialize:@"<SDK_KEY>"];
    [TenjinSDK connect];

    //
    // This will call [SKAdNetwork updatePostbackConversionValue: <Integer between 0 and 63>]
    // and also send conversion value to our servers.
    //
    // You will need to use a value between 0-63.
    //
    [TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63>];

    // For iOS 16.1+ (SKAN 4.0)
    [TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63> coarseValue:@"medium"];
    [TenjinSDK updatePostbackConversionValue:<Integer between 0 and 63> coarseValue:@"medium" lockWindow:true];
}

@end
```


### SKAdNetwork and iOS 15+ Advertiser Postbacks


To specify Tenjin as the destination for your [SK Ad Network postbacks][26], do the following:


1. Select ` Info.plist ` in the Project navigator in Xcode.

2. Click the Add button (+) beside a key in the property list editor and press Return.

3. Type the key name ` NSAdvertisingAttributionReportEndpoint `.

4. Choose String from the pop-up menu in the Type column.

5. Enter ` https://tenjin-skan.com `


These steps are an adaption from Apple’s instructions at [here](<https://developer.apple.com/documentation/storekit/configuring-an-advertised-app>).


### GDPR


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:


Objective-C

```
#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: ` advertising_id `, ` developer_device_id `, ` platform `, ` os_version `,` app_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 `, and ` limit_ad_tracking `


Objective-C

```
[TenjinSDK initialize:@"<SDK_KEY>"];

NSArray *optInParams = @[@"ip_address", @"advertising_id", @"developer_device_id", @"limit_ad_tracking"];
[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.


Objective-C

```
[TenjinSDK initialize:@"<SDK_KEY>"];

NSArray *optOutParams = @[@"country", @"timezone", @"language"];
[TenjinSDK optOutParams:optOutParams];

[TenjinSDK connect];
```


### Opt in/out using CMP


You can automatically opt in or opt out using your CMP consents (purpose 1) which are already saved in the user’s device. The method returns a boolean to let you know if it’s opted in or out.


` optInOutUsingCMP() `


Objective-C

```
[TenjinSDK initialize:@"<SDK_KEY>"];
optInOut = [TenjinSDK optInOutUsingCMP]; 
```


### Device-Related Parameters


| Param | Description |
| --- | --- |
| ip_address | IP Address |
| advertising_id | Device Advertising ID |
| developer_device_id | ID for Vendor |
| limit_ad_tracking | limit ad tracking enabled |
| platform | platform |
| os_version | operating system version |
| device | device name |
| device_model | device model |
| device_model_name | device machine |
| device_cpu | device cpu name |
| os_version_release | operating system version |
| build_id | build ID |
| locale | device locale |
| country | locale country |
| timezone | timezone |


## Purchase Events


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:


Objective-C

```
//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];
```


## StoreKit 2 IAP


StoreKit 2 is a Swift-only API. For apps using StoreKit 2, you can extract the JWS representation and transaction details:


Objective-C

```
import StoreKit

func handlePurchase(_ result: VerificationResult<Transaction>) async {
    switch result {
    case .verified(let transaction):
        // Get the JWS representation (SK2 receipt)
        let jwsRepresentation = transaction.jwsRepresentation

        // Extract transaction details
        let productId = transaction.productID
        let transactionId = String(transaction.id)
        let price = transaction.price ?? Decimal(0)
        let currencyCode = transaction.currency?.identifier ?? "USD"

        // Send to Tenjin
        TenjinSDK.transaction(
            withProductName: productId,
            andCurrencyCode: currencyCode,
            andQuantity: transaction.purchasedQuantity,
            andUnitPrice: NSDecimalNumber(decimal: price),
            andTransactionId: transactionId,
            andBase64Receipt: jwsRepresentation
        )

        await transaction.finish()

    case .unverified(_, _):
        // Handle unverified transaction
        break
    }
}
```


(Flexible App Store Commission setup) Choose between 0%, 15% and 30% App Store’s revenue commission via our new setup. The steps are –


- Go to CONFIGURE –> Apps

- Click on the app you want to change it for

- Under the ‘App Store Commission’ section click ‘Edit’

- Choose 30%, 15% or 0% as your desired app store commission.

- Select the start date and end date (Or you can keep the end date blank if you dont want an end date)

- Click Save (note: the commission can be applied only to dates moving forward and not historical dates. So please set the start date from the date you make the change and forward)


## Subscription IAP


IMPORTANT: If you have subscription IAP, you will need to add your app’s App-Specific Shared Secret in the [Tenjin dashboard](<https://www.tenjin.io/dashboard/apps>) (Settings tab of your app page, under IAP Validation). You can retrieve your iOS App-Specific Shared Secret from the [iTunes Connect Console](<https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/887212194/addons>) \> Select your app \> App Information \> 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.


For more information on subscriptions, please see: [Apple documentation on Working with Subscriptions](<https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html>)


## Custom Events


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:


Objective-C

```
//send a particular event for when someone swipes on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right"];
```


Custom events can also pass an ` NSInteger ` ` 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.


Objective-C

```
//send a particular event for when someone swipes and an event value on a part of your app
[TenjinSDK sendEventWithName:@"swipe_right" andEventValue:@"1"];
```


## Server-to-server integration


Tenjin offers [server-to-server integration](<https://docs.tenjin.com/docs/server-to-server-s2s>). This allows you to send your Install and post-Install events directly from your servers to Tenjin servers without needing an SDK integration.


## App Subversion parameter for A/B Testing (requires DataVault)


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.


Objective-C

```
[TenjinSDK initialize:@""];
[TenjinSDK appendAppSubversion:@8888];
[TenjinSDK connect];
```


## Impression Level Ad Revenue Integration


Tenjin supports the ability to integrate with the Impression Level Ad Revenue (ILRD) feature from the mediation providers below. Each method receives the impression payload from the mediation callback as a JSON string; follow the linked guide for the full setup of each provider.


| Provider | Method | Setup guide |
| --- | --- | --- |
| AppLovin MAX | ` [TenjinSDK appLovinImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-applovin-max/>) |
| Unity LevelPlay | ` [TenjinSDK ironSourceImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-unity-levelplay/>) |
| AdMob | ` [TenjinSDK adMobImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-admob/>) |
| HyperBid | ` [TenjinSDK hyperBidImpressionFromJSON:] ` |  |
| TopOn | ` [TenjinSDK topOnImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-topon/>) |
| CAS | ` [TenjinSDK casImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-cas/>) |
| TradPlus | ` [TenjinSDK tradPlusImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-tradplus/>) |
| CloudX | ` [TenjinSDK cloudXImpressionFromJSON:] ` | [Guide](<https://tenjin.com/docs/ios-cloudx/>) |
| Other providers | ` [TenjinSDK customImpressionFromJSON:] ` | See [Custom mediation](<https://github.com/tenjin/tenjin-ios-sdk#custom-mediation>) |


This feature allows you to receive events which correspond to your ad revenue that is affected by each advertisement show to a user. Access to the full documentation is [here](<https://tenjin.com/docs/category/ad-revenue/>).


## Custom mediation


If your mediation provider is not on the list above, you can report impressions with the generic custom mediation method, available since v1.17.1. Pass a JSON object string with your impression data. Required fields are ` network_name `, ` currency `, and either ` revenue_decimal ` (revenue for this impression) or ` revenue_cpm ` (revenue per 1,000 impressions); the full list of accepted fields is in the [ILRD API documentation](<https://tenjin.com/docs/impression-level-revenue-data-api-s2s/>). Impressions sent this way are reported under the ` custom ` mediation source, with ` ad_revenue_mediation ` and the device parameters set automatically by the SDK.


Objective-C

```
NSString *impressionJSON = @"{"
    "\"network_name\":\"my_network\","
    "\"mediation_country\":\"US\","
    "\"currency\":\"USD\","
    "\"ad_unit_id\":\"my_ad_unit_id\","
    "\"ad_format\":\"banner\","
    "\"revenue_decimal\":0.001,"
    "\"precision\":\"BID\","
    "\"creative_id\":\"my_creative\","
    "\"placement\":\"my_placement\","
    "\"network_placement\":\"my_network_placement\","
    "\"auction_id\":\"my_auction_id\""
"}";
[TenjinSDK customImpressionFromJSON:impressionJSON];
```


## LiveOps Campaigns


Tenjin supports retrieving of user Attribution information, like sourcing Ad Network and campaign, from the SDK. This will allow developers to collect and analyze user-level Attribution data in real-time. Here are the possible use cases using Tenjin LiveOps Campaigns:


- If you have your own data anlytics tool, S2S callback will allow you to tie the Attribution data to your in-game data per device level.

- Show different app content depending on where the user comes from. For example, if user A is attributed to organic and user B is attributed to Meta and user B is likely to be more engaged with your app, then you want to show a special in-game offer after the user installs the app. If you want to discuss more specific use cases, please write to support@tenjin.com.


Details on using LiveOps can be found [here](<https://tenjin.com/docs/liveops-campaigns/>).


## Customer User ID


You can set and get customer user id to send as a parameter on events.


` setCustomerUserId(userId: "user_id") ` ` getCustomerUserId() `


Objective-C

```
[TenjinSDK initialize:@"<SDK_KEY>"];
[TenjinSDK setCustomerUserId:@"user_id"];
userId = [TenjinSDK getCustomerUserId]; 
```


## Analytics Installation ID


You can get the analytics id which is generated randomly and saved in the local storage of the device. ` getAnalyticsInstallationId() `


Objective-C

```
[TenjinSDK initialize:@""];
analyticsId = [TenjinSDK getAnalyticsInstallationId]; 
```


## User Profile – LiveOps Metrics


The Tenjin SDK automatically tracks user engagement metrics to help you understand player behavior and lifetime value. These metrics are collected automatically and can be accessed programmatically.


### Automatic Tracking


The SDK automatically tracks:


- Session metrics: Session count, duration, first/last Session dates

- In-App Purchases (IAP): Transaction count, revenue by currency, purchased product IDs

- Ad Revenue (ILRD): Impression-level revenue from supported ad networks


### Retrieving User Profile Data


#### Get Full Profile Object


Returns a ` TJNUserProfileData ` object with all metrics:


Objective-C

```
TJNUserProfileData *profile = [TenjinSDK getUserProfile];

// Session metrics
NSInteger sessionCount = profile.sessionCount;
long long totalTime = profile.totalSessionTime;
long long avgLength = profile.averageSessionLength;
long long lastSession = profile.lastSessionLength;
long long currentSession = profile.currentSessionDuration;
NSDate *firstSession = profile.firstSessionDate;
NSDate *lastSession = profile.lastSessionDate;

// IAP metrics
NSInteger iapCount = profile.iapTransactionCount;
NSDictionary *revenueByCurrency = profile.iapRevenueByCurrency;
NSArray *productIDs = profile.purchasedProductIDsArray;

// ILRD metrics
double totalAdRevenue = profile.totalILRDRevenueUSD;
NSDictionary *revenueByNetwork = profile.ilrdRevenueByNetwork;
```


Available Properties:


| Property | Type | Description |
| --- | --- | --- |
| ` sessionCount ` | ` NSInteger ` | Total number of sessions |
| ` totalSessionTime ` | ` long long ` | Total time in milliseconds |
| ` averageSessionLength ` | ` long long ` | Average Session in milliseconds |
| ` lastSessionLength ` | ` long long ` | Last completed Session in milliseconds |
| ` currentSessionDuration ` | ` long long ` | Current active Session in milliseconds |
| ` firstSessionDate ` | ` NSDate? ` | First Session date |
| ` lastSessionDate ` | ` NSDate? ` | Last completed Session date |
| ` iapTransactionCount ` | ` NSInteger ` | Total IAP count |
| ` iapRevenueByCurrency ` | ` NSDictionary<NSString*, NSNumber*> ` | Revenue by currency code |
| ` purchasedProductIDsArray ` | ` NSArray<NSString*> ` | Sorted product IDs |
| ` totalILRDRevenueUSD ` | ` double ` | Total ad revenue USD |
| ` ilrdRevenueByNetwork ` | ` NSDictionary<NSString*, NSNumber*> ` | Ad revenue by network |


### Get Profile as Dictionary


Returns a dictionary with all metrics for easy serialization or display:


Objective-C

```
NSDictionary *profileDict = [TenjinSDK getUserProfileAsDictionary];

// Example usage
NSNumber *sessionCount = profileDict[@"session_count"];
NSString *firstSession = profileDict[@"first_session_date"];
NSDictionary *iapRevenue = profileDict[@"iap_revenue_by_currency"];
NSArray *productIds = profileDict[@"purchased_product_ids"];
```


Dictionary Keys (Always Present):


| Key | Type | Description |
| --- | --- | --- |
| ` session_count ` | ` NSNumber ` | Total sessions |
| ` total_session_time ` | ` NSNumber ` | Total time (milliseconds) |
| ` average_session_length ` | ` NSNumber ` | Average Session (milliseconds) |
| ` last_session_length ` | ` NSNumber ` | Last Session (milliseconds) |
| ` iap_transaction_count ` | ` NSNumber ` | Total IAP count |
| ` total_ilrd_revenue_usd ` | ` NSNumber ` | Total ad revenue USD |


Dictionary Keys (Conditional – only if available):


| Key | Type | Description |
| --- | --- | --- |
| ` first_session_date ` | ` NSString ` | ISO8601 formatted date |
| ` last_session_date ` | ` NSString ` | ISO8601 formatted date |
| ` current_session_length ` | ` NSNumber ` | Active Session duration (milliseconds) |
| ` iap_revenue_by_currency ` | ` NSDictionary ` | Map of currency → revenue |
| ` purchased_product_ids ` | ` NSArray ` | Sorted array of product IDs |
| ` ilrd_revenue_by_network ` | ` NSDictionary ` | Map of network → revenue |


### Reset Profile


Clears all user profile data (useful for testing or user logout):


Objective-C

```
[TenjinSDK resetUserProfile];
```


### Session Configuration


Customize Session timeout (default 30 minutes):


Objective-C

```
TJNUserProfileManager.sessionTimeoutInterval = 600; // 10 minutes
```


### Helper Methods


Get revenue for specific currency:


Objective-C

```
double usdRevenue = [profile getIAPRevenueForCurrency:@"USD"];
```


Get ILRD revenue for specific network:


Objective-C

```
double appLovinRevenue = [profile getILRDRevenueForNetwork:TJNAdNetworkAppLovin];
```


## Retry/cache events


You can enable/disable retrying and caching all events when requests fail or users don’t have internet connection. These events will be sent after a new event has been added to the queue and user has recovered connection.


` setCacheEventSetting(true) `


Objective-C

```
[TenjinSDK setCacheEventSetting:true];
```


## Google DMA Parameters


If you already have a CMP integrated, Google DMA parameters will be automatically collected by the Tenjin SDK. There’s nothing to implement in the Tenjin SDK if you have a CMP integrated. If you want to override your CMP, or simply want to build your own consent mechanisms, you can use the following:


` setGoogleDMAParametersWithAdPersonalization(bool, bool) `


Objective-C

```
[[TeninSDK sharedInstance] setGoogleDMAParametersWithAdPersonalization:adPersonalization adUserData:adUserData]; 
```


To explicitly manage the collection of Google DMA parameters, you have the flexibility to opt in or opt out at any time. While the default setting is to opt in, you can easily adjust your preferences using the optInGoogleDMA or optOutGoogleDMA methods, ensuring full control over your data privacy settings.


Objective-C

```
[TeninSDK optInGoogleDMA]; 
[TeninSDK optOutGoogleDMA]; 
```
