---
id: "integrations/attribution/tenjin"
title: "Tenjin"
description: "With our Tenjin integration you can:"
permalink: "/docs/integrations/attribution/tenjin"
slug: "tenjin"
version: "current"
original_source: "docs/integrations/attribution/tenjin.mdx"
---

> **AI agents:** This is the Markdown version of a RevenueCat documentation page. For the complete documentation index, see [llms.txt](https://www.revenuecat.com/docs/llms.txt).

With our Tenjin integration you can:

- Accurately track subscriptions generated from Tenjin campaigns, allowing you to know precisely how much revenue your campaigns generate.
- Send trial conversions and renewals directly from RevenueCat to Tenjin, allowing for tracking without an app open.
- Continue to follow your cohorts for months to know the long tail revenue generated by your campaigns.

### Integration at a Glance

| Includes Revenue | Supports Negative Revenue | Sends Sandbox Events | Includes Customer Attributes | Sends Transfer Events | Optional Event Types |
| :--------------: | :-----------------------: | :------------------: | :--------------------------: | :-------------------: | :------------------: |
|        ✅        |            ❌             |          ❌          |              ❌              |          ❌           |          ❌          |

## 1. Send device data to RevenueCat

The Tenjin integration requires some device-specific data. RevenueCat will only send events into Tenjin when the required [Attribute](https://www.revenuecat.com/docs/customers/customer-attributes) below is set for iOS or Android devices. Recommended attributes improve matching quality.

| Key         | Description                                                                                                                                     | Required         |
| :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | :--------------- |
| `$tenjinId` | Tenjin Id. The Tenjin Analytics Installation ID for the device                                                                                  | ⚠️ (recommended) |
| `$idfa`     | iOS [advertising identifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/1614151-advertisingidentifier) UUID        | ✅ (iOS)         |
| `$gpsAdId`  | Google [advertising identifier](https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info) | ✅ (Android)     |
| `$idfv`     | iOS [vendor identifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor) UUID                              | ⚠️ (recommended) |
| `$ip`       | The IP address of the device                                                                                                                    | ⚠️ (recommended) |

:::info\[IDFA attribute]
Even if a user has not granted permission to track, the IDFA attribute must be set to the iOS default provided value of `00000000-0000-0000-0000-000000000000` in order for events to be sent to Tenjin.
:::

:::warning\[Android ID deprecation]
Due to policy changes from the Play Store, Android ID is no longer collected by RevenueCat's Android SDKs starting on versions 6.9.8+, 7.11.1+, and later major versions.

Therefore, Google's Advertising ID acts as the primary device identifier for Android devices in RevenueCat and when connecting with third-party integrations.
:::

These properties can be set manually, like any other [Customer Attributes](https://www.revenuecat.com/docs/customers/customer-attributes), or through the helper method `collectDeviceIdentifiers()` and `setTenjinAnalyticsInstallationID()`.

**Swift**

```swift
import AdSupport
// ...
Purchases.configure(withAPIKey: "public_sdk_key")
// ...

// Automatically collect the $idfa, $idfv, and $ip values
Purchases.shared.attribution.collectDeviceIdentifiers()

// Set the Tenjin ID
Purchases.shared.attribution.setTenjinAnalyticsInstallationID(tenjinAnalyticsId)
```

**Kotlin**

```kotlin
//..
Purchases.configure(this, "public_sdk_key")
//..

// Automatically collect the $idfa, $idfv, and $ip values
Purchases.sharedInstance.collectDeviceIdentifiers()

// Set the Tenjin ID
Purchases.sharedInstance.setTenjinAnalyticsInstallationID(tenjinAnalyticsId);
```

`setTenjinAnalyticsInstallationID()` is available on:

- iOS version 5.8.0+
- Android version 8.10.0+
- React Native version 8.2.7+
- Flutter version 8.9.0+

You should make sure to call `collectDeviceIdentifiers()` after the *Purchases SDK* is configured, and before the first purchase occurs. It's safe to call this multiple times, as only the new/updated values will be sent to RevenueCat. If the Tenjin ID is not set, events will be sent with only the platform-specific advertising identifier.

:::danger\[Device identifiers with iOS App Tracking Transparency (iOS 14.5+)]
If you are requesting the App Tracking permission through ATT to access the IDFA, you can call `.collectDeviceIdentifiers()` *again* if the customer accepts the permission to update the `$idfa` attribute in RevenueCat.
:::

:::info\[Import AdSupport Framework (iOS)]
The AdSupport framework is required to access the IDFA parameter on iOS. Don't forget to import this into your project.
:::

![Import AdSupport Framework](https://www.revenuecat.com/docs_images/integrations/attribution/import-adsupport-framework.png)

### (Optional) Send campaign data to RevenueCat

RevenueCat itself is not an attribution network, and can't determine which specific ad drove an install/conversion. However, if you're able to collect this information from another source, such as Tenjin, it's possible to attach it to a Customer in RevenueCat using [Attributes](https://www.revenuecat.com/docs/customers/customer-attributes) as well.
The below reserved key names can be used to optionally attach campaign data to a user. This data will then be sent through to other downstream analytics integrations and accessible via APIs and webhooks.

| Key            |
| :------------- |
| `$mediaSource` |
| `$campaign`    |
| `$adGroup`     |
| `$ad`          |
| `$keyword`     |
| `$creative`    |

:::danger\[Remove SDK Purchase Tracking]
Make sure to remove all client side tracking of revenue. Since RevenueCat will be sending events for all revenue actions, tracking purchases with the Tenjin SDK directly can lead to double counting of revenue in Tenjin.
:::

## 2. Send RevenueCat events into Tenjin

After you've set up the *Purchases SDK* to send attribution data from Tenjin to RevenueCat, you can "turn on" the integration and configure the event names from the RevenueCat dashboard.

1. Navigate to your project settings in the RevenueCat dashboard and choose 'Tenjin' from the Integrations menu

![Integration setup](https://www.revenuecat.com/docs_images/integrations/setup-integrations.png)

2. Add the Tenjin SDK key(s) for your iOS app and/or Android app if available, which can be accessed in the applicable app's settings; or add your universal SDK key if app-specific keys are not available (only applicable for legacy Tenjin customers).
3. Select whether you want sales reported as gross revenue (before app store commission), or after store commission and/or estimated taxes.

:::info\[About revenue discrepancies]
RevenueCat must have the IDFA or ADID attribute of the user set at the time an event occurs in order to send that event to Tenjin. If IDFA access has not been granted, then the attribute should be set to the iOS default provided value of `00000000-0000-0000-0000-000000000000`. If neither of these attributes are set, events won't be delivered, which means some of your total revenue won't be tracked by Tenjin. If events are being sent successfully in testing and for your users in production who have either of those attributes set, then the integration is working as intended to pair subscription revenue with campaign performance.
:::

:::success\[You've done it!]
You should start seeing events from RevenueCat appear in Tenjin.
:::
