---
id: "integrations/attribution/adjust"
title: "Adjust"
description: "With our Adjust integration you can:"
permalink: "/docs/integrations/attribution/adjust"
slug: "adjust"
version: "current"
original_source: "docs/integrations/attribution/adjust.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 Adjust integration you can:

- Accurately track subscriptions generated from Adjust campaigns, allowing you to know precisely how much revenue your campaigns generate.
- Send trial conversions and renewals directly from RevenueCat to Adjust, 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

| Revenue support | Supports Negative Revenue | Sends Sandbox Events | Includes Customer Attributes | Sends Transfer Events |      Optional Event Types       |
| :-------------: | :-----------------------: | :------------------: | :--------------------------: | :-------------------: | :-----------------------------: |
|       ✅        |            ❌             |          ✅          |              ❌              |          ❌           | [See Event types](#event-types) |

For a cross-provider view of identifiers, revenue support, sandbox behavior, and attribution responsibilities, see the [attribution provider comparison](https://www.revenuecat.com/docs/integrations/attribution/provider-comparison).

## Before you begin

Review [Getting Started with Attribution Integrations](https://www.revenuecat.com/docs/integrations/attribution/getting-started) for how attribution integrations fit together, then use the [setup checklist](https://www.revenuecat.com/docs/integrations/attribution/setup-checklist) as a reference for required lifecycle events, reporting choices, duplicate-event risks, and testing checks.

The following considerations are specific to Adjust:

- Adjust uses event tokens, not readable event names. Configure the required tokens for each platform you want RevenueCat to send events from.
- If your app shows a paywall very early, a customer can purchase before `$adjustId` has synced to RevenueCat. Keep the callback or delegate path in your implementation so `collectDeviceIdentifiers()` and `setAdjustID()` run again when Adjust attribution data becomes available.
- Turn off Adjust SDK purchase or revenue tracking for the same events RevenueCat sends, unless you intentionally manage deduplication in Adjust.
- Adjust doesn't accept revenue values below `0.001`, including negative values. Free trial events and refunds are sent without revenue.
- If you enabled S2S authentication in Adjust, add the matching OAuth token to the RevenueCat Adjust settings.

#### iOS

- Adjust SDK v5 removed `adid` from `ADJAttribution` on iOS. Fetch the ADID
  from the Adjust SDK, then pass it to `setAdjustID()`. RevenueCat stores
  the value as `$adjustId`.

#### Android

- Adjust SDK v5 removed `adid` from `AdjustAttribution` on Android. Fetch
  the ADID from the Adjust SDK, then pass it to `setAdjustID()`. RevenueCat
  stores the value as `$adjustId`.

## 1. Install Adjust SDK

Before RevenueCat can integrate with Adjust, your app should be running the latest Adjust SDK. Refer to the [Adjust developer documentation](https://help.adjust.com/en/article/sdk-releases) for the latest installation instructions.

## 2. Send attribution data to RevenueCat

Adjust matches RevenueCat events to campaigns using device-specific attribution data. RevenueCat will only send events into Adjust when the required [Customer Attributes](https://www.revenuecat.com/docs/customers/customer-attributes) below are set for the device. Recommended attributes improve attribution matching quality.

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

These properties can be set manually, like any other [Customer Attributes](https://www.revenuecat.com/docs/customers/customer-attributes), or through the helper methods `collectDeviceIdentifiers()` and `setAdjustID()`. Set them after the RevenueCat SDK is configured and before the first purchase occurs whenever possible.

The examples below show the recommended app-side flow:

1. Configure the RevenueCat SDK.
2. Collect device identifiers.
3. Pass the Adjust ID to `setAdjustID()` if it's available.
4. Keep the callback path in place so your app can collect identifiers again when a previously unavailable value becomes available, such as after ATT permission is granted or the Adjust SDK returns the ADID.

#### iOS

- If you request App Tracking Transparency permission to access the IDFA,
  call `collectDeviceIdentifiers()` again after the customer accepts
  permission to update the `$idfa` attribute in RevenueCat.
- The AdSupport framework is required to access the IDFA parameter. In
  Xcode, add `AdSupport.framework` to your app target under **Frameworks,
  Libraries, and Embedded Content**, leave it set to **Do Not Embed**, then
  import `AdSupport` in your Swift file.

#### Android

- RevenueCat's current Android SDKs don't collect Android ID. Google's
  Advertising ID (`$gpsAdId`) acts as the primary Android device identifier
  in RevenueCat and when connecting with third-party integrations.

```
import AdjustSdk // Provides Adjust, ADJConfig, and AdjustDelegate
import RevenueCat
import AdSupport // Required for IDFA collection
import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {
    private let adjustDelegate = AdjustAttributionDelegate()

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        Purchases.configure(withAPIKey: "public_sdk_key")

        let config = ADJConfig(
            appToken: "adjust_app_token",
            environment: ADJEnvironmentProduction
        )!
        config.delegate = adjustDelegate
        Adjust.initSdk(config)

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

        // Set the Adjust ID on app launch if it exists
        setAdjustIdIfAvailable()

        return true
    }
}

private func setAdjustIdIfAvailable() {
    Adjust.adid { adjustId in
        if let adjustId = adjustId {
            Purchases.shared.attribution.setAdjustID(adjustId)
        }
    }
}

// IMPORTANT: Set the Adjust ID when it becomes available, if it
// didn't exist on app launch
private final class AdjustAttributionDelegate: NSObject, AdjustDelegate {
    func adjustAttributionChanged(_ attribution: ADJAttribution?) {
        Purchases.shared.attribution.collectDeviceIdentifiers()
        setAdjustIdIfAvailable()
    }
}
```

```
Purchases.configure(this, "my_api_key");

// Automatically collect the $gpsAdId and $ip values
Purchases.getSharedInstance().collectDeviceIdentifiers();

// Set the Adjust ID on app launch if it exists
setAdjustIdIfAvailable();

// IMPORTANT: Set the Adjust ID when it becomes available, if it
// didn't exist on app launch
config.setOnAttributionChangedListener(new OnAttributionChangedListener() {
    @Override
    public void onAttributionChanged(AdjustAttribution attribution) {
        Purchases.getSharedInstance().collectDeviceIdentifiers();
        setAdjustIdIfAvailable();
    }
});

private void setAdjustIdIfAvailable() {
    Adjust.getAdid(new OnAdidReadListener() {
        @Override
        public void onAdidRead(String adjustId) {
            if (adjustId != null) {
                Purchases.getSharedInstance().setAdjustID(adjustId);
            }
        }
    });
}
```

:::caution\[Set identifiers before purchase]
RevenueCat only creates an Adjust delivery attempt when `$adjustId` is present on the event. If RevenueCat already processed a purchase without the identifier, setting it later doesn't repair that past event.
:::

### (Optional) Send campaign data to RevenueCat

RevenueCat isn't an attribution network and can't determine which ad drove an install or conversion. If Adjust or another source gives your app final campaign values, you can attach them to the customer using reserved [Customer Attributes](https://www.revenuecat.com/docs/customers/customer-attributes).

:::caution\[Set final campaign values only]
Don't set your own fallback campaign values, such as `Organic`, `Unknown`, or `No User Consent`, while waiting for Adjust attribution. Reserved attribution attributes can only be set once per customer. If Adjust later returns final campaign values, RevenueCat can't replace a placeholder value you already set.
:::

If you set these campaign attributes from an Adjust callback or delegate, keep the `$adjustId` setup above in place. Campaign attributes are additive, not a replacement for the required Adjust ID.

| Key            | Description                                |
| :------------- | :----------------------------------------- |
| `$mediaSource` | The attribution source or network          |
| `$campaign`    | The campaign name or identifier            |
| `$adGroup`     | The ad group name or identifier            |
| `$ad`          | The ad name or identifier                  |
| `$keyword`     | The keyword associated with the attribution |
| `$creative`    | The creative name or identifier            |

## 3. Send RevenueCat events into Adjust

After you've set up the RevenueCat SDK to send attribution data from Adjust to RevenueCat, you can enable the integration and configure the event tokens from the RevenueCat dashboard.

1. Go to your dashboard and select your project.

2. In the lower-left corner, select **Integrations**.

3. Select **Adjust**.

4. Configure each platform you want RevenueCat to send events from:
   1. Open the platform's configuration section.
   2. Skip the **OAuth token override** field for now. This optional field is explained in [(Optional) Configure S2S Adjust authentication](#optional-configure-s2s-adjust-authentication).
   3. Add the Adjust app token.
   4. Create or find the corresponding events in Adjust for the core subscription lifecycle events described in the [setup checklist](https://www.revenuecat.com/docs/integrations/attribution/setup-checklist#configure-provider-communication), then copy each Adjust-generated event token into the matching RevenueCat event token field.
   5. Configure any optional event tokens from [Event types](#event-types) that you want RevenueCat to send.

5. Select whether you want sales reported as gross revenue (before app store commission), or after store commission and/or estimated taxes. This setting applies to the Adjust integration as a whole. It changes the revenue value RevenueCat sends to Adjust, so use the same reporting mode when comparing Adjust-side ROAS to RevenueCat revenue metrics. Learn more about [taxes and commissions](https://www.revenuecat.com/docs/dashboard-and-metrics/taxes-and-commissions).

If you set `$adjustId` and other attributes after configuring Purchases and before a purchase occurs, RevenueCat syncs them with the purchase event. You usually don't need to call `syncAttributesAndOfferingsIfNeeded()` for Adjust. Reserve explicit syncs for cases where newly set attributes must affect [Targeting](https://www.revenuecat.com/docs/tools/targeting/custom-attributes) or where you need to avoid a race with server-side purchase tracking. Avoid frequent calls because this SDK method is limited to 5 calls per minute per running app instance.

### Event types

RevenueCat sends Adjust events using the event tokens you configure for each platform. Adjust event tokens are provider-issued identifiers, not readable event names. Use the token for the matching Adjust event, and don’t reuse a token across different RevenueCat lifecycle events unless you intentionally want Adjust to report them as the same event.

RevenueCat sends the core subscription lifecycle events described in the [setup checklist](https://www.revenuecat.com/docs/integrations/attribution/setup-checklist#configure-provider-communication). Adjust also supports these optional events:

| Optional event            | Sent when                                           |
| :------------------------ | :-------------------------------------------------- |
| Non-subscription purchase | A user makes a one-time (non-subscription) purchase |
| Expiration                | A subscription expires and access is lost           |
| Product change            | A user changes the product of their subscription    |

### (Optional) Configure S2S Adjust authentication

If you've enabled [S2S authentication on Adjust](https://help.adjust.com/en/article/server-to-server-s2s-security), add the matching OAuth token to RevenueCat:

1. To use the same token for every platform, in the Adjust integration settings, add the token to **Global OAuth token**.
2. To use a platform-specific token, in the matching platform configuration section, add the token to **OAuth token override**.

If both fields are set for a platform, RevenueCat uses the platform **OAuth token override** instead of the **Global OAuth token**.

If you enable S2S authentication in Adjust and don't configure an OAuth token in RevenueCat, Adjust will respond to events with the following error:

```json
{"error":"Event request failed (missing authentication token)"}
```

## 4. Test the Adjust integration

Before rolling out the integration, test with a new customer after the SDK, customer attributes, and dashboard settings are configured.

1. Make a sandbox purchase with a new customer.
2. In the RevenueCat [Customer Profile](https://www.revenuecat.com/docs/dashboard-and-metrics/customer-profile#customer-details), confirm the required attributes from [Send attribution data to RevenueCat](#2-send-attribution-data-to-revenuecat) are present.
3. In [Customer History](https://www.revenuecat.com/docs/dashboard-and-metrics/customer-profile#customer-history), open the sandbox purchase event and confirm the Adjust delivery row exists. If RevenueCat doesn't show an Adjust delivery row, see [no provider delivery row troubleshooting](https://www.revenuecat.com/docs/integrations/attribution/troubleshooting#no-provider-delivery-row-appears-in-revenuecat).
4. In the RevenueCat Adjust integration settings, review failed events and compare any error codes with [Adjust's server-to-server API reference](https://help.adjust.com/en/article/s2s-api-reference?src=search#event-submission-responses). For general rejection guidance, see [provider rejection troubleshooting](https://www.revenuecat.com/docs/integrations/attribution/troubleshooting#the-provider-rejects-events).

### Verify sandbox events in Adjust Testing Console

RevenueCat sends sandbox subscription events to Adjust in sandbox mode. In Adjust Testing Console, use the **SANDBOX MODE** filter to view sandbox events before moving to production, especially if you're submitting an app with Adjust attribution for the first time. See [Adjust Testing Console docs](https://help.adjust.com/en/article/testing-console/).

![Use the "SANDBOX MODE" filter in Adjust to see sandbox events from RevenueCat](https://www.revenuecat.com/docs_images/integrations/attribution/adjust/adjust-sandbox-mode.png)

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

## Historical or backfilled events

Adjust can warn or reject events that arrive out of timestamp order, such as a historical import sent after a newer live event for the same customer. Test migrations with a small sample before sending a large backfill.

See [historical or backfilled event troubleshooting](https://www.revenuecat.com/docs/integrations/attribution/troubleshooting#historical-or-backfilled-events-behave-differently) for the shared pattern.

## Sample event

Below is a representative sample event sent to Adjust. The type of event (for example, initial purchase or renewal) is defined by the configured `event_token`. Optional device and revenue fields depend on the customer attributes and event data available when RevenueCat processes the event.

```json
{
  "app_token": "abcdefg",
  "event_token": "abcdefg",
  "s2s": 1,
  "created_at_unix": 1640995185,
  "adid": "00000000000000000000000000000000",
  "environment": "production",
  "currency": "USD",
  "revenue": 34.511,
  "idfa": "00000000-0000-0000-0000-000000000000",
  "idfv": "00000000-0000-0000-0000-000000000000",
  "ip_address": "00.0.000.000",
  "sender": "revenuecat"
}
```
