adjust-icon

S2S developer guide

Adjust offers a server-to-server (S2S) interface for mobile, console, and Connected TV (CTV) apps. If you choose to implement Adjust through S2S, you need to modify your app to replicate the Adjust SDK’s functions. This guide provides step-by-step instructions for the following:

  • How to make the necessary updates to your app.
  • How to send S2S requests to Adjust.

Before you begin

Here’s what you need to do before you get started.

Enable S2S session measurement

If you’re using the S2S interface for a mobile app, Adjust needs to enable S2S session measurement for your app. Contact your Adjust representative or support@adjust.com to proceed.

S2S session measurement is enabled automatically for CTV measurement and PC and Console measurement when you select a platform.

Set up S2S Security

Implement S2S Security to safeguard your S2S activities and prevent spoofed requests. Generate a token in your Adjust dashboard and include it in each incoming request.

Queue and persist events locally

Users may trigger important events, such as app installs or sessions, while their device is offline. To ensure accurate attribution, you must capture and store these events locally until they can be successfully transmitted to Adjust’s servers.

To implement a local event queue with persistence:

  1. Create a queue to store activities when they occur.
  2. For each activity, include a created_at_unix timestamp in seconds (for example: 1484085154) representing when the event occurred on the device.
  3. Save this queue to local storage (for example: SQLite database or files) to persist across app restarts.
  4. Attempt to send activities to Adjust’s servers when the queue is non-empty and the device is online.
  5. Remove activities from the queue only after successful transmission.

This approach helps mitigate data loss in the following scenarios:

  • Brief network interruptions (for example: 5G to WiFi handovers).
  • Extended periods without connectivity.
  • App crashes or force closes before transmission.

Without local queuing, you risk losing 10–20% of install data, which can significantly impact attribution accuracy. By implementing this queuing system, you ensure that Adjust receives a complete and accurate picture of user activity, enabling precise attribution even for events that occur offline.

Add iOS frameworks

You must link frameworks to your project to support certain iOS features. To add frameworks to your project:

  1. Open your project in Xcode.
  2. Select your target in the project navigator.
  3. Go to the General tab.
  4. Scroll to the Frameworks, Libraries, and Embedded Content section.
  5. Select the + button.
  6. Search for and add the frameworks that your app requires from the list below.
FrameworkDescription
AdSupport.frameworkRequired to collect IDFA. Also required to collect Limit Ad Tracking status for pre-ATT iOS versions.
AppTrackingTransparency.frameworkRequired to show the AppTrackingTransparency prompt and to collect IDFA on devices running iOS 14.5 and later.
AdServices.frameworkRequired for Adjust to attribute to Apple Search Ads campaigns.
StoreKit.frameworkRequired to run SKAdNetwork campaigns.

Required parameters

The following parameters are required in each S2S request.

ParameterDescription
s2sIndicates that the request is an S2S request. Must be hardcoded to 1.
app_tokenYour Adjust app token.
os_nameThe name of the mobile operating system. See the list of options below.
  • android
  • android-tv
  • apple-tv
  • bada
  • blackberry
  • fire-tv
  • ios
  • linux
  • macos
  • nintendo
  • playstation
  • roku-os
  • server
  • smart-cast
  • steamos
  • symbian
  • tizen
  • unknown
  • webos
  • windows
  • windows-phone
  • xbox

Create these parameters on your server. They will be used for all S2S requests to Adjust, regardless of the device. Additional device-specific parameters will be added as needed. For simplicity, this guide demonstrates all parameter handling on the client side, though in practice, much of this will occur server-side.

Device IDs and tracking statuses

Every S2S request must include at least one device identifier. Due to privacy measures implemented by mobile operating systems, the advertising ID may not always be available. Therefore, you should include the advertising ID when available and always include backup identifiers.

PC and Console / CTV device IDs

For PC and Console and CTV measurement, you can pass a unique external_device_id parameter with each call to use as a device identifier. This value can be any unique string that identifies the device.

iOS device IDs

IDFA and tracking status

The ID for Advertisers (IDFA) is available only for iOS devices where users have opted to share it. Some apps collect IDFA, other apps don’t. Regardless of whether an app collects IDFA, Adjust requires the tracking status in each request. Use the code below that corresponds to your implementation.

