> ## Documentation Index
> Fetch the complete documentation index at: https://linkrunner-01ef8e08-chetan-sdk-install-version-bumps.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Collecting Device Data

> Where each device_data field comes from on Android, and what attribution loses without it.

`device_data` is the object you send on `init`, `attribution-data`, and `signup`. It carries the signals Linkrunner uses to match an install to a click. Most fields are simple lookups. Three need Google Play libraries and do the heavy lifting for attribution.

The [full client](/sdk-less/android-quickstart) collects all of these for you. This page explains each one so you can trust, trim, or rebuild that collection.

## Dependencies

```gradle theme={null}
dependencies {
    // Advertising ID (GAID)
    implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
    // App Set ID
    implementation 'com.google.android.gms:play-services-appset:16.0.2'
    // Google Play Install Referrer
    implementation 'com.android.installreferrer:installreferrer:2.2'
}
```

<Note>
  Going SDK-less does not remove these libraries. They are how Android exposes the advertising ID and the install referrer, so you need them no matter how you call Linkrunner.
</Note>

## Permissions and queries

```xml theme={null}
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

<!-- Lets you see the Meta apps for the Meta install referrer (Android 11+) -->
<queries>
    <package android:name="com.facebook.katana" />
    <package android:name="com.instagram.android" />
    <package android:name="com.facebook.lite" />
</queries>
```

## What to send

| Field                                                          | Source on Android                 | Importance                                                   |
| -------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------ |
| `gaid`                                                         | `AdvertisingIdClient`             | **High**. Google Ads and device matching.                    |
| `install_ref` (and related)                                    | Play Install Referrer             | **High**. Carries `gclid`, `fbclid`, `utm_*`, Meta referrer. |
| `meta_install_ref`                                             | Meta content provider             | **High** for Meta ads.                                       |
| `device_id`                                                    | `Settings.Secure.ANDROID_ID`      | Recommended. Matching fallback.                              |
| `device_ip`                                                    | Network interfaces                | Recommended. IP matching fallback.                           |
| `user_agent`                                                   | `WebSettings.getDefaultUserAgent` | Recommended. Fingerprint matching.                           |
| `app_version`, `build_number`, `bundle_id`, `application_name` | `PackageManager`                  | Recommended.                                                 |
| `manufacturer`, `brand`, `device_name`, `system_version`       | `Build`                           | Recommended.                                                 |
| `connectivity`, `carrier`                                      | System services                   | Optional.                                                    |
| `appsetid`, `appsetid_scope`                                   | `AppSet`                          | Optional.                                                    |

<Warning>
  If you send only the basics and skip `gaid`, `install_ref`, and `meta_install_ref`, install registration still works, but paid attribution for Google and Meta will be weak or missing.
</Warning>

## Advertising ID (GAID)

The Google Advertising ID is the primary signal for Google Ads and device matching. Read it off the main thread.

```kotlin theme={null}
fun gaid(context: Context): String? = try {
    val info = AdvertisingIdClient.getAdvertisingIdInfo(context)
    if (info.isLimitAdTrackingEnabled) null else info.id
} catch (e: Exception) { null }
```

