AmiLink Integration Guide
A lightweight, dependency-free integration approach. Copy-paste our native helpers to handle URL resolution, capture attribution events, and report real-time analytics.
1. Register Your App
Create an Application in your dashboard and specify Android/iOS details.
2. Domain verification
AmiLink auto-hosts assetlinks.json & apple-app-site-association files.
3. Native Analytics SDK
Embed the helper class below to fetch deferred redirects and report analytics.
Android Native SDK Code
Enable Android App Links and copy-paste the Kotlin helper class below to handle routing, deferred attribution, and analytics event logging.
1
Add App Link Intent Filter
Add this intent-filter inside the main activity tag of your AndroidManifest.xml:
AndroidManifest.xml
<!-- AndroidManifest.xml — inside your <activity> tag -->
<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" />
<!-- Use your verified custom domain from the AmiLink dashboard -->
<data android:scheme="https" android:host="your-custom-domain.com" />
</intent-filter>2
Create AmiLink.kt Helper Class
Add the full SDK class to your codebase for deferred attribution and automatic analytics reporting:
AmiLink.kt
package com.amilink.sdk
import android.content.Context
import android.os.Build
import android.provider.Settings
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.IOException
/**
* AmiLink Android SDK / Helper
*
* Lightweight implementation to handle Android App Links, Deferred Deep Linking,
* and background analytics reporting.
*/
object AmiLink {
private var workspaceId: String? = null
private val client = OkHttpClient()
private const val apiBase = "https://api.amilink.to/sdk" // AmiLink production API
/**
* Configure the SDK
*/
fun configure(workspaceId: String) {
this.workspaceId = workspaceId
}
/**
* Handle incoming App Links in your MainActivity
*/
fun handle(data: android.net.Uri?) {
data?.let {
val slug = it.lastPathSegment ?: return
reportEvent(EventType.OPEN, slug)
}
}
/**
* Check for deferred deep links on first cold start
*/
fun checkDeferred(context: Context, callback: (JSONObject?) -> Unit) {
val appId = context.packageName
val fingerprint = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
val json = JSONObject().apply {
put("applicationId", appId)
put("fingerprint", fingerprint)
put("platform", "Android")
put("os", "Android ${Build.VERSION.RELEASE}")
}
val request = Request.Builder()
.url("$apiBase/deferred")
.post(json.toString().toRequestBody("application/json".toMediaType()))
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback(null)
}
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string() ?: return callback(null)
val responseJson = JSONObject(body)
if (responseJson.optBoolean("match")) {
callback(responseJson.optJSONObject("data"))
} else {
callback(null)
}
}
})
}
/**
* Report analytics events (OPEN, INSTALL, CONVERSION)
*/
fun reportEvent(eventType: EventType, deepLinkSlug: String) {
val json = JSONObject().apply {
put("eventType", eventType.name)
put("deepLinkId", deepLinkSlug)
put("platform", "Android")
put("os", "Android ${Build.VERSION.RELEASE}")
}
val request = Request.Builder()
.url("$apiBase/events")
.post(json.toString().toRequestBody("application/json".toMediaType()))
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {}
override fun onResponse(call: Call, response: Response) {}
})
}
}
enum class EventType {
OPEN, INSTALL, CONVERSION
}