Как передавать utm_source и атрибутировать установки в Android
Краткий ответ: используйте Google Play Install Referrer API, извлеките utm_source при первом запуске, сохраните в локальном хранилище и передайте в Firebase/AppsFlyer/Adjust и на бэкенд для server-side атрибуции. Ниже — конкретные шаги с кодом и тестами.
Как извлекать UTM из Install Referrer
- Подключите библиотеку в build.gradle (app):
dependencies {
implementation 'com.android.installreferrer:installreferrer:2.2'
}
- Пример чтения реферера в Application (однократно при старте):
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
fetchInstallReferrer()
}
private fun fetchInstallReferrer() {
val prefs = getSharedPreferences("install_prefs", MODE_PRIVATE)
if (prefs.getBoolean("referrer_processed", false)) return
val client = InstallReferrerClient.newBuilder(this).build()
client.startConnection(object : InstallReferrerStateListener {
override fun onInstallReferrerSetupFinished(responseCode: Int) {
when (responseCode) {
InstallReferrerClient.InstallReferrerResponse.OK -> {
val response = client.installReferrer
val referrer = response.installReferrer // e.g. "utm_source=google&utm_medium=cpc"
parseAndSave(referrer)
client.endConnection()
}
else -> client.endConnection()
}
}
override fun onInstallReferrerServiceDisconnected() {}
})
}
private fun parseAndSave(referrer: String?) {
if (referrer.isNullOrEmpty()) return
val uri = Uri.parse("http://dummy?$referrer")
val source = uri.getQueryParameter("utm_source")
if (!source.isNullOrEmpty()) {
getSharedPreferences("install_prefs", MODE_PRIVATE)
.edit()
.putString("utm_source", source)
.putBoolean("referrer_processed", true)
.apply()
}
}
}
Не забудьте указать android:name=".MyApplication" в AndroidManifest.xml.
Если Install Referrer не доступен (response != OK), используйте fallback: проверьте Intent из deep link при первом запуске и сохраните utm-параметры.
Как передавать utm_source в аналитику и сервер
- Сохраните utm_source в SharedPreferences/EncryptedSharedPreferences сразу после парсинга — это важно для последующих сессий и LTV-анализа.
- Отправляйте в Firebase:
val params = Bundle().apply {
putString("utm_source", source)
}
FirebaseAnalytics.getInstance(context).logEvent("install_attributed", params)
FirebaseAnalytics.getInstance(context).setUserProperty("utm_source", source)
- Отправляйте на ваш сервер вместе с первым opens/регистрацией для сквозной аналитики (server-side атрибуция), чтобы связывать установку и платежи.
- Для коммерческих SDK (AppsFlyer/Adjust) передавайте результаты парсинга или используйте их встроенные механизмы, если они получают Install Referrer напрямую.
Совет: логируйте install_date и идентификатор устройства/сессии для дедупликации на сервере.
Тестирование и проверка
- Симуляция через adb: adb shell am start -a android.intent.action.VIEW -d "https://play.google.com/store/apps/details?id=your.app&referrer=utm_source%3Dtest"
- Проверяйте на реальном устройстве/деньг. аккаунте Play, потому что эмуляторы/другие магазины могут вести себя иначе.
- Логируйте результат парсинга в релизных логах/экспортируйте события в staging-аналитику.
Не обрабатывать referrer на каждом запуске — это приведет к дублирующим событиям. Помечайте в prefs, что реферер уже сохранён.
Сравнение подходов (кратко)
- Install Referrer — бесплатный и надежный для utm_source при установках из Google Play.
- SDK (AppsFlyer/Adjust) — удобны для сквозной аналитики и ретрибуции, но могут требовать интеграции сервер-сервер.
- Server-side атрибуция — лучший запасной план для ограничения IDFA/ADID и для контроля качества данных.
Частые ошибки
- Чтение реферера не один раз: забывают сохранять флаг и дублят события.
- Неправильный парсинг: не декодируют URL-энкодинг, пропускают & или =.
- Ожидание реферера от всех магазинов: Install Referrer работает только для Google Play.
- Игнорирование приватности и GDPR: храните минимум данных и сообщайте в политике приватности.
FAQ
-
Нужно ли просить разрешения у пользователя для чтения реферера?
Нет, Install Referrer не требует дополнительных runtime permissions, но данные используют в соответствии с политикой конфиденциальности. -
Что делать, если utm_source пустой?
Считать установку "органической" и использовать server-side или SDK-атрибуцию для доузнавания, если есть сопоставимые события/платежи. -
Как связать utm_source с LTV?
Сохраняйте utm_source как user property и отправляйте на сервер вместе с событиями покупки; агрегируйте LTV по этому ключу.