Apps that collect IDFA

  1. Add ATT description in Xcode.
    1. Open your project’s Info.plist file.
    2. In the editor, right-click on Information Property List and choose Add Row to add a key to the root.
    3. Set the key to NSUserTrackingUsageDescription.
    4. Set the value to a string explaining why you’re requesting tracking permission (for example: “This identifier will be used to deliver personalized ads to you.”). Be sure to review Apple’s guidelines for this text.
  2. Implement ATT prompt and IDFA retrieval.

ATT has the following requirements:

  • While ATT support begins with iOS 14, user consent for IDFA retrieval is only required from iOS 14.5 onwards. Therefore, Adjust recommends targeting the ATT prompt specifically to users on iOS 14.5 and later versions.
  • The ATT prompt requires an active app state to display. Showing it immediately after other system prompts may fail unless you first wait for the app state to be active again.
  • The earliest places to show the prompt are in applicationDidBecomeActive (App Delegate) or sceneDidBecomeActive (Scene Delegate). It’s not possible to show the ATT prompt in didFinishLaunchingWithOptions (App Delegate).

The below code example meets all of these requirements.

For accurate attribution, include the IDFA in the first session request and all subsequent requests whenever it is available.

Apps that don’t collect IDFA

Use the below code to get tracking status.

IDFV

The ID for Vendors (IDFV) is a backup identifier available on all modern iOS devices.

Primary deduplication token

To consistently measure app activities across uninstalls and reinstalls, generate a random version 4 UUID (the “primary deduplication token”) and save it in the iOS keychain. The primary deduplication token is a backup identifier that you should generate for all devices.

Google Play device IDs (Android)

Google Advertising ID

The Google Play Services Advertising ID (GPS ADID) is available on Android devices with Google Play Services, provided the user hasn’t opted to delete their advertising ID.

  1. Add the play-services-ads-identifier dependency to your app’s build.gradle file:
  1. Add the following permission to your AndroidManifest.xml file:

    AndroidManifest.xml
    <uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
  2. If your app uses R8 or ProGuard, add these rules to your proguard-rules.pro file to preserve classes and methods needed for Google Advertising ID retrieval during code optimization (create the file in your app module’s directory if it doesn’t exist):

    proguard-rules.pro
    -keep class com.google.android.gms.common.ConnectionResult {
    int SUCCESS;
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
    com.google.android.gms.ads.identifier.
    AdvertisingIdClient$Info getAdvertisingIdInfo(
    android.content.Context);
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
    java.lang.String getId();
    boolean isLimitAdTrackingEnabled();
    }
  3. Implement the code to collect Google Advertising ID and tracking status:

App Set ID

App Set ID is a backup identifier available on all Android devices with Google Play Services installed and running API Level 30 (Android 11) or later.

  1. Add the necessary dependency to your app’s build.gradle file:
  1. Implement the code to collect App Set ID:

Additional parameters

These parameters aren’t required. If you use any of these parameters, you should include them in all requests.

Unix timestamp

Including a Unix timestamp with each S2S request improves attribution accuracy by providing the time at which the activity occured on the device.

Probabilistic modeling data points

To use probabilistic modeling as an attribution method, you need to include the following parameters on all S2S requests:

ParameterDescription
device_nameThe name of the device.
device_typeThe device type or model.
os_versionThe version of the operating system running on the device.
ip_addressThe IP address of the device

Adjust strongly recommends adding these parameters as it enables more comprehensive attribution, particularly for iOS.

Environment

You can specify the environment that requests are being sent in by passing an environment parameter. Requests from different environments are kept separate in Adjust to enable testing. The following values are available:

  • sandbox: use this while testing to keep your requests separate from your production data.
  • production: use this when you release your app.

If you don’t pass this parameter, the default value is production.

Global callback parameters

When using raw data exports, you can include “global callback parameters” in all your S2S requests to add custom parameters to the raw data. This is commonly used to include your internal user ID in your exported raw data.

Global callback parameters are represented as a JSON object containing string key-value pairs.

Global partner parameters

When integrating with certain partners, you may need to include “global partner parameters” in all your S2S requests. Adjust’s servers passes these parameters in all callbacks it makes to partners. This is commonly used for analytics partners that require their own proprietary user ID in the callbacks they receive.

Global partner parameters are represented as a JSON object containing string key-value pairs.

Requests

Session

Sessions form the foundation of Adjust implementation and are the only required activity. A session typically represents an app open. Adjust’s servers log successful session requests as follows:

  • It records the first session for a device as an “install” activity.
  • It records subsequent sessions as “session” activities.
  • It records a “reattribution” or “reattribution reinstall” activity if reattribution criteria are satisfied.

