Android Onboarding Analytics: Track Onboarding Drop-off in Kotlin
Android apps face unique onboarding challenges: device diversity, Google Play install flows, and permission models that differ by Android version. Here's how to instrument your onboarding flow and measure where users leave.
Android-specific onboarding challenges
Device fragmentation. Android runs on thousands of device configurations. A layout that works on a Pixel 7 may break on a budget Samsung running Android 10. If you see unusually high drop-off at a specific step, check whether it correlates with device manufacturer or Android version.
Google Play install flow. Define the first funnel entry consistently. For an in-app onboarding funnel, a first app open is usually a more direct entry event than a store install because it represents a user who reached the product.
Permission model. Android's runtime permissions differ from iOS. On Android 13+, push notifications require explicit permission (similar to iOS). On older versions, push was granted by default. If your user base spans Android versions, track permission grant/deny separately.
Back button behavior. Android's back button can disrupt onboarding if tapping back exits a step the user was supposed to complete. Make sure back navigation within onboarding steps is handled intentionally.
Install the SDK
Add to your build.gradle (app module):
dependencies {
implementation("dev.getonramp:android-sdk:1.0.0")
}
Sync your project.
Initialise in Application class
// MyApplication.kt
import android.app.Application
import dev.getonramp.OnRamp
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
OnRamp.initialize(
context = this,
apiKey = BuildConfig.ONRAMP_API_KEY
)
}
}
Add your Application class to AndroidManifest.xml:
<application
android:name=".MyApplication"
...>
✓ Tip
Store your API key in local.properties and reference it in build.gradle via BuildConfig. This keeps it out of source control.
Track onboarding steps
import dev.getonramp.OnRamp
class SignupFragment : Fragment() {
private fun handleSignup(email: String, password: String) {
lifecycleScope.launch {
try {
authRepository.createAccount(email, password)
// Fire after the action succeeds
OnRamp.step("account_created")
navigateToNextStep()
} catch (e: Exception) {
OnRamp.step("account_creation_failed", mapOf(
"error_type" to e.javaClass.simpleName
))
showError(e.message)
}
}
}
}
With Compose:
import dev.getonramp.OnRamp
@Composable
fun SignupScreen(onSuccess: () -> Unit) {
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
try {
createAccount(email, password)
OnRamp.step("account_created")
onSuccess()
} catch (e: Exception) {
OnRamp.step("account_creation_failed")
}
}
}) {
Text("Create account")
}
}
Track permission outcomes
// Push notifications (Android 13+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissions(
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
NOTIFICATION_PERMISSION_CODE
)
}
// In onRequestPermissionsResult:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
if (requestCode == NOTIFICATION_PERMISSION_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
OnRamp.step("push_permission_granted")
} else {
OnRamp.step("push_permission_denied")
}
}
}
Recommended step map for Android onboarding
| Step | Event name | When to fire |
|---|---|---|
| App first opened | app_first_open | In Application.onCreate, gated by SharedPreferences flag |
| Signup started | signup_started | On first tap of signup button |
| Account created | account_created | After successful account creation |
| Email verified | email_verified | When deep link intent returns to activity |
| Permission granted | push_permission_granted | In permission callback |
| First action | first_action | After user completes first core task |
Build the funnel
Open the OnRamp dashboard → Funnel → New funnel
Name it and add your Android app.
Add each step in order
Enter step names exactly as passed to OnRamp.step(). The funnel uses exact string matching.
Segment by Android version if needed
If you're seeing unexpected drop-off, add "android_version" as a property and split the funnel view to see whether specific Android versions are the cause.
Android-specific funnel signals to watch
Drop-off at email_verified higher than iOS? On Android, the back stack behavior when returning from the email client via deep link is less predictable. Check that your intent-filter for the deep link correctly returns to the right activity and fires the step event.
High drop-off on Android 10–11 at permission steps? These Android versions have different permission behavior for location and storage. Confirm your permission request code handles API level differences correctly.
Different completion rates by manufacturer? Samsung One UI, Xiaomi MIUI, and other heavily modified Android builds sometimes restrict background processes and battery optimization in ways that affect SDK event delivery. If you see a manufacturer-specific gap, check whether events are being batched and delivered correctly on those devices.
Android version breakdown
Funnel completion by version = filter funnel by android_version property
Example: completion 52% on Android 13+, 31% on Android 10–11 - likely a layout or permission issue on older OS
Android onboarding analytics
See where Android users drop off
The OnRamp Android SDK works with Activities, Fragments, and Compose. Per-step funnel, session timelines, and retention cohorts - no backend setup required.
Start free trial →
