Open LupusX5 opened 2 years ago
Partly resolved: the issues with getting the converision data and sharing it with the server is fixed. However I'm still searching for better option to pass the conversion data to the url. Within a few days may come up with a solution and will share the code.
I guess the best place to document the AppsFlyer flow is in the AppsFlyer docs themselves. Nevertheless, any updates here?
I guess the best place to document the AppsFlyer flow is in the AppsFlyer docs themselves. Nevertheless, any updates here?
Programming language used in this comment: Kotlin.
Hello! Yep. I have managed to use it with Chrome Custom Tabs, but not still figured out how to do that with the TWA. The issue is that for Chrome Custom Tabs I see the way of using it, and in TWA there's one thing that doesn't let me to get normally the idea.
So this is the problematic place for me:
class LauncherActivity : LauncherActivity() {
override fun getLaunchingUrl(): Uri {
val uri = super.getLaunchingUrl()
val appsFlyerId = AppsFlyerLib.getInstance().getAppsFlyerUID(this)
uri
.buildUpon()
.appendQueryParameter("appsflyer_id", appsFlyerId)
.build()
return uri
}
...
}
So what's the issue here. The issue is that I can't launch this code or any of its parts inside an AppsFlyer caller function.
Let me show you what I'm talking about with a working example. Here in this case I can do what I need, but I need it for TWA as well :) I guess many people would love to have it as it makes marketing more efficient.
package com.example.app
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.appsflyer.AppsFlyerConversionListener
import com.appsflyer.AppsFlyerLib
import androidx.browser.customtabs.CustomTabsClient
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsServiceConnection
import androidx.browser.customtabs.CustomTabsSession
import android.net.Uri
import com.example.app.R
import android.content.ComponentName
import android.graphics.Color
class MainActivity : AppCompatActivity() {
val CUSTOM_TAB_PACKAGE_NAME = "com.android.chrome";
lateinit var webView: WebView
private val host = "https://example.com"
private val baseUrl = "${host}/?"
private val errorUrl = "${host}/?error=error-appsflyer-not-working"
private var mCustomTabsServiceConnection: CustomTabsServiceConnection? = null
private var mClient: CustomTabsClient? = null
private var mCustomTabsSession: CustomTabsSession? = null
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
supportActionBar!!.hide()
setContentView(R.layout.activity_main)
// A container function inside of which the AppsFlyer Caller function is fired, which contains a nested Chrome Custom Tabs
// function to ALWAYS get the data from appsflyer.
stack()
mCustomTabsServiceConnection = object : CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(componentName: ComponentName, customTabsClient: CustomTabsClient) {
//Pre-warming
mClient = customTabsClient
mClient?.warmup(0L)
mCustomTabsSession = mClient?.newSession(null)
}
override fun onServiceDisconnected(name: ComponentName) {
mClient = null
}
}
CustomTabsClient.bindCustomTabsService(this, CUSTOM_TAB_PACKAGE_NAME,
mCustomTabsServiceConnection as CustomTabsServiceConnection
);
}
// placing AppsFlyer Caller function to a separate function to launch some more useful functions
// in future
private fun stack() {
AFcaller()
}
// AppsFlyer Caller function
private fun AFcaller() {
// InstallReferrer.installerReferrer(applicationContext)
val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener {
/* Returns the attribution data. Note - the same conversion data is returned every time per install */
override fun onConversionDataSuccess(conversionData: Map<String, Any>) {
// setting conversion data to the companion object
setInstallData(conversionData)
// getting conversion data from the companion object and adding it to the
// base URL
loadCustomTabForSite(baseUrl+InstallConversionData)
}
override fun onConversionDataFail(errorMessage: String) {
loadCustomTabForSite(errorUrl)
}
/* Called only when a Deep Link is opened */
override fun onAppOpenAttribution(conversionData: Map<String, String>) {
for (attrName in conversionData.keys) {
loadCustomTabForSite(baseUrl+InstallConversionData)
}
}
override fun onAttributionFailure(errorMessage: String) {
loadCustomTabForSite(errorUrl)
}
}
/* This API enables AppsFlyer to detect installations, sessions, and updates. */
AppsFlyerLib.getInstance()
.init(AF_DEV_KEY, conversionListener, applicationContext)
AppsFlyerLib.getInstance().start(this)
/* Set to true to see the debug logs. Comment out or set to false to stop the function */AppsFlyerLib.getInstance()
.setDebugLog(true)
}
// This function allows me to do what the in-built TWA function doesn't allow: use it in other
// functions and pass the needed url as a parameter. In case with TWA it would be the same url all the
// time, but what's really needed is to pass the parameters in a timely manner to the url, from where
// JavaScript on the webpage will read the conversion data and will display promotions to the users
// based on this data.
fun loadCustomTabForSite(url: String) {
val customTabsIntent = CustomTabsIntent.Builder(mCustomTabsSession)
.setShowTitle(true)
.build()
customTabsIntent.launchUrl(this, Uri.parse(url))
}
companion object {
private const val AF_DEV_KEY = "KEY"
var InstallConversionData = ""
var sessionCount = 0
fun setInstallData(conversionData: Map<String, Any>) {
if (sessionCount == 0) {
val googlePlayInstallReferrer = """&googlePlayInstallReferrer=${conversionData["gp_referrer"]}""".trimIndent()
val installCampaign = """&campaign=${conversionData["campaign"]}""".trimIndent()
val adsetInfo = """&adset=${conversionData["adset"]}""".trimIndent()
val adName = """&afadname=${conversionData["af_ad"]}""".trimIndent()
val afAdset = """&afadset=${conversionData["af_adset"]}""".trimIndent()
val installType = """install_type=${conversionData["af_status"]}""".trimIndent()
val mediaSource = """&media_source=${conversionData["media_source"]}""".trimIndent()
val installTime = """&install_time=${conversionData["install_time"]}""".trimIndent()
val clickTime = """&click_time=${conversionData["click_time"]}""".trimIndent()
val isFirstLaunch = """&is_first_launch=${conversionData["is_first_launch"]}""".trimIndent()
val advertisingId = """&advertising_id=${conversionData["advertising_id"]}""".trimIndent()
val timeStamp = """×tamp=${conversionData["ts"]}""".trimIndent()
InstallConversionData += installType +
googlePlayInstallReferrer +
installCampaign +
adsetInfo +
adName +
afAdset +
mediaSource +
installTime +
clickTime +
isFirstLaunch +
advertisingId +
timeStamp
sessionCount++
}
}
}
override fun onBackPressed() {
if (webView.canGoBack()) {
webView.goBack()
} else {
super.onBackPressed()
}
}
}
Hello @LupusX5. Were you able to resolve this issue and get conversation data on the TWA?
I have created an app using Bubblewrap, with the enabled feature of Appsflyer – it's needed to receive the google play referrer information.
But I have kind of unexpected behaviour:
When I launch the app the following happens: on open the app opens a url with the
appsflyer_id
query parameter. I.e. the following url is being opened: https://angus.surge.sh/?appsflyer_id=xxxxxxxx. However, it doesn't receive any cookies in response afterwards as expected according to Appsflyer documentation.Screenshot №1 + source URL: https://support.appsflyer.com/hc/en-us/articles/360002330178-Using-AppsFlyer-with-TWA#append-appsflyer-id-and-customer-user-id-to-url:
Screenshot №2: expected cookies on the client side (the same source as Screenshot №1):
And this is my source code: https://github.com/LupusX5/twa-demo
Could you please help solve this issue?