When sending S2S session requests with the created_at_unix parameter, Adjust’s servers require this value to be at least 20 minutes later than the created_at_unix time of the last successfully logged session.

Request - cURL
curl -X POST "https://app.adjust.com/session" \ -H "Authorization: Bearer ADD_YOUR_AUTH_TOKEN_HERE" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "s2s=1\
&os_name=ios\
&app_token=i9dukg8o5slc\
&idfa=29DDE430-CE81-4F00-A50C-689595AAD142\
&att_status=3\
&idfv=59E27F41-A86B-4560-B585-63161F871C4B\
&primary_dedupe_token=3b35fcfb-6115-4cff-830f-e32a248c487d\
&created_at_unix=1484085154\
&device_name=iPhone16%2C2\
&device_type=iPhone\
&os_version=17.5.1\
&ip_address=192.0.0.1\
&environment=sandbox\
&callback_params=%7B%22user_id%22%3A%20%222696775149%22%2C%20%22user_category%22%3A%20%22high%20value%22%7D\
&partner_params=%7B%22analytics_user_id%22%3A%20%223913132433%22%2C%20%22analytics_session_id%22%3A%20%22nzFC9LKSqM%22%7D"\
-w "\n\nHTTP Status Code: %{http_code}\n"\
-s

This is the response format when Adjust successfully logs the first session for the device. You can use the Adjust testing console to forget your device and test this multiple times, if needed.

Response
{
"app_token": "4w565xzmb54d",
"adid": "df6c5653080670612cd2f9766ddc0814",
"timestamp": "2024-07-09T01:31:14.373Z+0000",
"message": "Install tracked",
"ask_in": 2000
}
HTTP Status Code: 200

This is the response format when Adjust successfully logs subsequent sessions for the device.

Response
{
"app_token": "4w565xzmb54d",
"adid": "df6c5653080670612cd2f9766ddc0814",
"timestamp": "2024-07-09T02:31:14.373Z+0000",
"message": "Session tracked",
"ask_in": 5000
}
HTTP Status Code: 200

Post-install event

After you send at least one successful session request for a device, you can send post-install events. These are typically events that represent marketing goals, and that networks can use to optimize campaigns.

Callback parameters

When using raw data exports, you can include custom “callback parameters” in specific event requests to add event-level custom data. For instance, on a purchase event, you might want to include your internal transaction ID in the raw data for that event.

Callback parameters are represented as a JSON object containing string key-value pairs.

Partner parameters

When integrating with certain partners, you may need to include custom “partner parameters” in your event requests. Adjust’s servers will then include these parameters on the callbacks it makes to partners for relevant events. This is most commonly used to enable dynamic remarketing campaigns, typically for events like view_item, add_to_cart, and purchase.

Partner parameters are represented as a JSON object containing string key-value pairs.

Send an event request.

Request - cURL
curl -X POST "https://app.adjust.com/event" \
-H "Authorization:Bearer ADD_YOUR_AUTH_TOKEN_HERE" \
-H "Content-Type:application/x-www-form-urlencoded" \
-d "s2s=1\
&os_name=ios\
&app_token=4w565xzmb54d\
&idfa=29DDE430-CE81-4F00-A50C-689595AAD142\
&att_status=3\
&idfv=59E27F41-A86B-4560-B585-63161F871C4B\
&primary_dedupe_token=3b35fcfb-6115-4cff-830f-e32a248c487d\
&created_at_unix=1484085154\
&device_name=iPhone16%2C2\
&device_type=iPhone\
&os_version=17.5.1\
&ip_address=192.0.0.1\
&environment=sandbox\
&callback_params=%7B%22user_id%22%3A%20%222696775149%22%2C%20%22user_category%22%3A%20%22high%20value%22%2C%20%22txn_id%22%3A%20%228837853376%22%7D\
&partner_params=%7B%22analytics_user_id%22%3A%20%223913132433%22%2C%20%22analytics_session_id%22%3A%20%22nzFC9LKSqM%22%2C%20%22item_id%22%3A%20%22%5B%5C%2276524%5C%22%2C%5C%2262599%5C%22%5D%22%7D"\
&event_token=2y7e81\
&revenue=19.99\
&currency=USD\
-w "\n\nHTTP Status Code: %{http_code}\n"\
-s
Response
{
"status": "OK"
}
HTTP Status Code: 200