Introduction
App Conversions allows mobile app developers to track and measure user interactions and conversions within their mobile apps. It enables developers to send app events directly from their apps to advertising platforms' servers, providing valuable data for ad optimization and tracking the effectiveness of their app marketing campaigns.
With App Conversions, developers can track various app events, such as app installs, app opens, in-app purchases, and other user interactions. These events are sent to advertising platforms, where advertisers can use them to target specific audiences and optimize their ad campaigns for better performance.
Get Started
The examples below use OkHttp for the HTTP call, org.json for building the request body, and Kotlin coroutines to keep networking off the main thread. Add the following imports to your project:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.io.IOExceptionExtended Device Information
Send device information, such as screen width and height, in your app event call using /{app-id}/activities?extinfo. Values are separated by commas and must be in the order indexed in the /application/activities reference guide. When using extinfo, all values are required.
versionmust bea2for Androidversionmust bei2for iOS
Get Mobile Cookies for Android
We encourage you to associate app events with an advertiser_id. However, for Android devices and iOS devices earlier than iOS 6, you can also use the attribution parameter set to the mobile cookie of the device.
Note
Mobile cookies are not derived from any user or device attributes. These cookies are not persistent and are designed to be refreshed frequently. Do not use mobile cookies for re-targeting ads.
The cookie is a random 22-character alphanumeric string. Get the Facebook attribution ID using ContentProvider:
public static final Uri ATTRIBUTION_ID_CONTENT_URI =
Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider");
public static final String ATTRIBUTION_ID_COLUMN_NAME = "aid";
public static String getAttributionId(ContentResolver contentResolver) {
String[] projection = {ATTRIBUTION_ID_COLUMN_NAME};
Cursor c = contentResolver.query(ATTRIBUTION_ID_CONTENT_URI, projection, null, null, null);
if (c == null || !c.moveToFirst()) {
return null;
}
String attributionId = c.getString(c.getColumnIndex(ATTRIBUTION_ID_COLUMN_NAME));
c.close();
return attributionId;
}Set Up Deduplication
The deduplication mechanism is required to remove duplicate event traffic between the Conversions API integration and all other existing integrations you have with app events, including the SDK and App Events API.
For app events, we apply the same deduplication functionality that exists for web events. The logic leverages event_id and event_name based deduplication (Conversions API and SDK / App Events API events that carry the same event_id). The event_id parameter is an identifier that can uniquely distinguish between similar events. Inaccurate event IDs may cause your conversion to be wrongly deduplicated, further impacting conversion reporting and campaign performance.
logger = AppEventsLogger.newLogger(this);
// Let's say you want to log a custom event
Bundle parameters = new Bundle();
parameters.putString("event_id", "123"); // deduplication parameter
// Add other event parameters if required
logger.logEvent("achievedLevel", parameters);Install events
For app install events, there is already a deduplication mechanism that makes sure only one install is attributed in the last 90-day window. We keep the first event and drop the later ones no matter the action source. No extra deduplication is required for install-related events.
Events
Please implement the following events in your app:
1. Purchase Event
object ApiClient {
// The base URL for the API endpoint
private const val BASE_URL = "https://cpi.ssevt.com/push"
private const val TOKEN = "ABC123" // Predefined Bearer Token
// Function to send a POST request to the API
suspend fun sendPostRequest() = withContext(Dispatchers.IO) {
// Create an instance of OkHttpClient to make the HTTP request
val client = OkHttpClient()
// Define the media type for the request body (application/json)
val mediaType = "application/json".toMediaType()
// Create the request body
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Order ID or Transaction ID For Purchase Event
put("et", "Purchase") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
put("currency", "USD")
put("value", 142.54)
put("app_id", "com.example.myapp")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
// Required
put("contents", JSONArray().apply {
put(JSONObject().apply {
put("id", "ABC123")
put("quantity", 1)
})
put(JSONObject().apply {
put("id", "DEF456")
put("quantity", 1)
})
})
// Required
put("content_type", "product")
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}
// Create the request body from the JSON body and media type
val requestBody = RequestBody.create(mediaType, jsonBody.toString())
// Build the POST request with the request body and headers, including Bearer token
val request = Request.Builder()
.url(BASE_URL)
.post(requestBody)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer $TOKEN") // Adding Bearer Token
.build()
try {
// Execute the request using OkHttpClient
val response = client.newCall(request).execute()
// Check if the response was successful (HTTP status code 200-299)
if (response.isSuccessful) {
val responseData = response.body?.string()
val jsonResponse = JSONObject(responseData)
println("Response: $jsonResponse")
} else {
println("Error: ${response.code} ${response.message}")
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: JSONException) {
e.printStackTrace()
}
}
}The other events reuse this client
Only the jsonBody changes between events. The sections below show the body for each event — the OkHttp request code stays exactly the same as in the Purchase example.
Parameter List
| User information | Parameter | Format | Example |
|---|---|---|---|
| Anonymous ID* | anon_id | Unique ID — do not hash | 123456abc |
| Advertising ID (IDFA / GAID)* | madid | Unique ID — do not hash | 7497f910905fb413fe27a64a557778063 |
| em | Lowercase + SHA256 hash | [email protected] | |
| First name | fn | Lowercase + SHA256 hash | john |
| Last name | ln | Lowercase + SHA256 hash | doe |
| Telephone | ph | Only numbers, incl. country and area code + SHA256 hash | 12125357525 |
| Gender | ge | A single lowercase letter, f or m + SHA256 hash | f |
| Birthday | db | Only numbers: year, month, day + SHA256 hash | 19910526 for May 26, 1991 |
| City | ct | Lowercase, no spaces + SHA256 hash | newyork |
| Postal / zip code | zp | Only numbers + SHA256 hash | 34000 |
| Country | cn | Two-letter country code, lowercase + SHA256 hash | tr |
PII Hashing
Every personal identifier except anon_id and madid must be normalized and SHA256-hashed before sending. Use our PII Hashing guide and live tool to verify your hashes.
2. View Content Event
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Any Unique Identifier
put("et", "ViewContent") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
put("currency", "USD")
put("value", 142.54)
put("app_id", "com.example.myapp")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
// Required
put("contents", JSONArray().apply {
put(JSONObject().apply {
put("id", "ABC123")
put("quantity", 1)
})
put(JSONObject().apply {
put("id", "DEF456")
put("quantity", 1)
})
})
// Required
put("content_type", "product")
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}3. Add To Cart Event
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Any Unique Identifier
put("et", "AddToCart") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
put("currency", "USD")
put("value", 142.54)
put("app_id", "com.example.myapp")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
// Required
put("contents", JSONArray().apply {
put(JSONObject().apply {
put("id", "ABC123")
put("quantity", 1)
})
put(JSONObject().apply {
put("id", "DEF456")
put("quantity", 1)
})
})
// Required
put("content_type", "product")
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}4. Lead Event
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Any Unique Identifier
put("et", "Lead") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}5. Complete Registration Event
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Any Unique Identifier
put("et", "CompleteRegistration") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}6. Contact Event
val jsonBody = JSONObject().apply {
// Required
put("eid", "d290f1ee-6c54-4b01-90e6-d701748f0851") // Any Unique Identifier
put("et", "Contact") // Event Name
put("ua", "App") // App Static Value
put("p", JSONObject().apply {
// Required
put("event_time", 1644778428)
put("platform", "android")
put("os_version", "33") // Android API version
put("att", 1) // Advertiser Tracking Enabled
put("ate", 1) // Application Tracking Enabled
put("device_model", "Galaxy A23")
// Optional
put("screen_width", "762")
put("screen_height", "1278")
put("external_storage", "128")
put("free_space", "63")
put("device_timezone", "Europe/London")
// Add other optional properties here
// ...
})
// Advanced Matching Parameters
put("amp", JSONObject().apply {
// Required
put("anon_id", "123456abc") // The ID of a person who has installed the app anonymously
put("madid", "7497f910905fb413fe27a64a557778063") // IDFA or Google advertising ID
// Optional
put("ph", "8a187a62e69697497f910905fb413fe27a64a5577780636db7b18305e57cacaf") // Phone
put("em", "55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149") // Email
put("ge", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111") // Gender
put("db", "d5234ccb6fb4dd59cbe76a3e5e1f396c27d2862246c7dbd7bc9e8fd72d664aaf") // Date Of Birth
put("ct", "350c754ba4d38897693aa077ef43072a859d23f613443133fecbbd90a3512ca5") // City
put("zp", "3ebb904517b0c6cf6b2d387f1e5f0ba715258125efc4012d88c4053d0da62233") // Zip Code
put("cn", "79adb2a2fce5c6ba215fe5f27f532d4e7edbac4b6a5e09e1ef3a08084a904621") // Country
})
}