Skip to content

Mobile App Tracking

CustomerLabs Mobile Tracking lets you capture behavioural data from your Android or iOS app, unify anonymous and identified user profiles, and activate that data across ad platforms and destinations. This guide walks you through the complete setup.


Before you begin, make sure you have the following:

  • Your CustomerLabs app_id — available in your CustomerLabs dashboard under Sources → [Your Mobile Source] → Source Configuration.
  • Your Webhook URL for the Events Tracking endpoint — also found in Source Configuration.
  • The target platform — Android (extInfoVersion: a2) or iOS (extInfoVersion: i2).
  • Permission to read the device advertising ID (AAID on Android, IDFA on iOS) and the user’s ad tracking preference (limitAdTracking).

Step 1: Initialise User and Session Identifiers

Section titled “Step 1: Initialise User and Session Identifiers”

On every app launch, check mobile local storage for an existing user_id. If none exists, generate one. Always generate a fresh session_id for each new session.

  1. Check for an existing user_id in local storage.
  2. If not found, generate user_id = app_id + UUIDv4 and persist it in local storage.
  3. Always generate a new session_id = CL- + UUIDv4 and store it in local storage for the duration of the session.
val prefs = context.getSharedPreferences("cl_prefs", Context.MODE_PRIVATE)
val userId = prefs.getString("user_id", null)
?: run {
val generated = "${appId}_${UUID.randomUUID()}"
prefs.edit().putString("user_id", generated).apply()
generated
}
val sessionId = "CL-${UUID.randomUUID()}"
prefs.edit().putString("session_id", sessionId).apply()

Step 2: Register the Device (External IDs)

Section titled “Step 2: Register the Device (External IDs)”

At the start of every session — for both new and returning users — call the External IDs endpoint. This registers the device’s advertising IDs, device metadata, and any UTM parameters from the app open deep link.

Endpoint: POST https://io.v2.customerlabs.co/app/externalIds

Headers:

Content-Type: application/json
CL-User-Agent: <user_agent>
{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"external_ids": {
"idfa": "IDFA_VALUE",
"aaid": "AAID_VALUE",
"google_analytics__app_instance_id": "GA_INSTANCE_ID",
"google_analytics__app_session_id": "GA_SESSION_ID",
"customerlabs_user_id": "YOUR_USER_ID"
},
"additional_info": {
"limitAdTracking": false,
"user_agent": "Mozilla/5.0 ...",
"appPackageName": "com.example.myapp",
"app_version_name": "2.1.0",
"carrier": "Airtel",
"deviceModelName": "Pixel 7",
"deviceTimeZone": "Asia/Kolkata",
"extInfoVersion": "a2",
"osVersion": "14",
"locale": "en-IN",
"screenWidth": "393",
"screenHeight": "851",
"screenDensity": "2.75"
},
"utm_params": {
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "summer_sale"
}
}

When a user logs in or provides their email or phone number, call the Profile Identify endpoint. This links the anonymous device identity to a known user profile and enriches it with traits.

Endpoint: POST https://io.v2.customerlabs.co/app/identify

{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"event_source": "mobile_app",
"added_at": "2026-03-12T05:45:15Z",
"identify_by": {
"identify_by_email": "[email protected]",
"identify_by_phone": "+918424032105"
},
"traits": {
"first_name": "Nelson",
"last_name": "Jaffery",
"email": "[email protected]",
"phone": "+918424032105",
"city": "Thane",
"country": "India"
},
"external_ids": {
"idfa": "IDFA_VALUE",
"aaid": "AAID_VALUE",
"customerlabs_user_id": "YOUR_USER_ID"
}
}

Use your Webhook URL to send behavioural events. Retrieve the Webhook URL from CustomerLabs Dashboard → Sources → [Your Mobile Source] → Source Configuration.

Endpoint: POST <YOUR_WEBHOOK_URL>

{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"event_name": "Product viewed",
"event_source": "mobile_app",
"added_at": "2026-03-12T05:45:15Z",
"identify_by": {
"identify_by_email": "[email protected]"
},
"properties": {
"currency": "USD"
},
"products": [
{
"product_id": "SKU-001",
"product_name": "Running Shoes",
"product_price": 100,
"product_quantity": 1
}
]
}
{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"event_name": "Added to cart",
"event_source": "mobile_app",
"added_at": "2026-03-12T05:46:00Z",
"identify_by": {
"identify_by_email": "[email protected]"
},
"properties": {
"value": 100,
"currency": "USD"
},
"products": [
{
"product_id": "SKU-001",
"product_name": "Running Shoes",
"product_price": 100,
"product_quantity": 1
}
]
}
{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"event_name": "Purchased",
"event_source": "mobile_app",
"added_at": "2026-03-12T05:47:30Z",
"identify_by": {
"identify_by_email": "[email protected]"
},
"properties": {
"value": 110,
"currency": "USD",
"transaction_id": "TXN-12345",
"shipping": 10,
"tax": 5,
"discount": 5,
"coupon": "SAVE10"
},
"products": [
{
"product_id": "SKU-001",
"product_name": "Running Shoes",
"product_price": 100,
"product_quantity": 1
}
]
}
{
"id": "YOUR_APP_ID",
"uid": "YOUR_USER_ID",
"sid": "CL-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"event_name": "Search",
"event_source": "mobile_app",
"added_at": "2026-03-12T05:50:00Z",
"identify_by": {
"identify_by_email": "[email protected]"
},
"properties": {
"search_string": "water bottle"
}
}

This flow covers a user opening the app for the first time, browsing anonymously, and adding an item to cart.

  1. User opens the app for the first time.
  2. App checks local storage for user_idnot found.
  3. App generates user_id = app_id + UUIDv4 and session_id = CL- + UUIDv4.
  4. App stores both in local storage.
  5. App calls POST /app/externalIds → sends AAID/IDFA, device metadata, UTM params → 200 OK.
  6. User views a product → App calls POST [Webhook URL] with event_name: "View Item"200 OK.
  7. User adds item to cart → App calls POST [Webhook URL] with event_name: "Add to Cart"200 OK.

Scenario 2: Returning User — Login + Purchase

Section titled “Scenario 2: Returning User — Login + Purchase”

This flow covers a returning user who opens the app, logs in, and completes a purchase.

  1. User opens the app.
  2. App checks local storage for user_idfound.
  3. App generates a new session_id = CL- + UUIDv4 and stores it.
  4. App calls POST /app/externalIds → sends AAID/IDFA, device metadata, UTM params → 200 OK.
  5. User logs in with email and phone → App calls POST /app/identify with identify_by, traits, and external_ids200 OK.
  6. User completes a purchase → App calls POST [Webhook URL] with event_name: "Purchase", identify_by, properties, and products200 OK.
  7. User searches for a product → App calls POST [Webhook URL] with event_name: "Search", properties.search_string200 OK.