It returns `null` when the user has limited ad tracking. If your app targets children, do not collect the GAID and remove the `AD_ID` permission. See the [SDK guidance on AAID](/sdk/android#disabling-aaid-collection).

## Google Play Install Referrer

The install referrer is the single most valuable attribution signal on Android. It carries the `gclid`, `fbclid`, `utm_*` parameters, and the Meta encrypted referrer from the Play Store click that led to the install.

```kotlin theme={null}
suspend fun installReferrer(context: Context): JSONObject? = withContext(Dispatchers.IO) {
    suspendCancellableCoroutine { cont ->
        val client = InstallReferrerClient.newBuilder(context).build()
        client.startConnection(object : InstallReferrerStateListener {
            override fun onInstallReferrerSetupFinished(code: Int) {
                try {
                    if (code == InstallReferrerClient.InstallReferrerResponse.OK) {
                        val r = client.installReferrer
                        cont.resume(JSONObject().apply {
                            put("install_ref", r.installReferrer ?: "")
                            put("install_ref_install_version", r.installVersion ?: "")
                            put("install_ref_installBeginTimestampSeconds", r.installBeginTimestampSeconds)
                            put("install_ref_referrerClickTimestampSeconds", r.referrerClickTimestampSeconds)
                            put("install_ref_googlePlayInstantParam", r.googlePlayInstantParam)
                        })
                    } else cont.resume(null)
                } catch (e: Exception) {
                    cont.resume(null)
                } finally {
                    runCatching { client.endConnection() }
                }
            }
            override fun onInstallReferrerServiceDisconnected() {
                if (cont.isActive) cont.resume(null)
            }
        })
        cont.invokeOnCancellation { runCatching { client.endConnection() } }
    }
}
```

<Tip>
  The install referrer is available right after install. Read it once on first launch, send it with `init`, and cache it. The Play Store keeps it only briefly, so do not delay the first read.
</Tip>

## Meta Install Referrer

For Meta (Facebook and Instagram) attribution, query the Meta install referrer from the installed Meta app. It needs your Facebook App ID in the manifest and the `<queries>` block above.

```xml theme={null}
<application>
    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb1234567890" />
    <!-- If you do not use the Facebook SDK, use this key instead: -->
    <!-- <meta-data android:name="com.linkrunner.FacebookApplicationId" android:value="1234567890" /> -->
</application>
```

```kotlin theme={null}
fun metaInstallReferrer(context: Context): JSONObject? {
    val appId = facebookAppId(context) ?: return null
    val providers = listOf(
        "com.facebook.katana.provider.InstallReferrerProvider" to "facebook",
        "com.instagram.contentprovider.InstallReferrerProvider" to "instagram",
        "com.facebook.lite.provider.InstallReferrerProvider" to "facebook_lite",
    )
    for ((authority, source) in providers) {
        if (context.packageManager.resolveContentProvider(authority, 0) == null) continue
        val uri = Uri.parse("content://$authority/$appId")
        context.contentResolver.query(
            uri, arrayOf("install_referrer", "is_ct", "actual_timestamp"), null, null, null
        )?.use { c ->
            if (c.moveToFirst()) {
                val refIdx = c.getColumnIndex("install_referrer")
                val ref = if (refIdx >= 0) c.getString(refIdx) else null
                if (!ref.isNullOrEmpty()) return JSONObject().apply {
                    put("install_referrer", ref)
                    put("source", source)
                    c.getColumnIndex("is_ct").let { if (it >= 0) put("is_ct", c.getInt(it)) }
                    c.getColumnIndex("actual_timestamp").let { if (it >= 0) put("actual_timestamp", c.getLong(it)) }
                }
            }
        }
    }
    return null
}

fun facebookAppId(context: Context): String? = try {
    val meta = context.packageManager
        .getApplicationInfo(context.packageName, PackageManager.GET_META_DATA).metaData
    meta?.getString("com.facebook.sdk.ApplicationId")
        ?: meta?.getString("com.linkrunner.FacebookApplicationId")
} catch (e: Exception) { null }
```

See [Meta Install Referrer](/features/meta-install-referrer) for how Linkrunner uses this signal.

## Everything else

These are plain system lookups. The [full client](/sdk-less/android-quickstart) includes them.

* `device_id`: `Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)`
* `device_ip`: first non-loopback IPv4 from `NetworkInterface.getNetworkInterfaces()`
* `user_agent`: `WebSettings.getDefaultUserAgent(context)`
* `manufacturer`, `brand`, `device_name`, `system_version`: `Build.MANUFACTURER`, `Build.BRAND`, `Build.MODEL`, `Build.VERSION.RELEASE`
* App info: `PackageManager.getPackageInfo` for `app_version` and `build_number`, `context.packageName` for `bundle_id`

**Need help?** Contact [support@linkrunner.io](mailto:support@linkrunner.io)
