Deferred deep links let you send a user straight to a specific screen inside your app — a product page, an offer, a referral reward — even if the app isn't installed yet when they click the link. Once the app installs and opens for the first time, the user lands on the exact screen the link pointed to, instead of a generic home screen.
What changed: this guide has been refreshed for 2026 with updated Install Referrer library guidance, clearer handling of edge cases (null referrers, cold vs warm start), a dedicated testing section, and a troubleshooting checklist. The core integration steps and Smler API call remain the same.
In this guide, we'll walk you through:
Setting up the Install Referrer API
Handling the deep link after app install
Sending install data back to Smler
Routing users to the right screen using the link
Testing the flow and fixing the issues that most often break it
How Do Deferred Deep Links Work on Android with Smler?
When a user clicks a Smler deferred link and then installs your app from the Play Store, four things happen in sequence:
The Install Referrer string attached to the Play Store install contains the link metadata (query parameters like
pageor a full path).Your app reads this referrer string on first launch.
The app extracts the deep link from the referrer URL and tracks the deep link open by hitting the Smler endpoint.
The app redirects the user to the appropriate screen using the destination URL returned by the
/api/v1/shortendpoint.
If you haven't generated a deferred link yet, see the step-by-step guide to generating deferred deep links in Smler before wiring up the Android side below.
Step 1: Add the Install Referrer Dependency
Google's Install Referrer library is what gives you access to the referrer string. Add it to your module-level build.gradle:
dependencies {
implementation 'com.android.installreferrer:installreferrer:2.2'
}
This is the same library Google Play Services uses to expose install attribution data, and it's still the current, supported way to read the referrer — there's no newer replacement API as of this update.
Step 2: Build the Referrer Client Manager
This class does the actual work: it connects to the Install Referrer service, reads the referrer string once, stores a flag so it never runs twice, and forwards the data to Smler.
package `in`.smler.deferredlink import android.content.Context
import android.util.Log
import com.android.installreferrer.api.InstallReferrerClient
import com.android.installreferrer.api.InstallReferrerStateListener
import com.android.installreferrer.api.ReferrerDetails
import androidx.core.content.edit
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.net.URLEncoder
import java.net.HttpURLConnection
import java.net.URL
class InstallReferrerClientManager(private val context: Context) {
fun fetchReferrer() {
val prefs = context.getSharedPreferences("smler_preference", Context.MODE_PRIVATE)
val isFirstInstall = prefs.getBoolean("is_first_install", true)
if (!isFirstInstall) {
Log.d("ReferrerClient", "Not first install. Skipping referrer fetch.")
return
}
val referrerClient = InstallReferrerClient.newBuilder(context).build()
Log.d("ReferrerClient", "Starting connection...")
referrerClient.startConnection(object : InstallReferrerStateListener {
override fun onInstallReferrerSetupFinished(responseCode: Int) {
when (responseCode) { I
nstallReferrerClient.InstallReferrerResponse.OK -> {
val response: ReferrerDetails = referrerClient.installReferrer
val referrerUrl = response.installReferrer
Log.d("ReferrerClient", "Referrer URL: $referrerUrl")
// Save flag
prefs.edit { putBoolean("is_first_install", false) }
// Notify Smler
notifySmlerInstall(referrerUrl)
}
InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED -> Log.w("ReferrerClient", "Install Referrer not supported")
InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE -> Log.w("ReferrerClient", "Install Referrer service unavailable")
}
referrerClient.endConnection()
}
override fun onInstallReferrerServiceDisconnected() { Log.d("ReferrerClient", "Referrer service disconnected") }
})
}
private fun notifySmlerInstall(referrer: String) {
CoroutineScope(Dispatchers.IO).launch {
try {
val encoded = URLEncoder.encode(referrer, "UTF-8")
val url = URL("https://smler.in/api/v1/deferred-link/install?details=$encoded")
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"
val responseCode = conn.responseCode
Log.d("ReferrerClient", "Install ping response: $responseCode")
conn.disconnect()
} catch (e: Exception) {
Log.e("ReferrerClient", "Error notifying Smler", e)
}
}
}
Call fetchReferrer() once, from either your Application class or the first activity's onCreate(). The is_first_install flag in SharedPreferences is what stops it from firing on every app open — without it, you'd re-notify Smler on every cold start, which pollutes your attribution data.
Step 3: Handle Deep Link Navigation After Install
Once the app opens, the referrer tells you that a deferred link was clicked. The intent data tells you where to send the user. Add this to the activity that receives the launch intent:
private fun handleIntentDeepLink() {
val page = intent?.data?.getQueryParameter("page")
val fullUrl = intent?.data.toString()
Log.i("MainActivity", "Intent URL: $fullUrl")
Log.i("MainActivity", "Page Param: $page")
// Navigate to specific screen based on query param
when (page) {
"123" -> openOfferPage()
"home" -> openHome()
else -> handleUriFallback(fullUrl)
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent)
handleIntentDeepLink()
}
You can configure page=xyz in the Smler dashboard while creating the deferred link, or use the entire URI path to route users (e.g. /product/9876 → open the product page).
A few edge cases worth handling explicitly:
Cold start vs warm start:
onNewIntent()only fires if the activity is already running. On a true cold start (first launch after install), read the deep link data fromgetIntent()insideonCreate()as well.Null or empty referrer: if the user installed the app organically, the referrer will be empty or generic. Always fall back to your normal home screen rather than crashing on a null
pageparameter.Delayed referrer availability: on some devices the referrer isn't available for a few seconds after first launch. Don't block your splash screen indefinitely waiting for it — set a short timeout and fall back gracefully.
Step 4: Enable Deep Linking in AndroidManifest.xml
Your manifest needs to declare which links your app is allowed to open. This is required regardless of whether the link is deferred or a standard deep link:
<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="smler.in" android:pathPrefix="/your/custom/path" />
</intent-filter> <!--
Custom scheme like smler:// awesomeapp:// --> <intent-filter>
<data android:scheme="smler" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
Match the exact path structure you're using in Smler, and set android:autoVerify="true" if you want the link to open your app directly instead of showing a disambiguation dialog.
How Are Deferred Deep Links Different from Regular Deep Links?
A regular deep link only works if the app is already installed — the intent-filter in Step 4 handles those cases on its own, no referrer needed. A deferred deep link is the version that survives an app install in between: the click happens before the app exists on the device, and the destination is recovered afterwards using the Install Referrer data described above. If you're deciding which one your feature actually needs, the deferred vs regular deep linking comparison guide breaks down when each applies.
How to Test Deferred Deep Links Before Launch
Test the full install-to-navigation flow before shipping, not just the link click. Three ways to do it:
Play Install Referrer Test Tool: Google's official Play Install Referrer Test Tool lets you simulate a referrer string without going through an actual Play Store install — the fastest way to check your parsing logic.
Fresh install on a real device: uninstall the app completely, click your Smler deferred link, install from the Play Store, and confirm you land on the correct screen on first open.
ADB intent simulation: once the app is installed, you can fire a test intent directly with
adb shell am start -a android.intent.action.VIEW -d "https://smler.in/your/custom/path?page=123"to test navigation logic in isolation from the referrer flow.
For a broader testing checklist that covers regular deep links as well, see how to test deep links on Android.
Common Issues When Integrating Deferred Deep Links on Android
Referrer comes back empty: usually means the app was tested via a direct APK install (sideloaded) rather than through the Play Store, which is the only path that populates the referrer.
Navigation fires more than once: check that the
is_first_installflag is being written correctly and thatfetchReferrer()is only called from one place in your app.Wrong screen opens: double-check the query parameter names configured in the Smler dashboard match exactly what your
whenblock expects — a mismatched key silently falls through to your fallback case.Works on some devices, not others: a handful of OEM Android builds delay or restrict Install Referrer callbacks; always test on at least one non-Pixel device before launch.
Wrap-Up
By integrating Smler's deferred deep linking with the Google Install Referrer API, you ensure users land on the exact screen they expect — even after installing your app for the first time. It's simple, lightweight, and requires no third-party SDK. Configure it once, and track installs and navigation automatically from then on.
Building the iOS side of the same feature? Check the companion guide to integrating deferred deep links in your iOS app with Smler. And if you want the full conceptual background before you touch code, the Ultimate Guide to Deferred Deep Linking is a good place to start.
Start creating your deferred links here:
https://app.smler.in/app/deferred-link
FAQ: Deferred Deep Links on Android
Do I need a third-party SDK to implement deferred deep links on Android?
No. Google's Install Referrer library plus Smler's API call is enough to build the full flow described in this guide. Third-party attribution SDKs add extra cost and data collection that most apps don't need for this use case.
Why is my Install Referrer returning null or empty?
This almost always happens when the app was installed by sideloading an APK instead of through the Play Store, since the referrer is only populated on Play Store installs. It can also happen briefly right after install if you read it before the connection finishes.
Can deferred deep links work with a custom URL scheme instead of a domain?
Yes. The manifest example in Step 4 shows both an HTTPS domain-based intent-filter and a custom scheme (like smler://). Custom schemes are simpler to set up but don't support Android App Links verification, so the OS may prompt the user to choose an app.
How long after install does the referrer data stay valid?
Referrer data remains available for up to 90 days after installation. That's why this guide stores an is_first_install flag — to manage the user experience effectively during the initial onboarding process.
