Skip to main content

Tenjin integration

Tenjin is a mobile attribution and analytics platform for app developers and marketers. It provides tools to measure and optimize user acquisition campaigns by offering detailed insights into app performance and user behavior. With its transparent and flexible approach, Tenjin aggregates data from advertising networks and app stores, enabling teams to analyze ROI, track conversions, and monitor key performance metrics.

By forwarding subscription events to Tenjin, you can see exactly where conversions come from and which campaigns bring in the most value across all channels, platforms, and devices. Essentially, Tenjin dashboards offer advanced analytics for marketing campaigns.

By forwarding Tenjin's attribution to Adapty, you enrich the Adapty analytics with additional filtration criteria you can use in cohort and conversion analysis.

This integration operates in two key ways:

  1. Receiving attribution data from Tenjin Once integrated, Adapty collects attribution data from Tenjin. You can access this information on the user’s profile page in the Adapty Dashboard.
  2. Sending subscription events to Tenjin Adapty sends purchase events to Tenjin in real-time. These events help evaluate the effectiveness of your ad campaigns directly within Tenjin’s dashboard.

Integration Characteristics

Integration characteristicDescription
ScheduleReal-time
Data direction

Two-way transmission:

  • Adapty events: From Adapty server to Tenjin server
  • Tenjin attribution: From Tenjin SDK to Adapty server
Adapty integration point
  • Tenjin and Adapty SDKs in the mobile app code
  • Adapty server

Tenjin event structure

Adapty sends selected events to Tenjin as configured in the Events names section on the Tenjin Integration page. Each event is structured like this:

Json
{
"price": 99.0,
"locale": "en-US",
"country": "ME",
"postcut": "false",
"currency": "USD",
"platform": "ios",
"quantity": 1,
"bundle_id": "com.adapty.adaptydemoapp",
"ip_address": "127.0.0.1",
"os_version": "18.1.1",
"product_id": "month.premium.99",
"app_version": "3.2.0",
"sdk_version": "server",
"device_model": "iPhone 13 Mini",
"advertising_id": "00000000-0000-0000-0000-000000000000",
"os_version_release": "18.1.1",
"developer_device_id": "00000000-0000-0000-0000-000000000000",
"analytics_installation_id": "00000000-0000-0000-0000-000000000000"
}

Where

ParameterTypeDescription
priceFloatThe unit price of the item purchased in the currency standard unit (e.g., USD is reported in dollars).
localeStringThe locale of the device. For Android: Locale.getDefault().toString(). For iOS: [[NSLocale currentLocale] localeIdentifier].
countryStringThe ISO locale country code standard (e.g., US for the United States).
postcutString (Boolean)Indicates whether the purchase was sent after the platform cut. 1 for true, 0 for false.
currencyStringThe ISO currency code (e.g., USD for US dollars).
platformStringThe platform of the device (e.g., ios, android, windows, amazon).
quantityIntegerThe number of units purchased.
bundle_idStringThe bundle identifier of the app (e.g., com.example.app).
ip_addressString (IPv4)The user’s IP address. Used to look up the country.
os_versionStringThe OS version of the device. For Android: String.valueOf(Build.VERSION.SDK_INT). For iOS: [[UIDevice currentDevice] systemVersion].
product_idStringUnique identifier for the product purchased.
app_versionFloat, DecimalThe version of the app. For Android: context.getPackageManager().getPackageInfo(). For iOS: [[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"].
sdk_versionStringThe SDK version in use, always set to server.
device_modelStringThe model of the device. For Android: Build.MODEL. For iOS: sysctl("hw.machine").
advertising_idUUIDThe advertising ID of the device. Required for Android. For iOS, it can be empty or all zeros.
os_version_releaseStringThe OS version release. For Android: String.valueOf(Build.VERSION.RELEASE). For iOS: [[UIDevice currentDevice] systemVersion].
developer_device_idUUIDThe identifier for the vendor (iOS only).
analytics_installation_idUUIDAnalytics installation ID. For details, refer to the documentation at https://docs.tenjin.com.

Setting up Tenjin integration

  1. Open the Integrations -> Tenjin page in the Adapty Dashboard.

  2. Enable the toggle to activate the integration.

  3. Log into the Tenjin Dashboard.

  4. Go to Configuration -> Apps in the navigation menu.

  5. Select the app you want to integrate and navigate to the App and SDK tab.

  6. In the App and SDK tab, click Copy in the SDK Key column. If you don’t have an SDK key yet, click the Generate SDK Key button to create one.

  7. Paste the copied SDK Key into the SDK Key or Sandbox SDK Key field in the Adapty Dashboard.

    info

    Tenjin doesn’t have a specific Sandbox mode for server-to-server integration. Use a separate Tenjin app or the same key for both production and sandbox events.

  8. (optional) Adjust the How the revenue data should be sent section if needed. For a detailed explanation of its settings, refer to the Integration settings.

  9. Click Save to finalize the setup.

Adapty will now send purchase events to Tenjin and receive attribution data. You can adjust event sharing in the Events names section.

Events and tags

Tenjin only accepts purchase and Trial started events. In the Events names section, select which events to share with Tenjin to align with your tracking goals.

SDK configuration

It's very important to send Tenjin attribution data from the device to Adapty using Adapty.updateAttribution() SDK method. The example below shows how to do that.

import TenjinSDK

func updateTenjinId() {
guard let tenjinId = TenjinSDK.getAnalyticsInstallationId() else { return }

do {
try await Adapty.setIntegrationIdentifier(
key: "tenjin_analytics_installation_id",
value: tenjinId
)
} catch {
// handle the error
}
}

func updateTenjinAttribution() {
let instance = TenjinSDK.getInstance("<YOUR_TENJIN_API_TOKEN>")

instance?.getAttributionInfo { info, _ in
guard let info else { return }

Task {
do {
try await Adapty.updateAttribution(info, source: "tenjin")
} catch {
// handle the error
}
}
}
}