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 Settings → General → Account ID.
  • 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_name": "User identified",
"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"
}
}

Send behavioural events to the Events Tracking endpoint.

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

{
"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 /app/track with event_name: "Product viewed"200 OK.
  7. User adds item to cart → App calls POST /app/track with event_name: "Added 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 and traits200 OK returns user_id.
  6. App stores the returned user_id in local storage, replacing the anonymous one, and uses it for all further calls.
  7. User completes a purchase → App calls POST /app/track with event_name: "Purchased", identify_by, properties, and products200 OK.
  8. User searches for a product → App calls POST /app/track with event_name: "Search", properties.search_string200 OK.
Section titled “Scenario 3: App Opened via Campaign Deeplink”

This flow covers a user opening the app through a campaign link carrying UTM parameters or click IDs.

  1. User clicks a campaign link and the app opens with parameters (utm_source, utm_medium, gclid, fbclid, ttclid, etc.).
  2. App retrieves the existing user_id from local storage.
  3. App generates a new session_id = CL- + UUIDv4 to associate the campaign data with a fresh session, and updates local storage.
  4. App calls POST /app/externalIds → sends the received UTM parameters and click IDs along with the required parameters → 200 OK.
  5. App continues tracking events with POST /app/track using the updated session_id.