Updated on 2026-08-14
This commit is contained in:
parent
e904e54848
commit
b2fbe74220
14 changed files with 121 additions and 32 deletions
|
|
@ -19,6 +19,7 @@ import com.tangem.common.routing.AppRouter
|
|||
import com.tangem.core.abtests.manager.ABTestsManager
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.core.analytics.filter.AppsFlyerEventFilter
|
||||
import com.tangem.core.analytics.filter.OneTimeEventFilter
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
|
|
@ -423,6 +424,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration.
|
|||
factory.addHandlerBuilder(AppsFlyerAnalyticsHandler.Builder())
|
||||
|
||||
factory.addFilter(oneTimeEventFilter)
|
||||
factory.addFilter(AppsFlyerEventFilter())
|
||||
|
||||
val buildData = AnalyticsHandlerBuilder.Data(
|
||||
application = application,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.common.analytics.handlers.amplitude
|
|||
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsUserIdHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AmplitudeAnalyticsHandler(
|
||||
|
|
@ -9,7 +10,6 @@ class AmplitudeAnalyticsHandler(
|
|||
) : AnalyticsHandler, AnalyticsUserIdHandler {
|
||||
|
||||
override fun id(): String = ID
|
||||
|
||||
override fun setUserId(userId: String) {
|
||||
client.setUserId(userId)
|
||||
}
|
||||
|
|
@ -18,8 +18,8 @@ class AmplitudeAnalyticsHandler(
|
|||
client.clearUserId()
|
||||
}
|
||||
|
||||
override fun send(eventId: String, params: Map<String, String>) {
|
||||
client.logEvent(eventId, params)
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
client.logEvent(event.id, event.params)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package com.tangem.tap.common.analytics.handlers.appsflyer
|
|||
import android.content.Context
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.tangem.core.analytics.api.EventLogger
|
||||
import com.tangem.core.analytics.api.UserIdHolder
|
||||
import com.tangem.tap.common.analytics.handlers.firebase.UnderscoreAnalyticsEventConverter
|
||||
|
||||
interface AppsFlyerAnalyticsClient : EventLogger
|
||||
interface AppsFlyerAnalyticsClient : EventLogger, UserIdHolder
|
||||
|
||||
internal class AppsFlyerClient(
|
||||
private val context: Context,
|
||||
|
|
@ -13,6 +15,7 @@ internal class AppsFlyerClient(
|
|||
) : AppsFlyerAnalyticsClient {
|
||||
|
||||
private val appsFlyerLib: AppsFlyerLib = AppsFlyerLib.getInstance()
|
||||
private val eventConverter = UnderscoreAnalyticsEventConverter()
|
||||
|
||||
init {
|
||||
appsFlyerLib.init(key, null, context)
|
||||
|
|
@ -20,7 +23,19 @@ internal class AppsFlyerClient(
|
|||
appsFlyerLib.start(context)
|
||||
}
|
||||
|
||||
override fun setUserId(userId: String) {
|
||||
appsFlyerLib.setCustomerUserId(userId)
|
||||
}
|
||||
|
||||
override fun clearUserId() {
|
||||
appsFlyerLib.setCustomerUserId(null)
|
||||
}
|
||||
|
||||
override fun logEvent(event: String, params: Map<String, String>) {
|
||||
appsFlyerLib.logEvent(context, event, params)
|
||||
appsFlyerLib.logEvent(
|
||||
context,
|
||||
event,
|
||||
eventConverter.convertEventParams(params),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,38 @@
|
|||
package com.tangem.tap.common.analytics.handlers.appsflyer
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsUserIdHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerOnlyEvent
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AppsFlyerAnalyticsHandler(
|
||||
private val client: AppsFlyerAnalyticsClient,
|
||||
) : AnalyticsHandler {
|
||||
) : AnalyticsHandler, AnalyticsUserIdHandler {
|
||||
|
||||
override fun id(): String = ID
|
||||
|
||||
override fun send(eventId: String, params: Map<String, String>) {
|
||||
client.logEvent(eventId, params)
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
when (event) {
|
||||
is AppsFlyerOnlyEvent -> {
|
||||
client.logEvent(event.id, event.params)
|
||||
}
|
||||
is AppsFlyerIncludedEvent -> {
|
||||
client.logEvent(
|
||||
event = AnalyticsEvent(category = event.category, event = event.appsFlyerReplacedEvent).id,
|
||||
params = event.params,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
super.send(event)
|
||||
override fun setUserId(userId: String) {
|
||||
client.setUserId(userId)
|
||||
}
|
||||
|
||||
override fun clearUserId() {
|
||||
client.clearUserId()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
@ -23,12 +40,10 @@ class AppsFlyerAnalyticsHandler(
|
|||
}
|
||||
|
||||
class Builder : AnalyticsHandlerBuilder {
|
||||
override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler? = null
|
||||
// disabled for now until analytics strategy is defined
|
||||
// when {
|
||||
// !data.isDebug -> AppsFlyerClient(data.application, data.config.appsFlyerApiKey, data.config.appsAppId)
|
||||
// data.isDebug && data.logConfig.appsflyer -> AppsFlyerLogClient(data.jsonConverter)
|
||||
// else -> null
|
||||
// }?.let { AppsFlyerAnalyticsHandler(it) }
|
||||
override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler? = when {
|
||||
!data.isDebug -> AppsFlyerClient(data.application, data.config.appsFlyerApiKey, data.config.appsAppId)
|
||||
data.isDebug && data.logConfig.isAppsflyerLogEnabled -> AppsFlyerLogClient(data.jsonConverter)
|
||||
else -> null
|
||||
}?.let { AppsFlyerAnalyticsHandler(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -12,4 +12,12 @@ internal class AppsFlyerLogClient(
|
|||
override fun logEvent(event: String, params: Map<String, String>) {
|
||||
logger.logEvent(event, params)
|
||||
}
|
||||
|
||||
override fun setUserId(userId: String) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
override fun clearUserId() {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics.handlers.firebase
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsErrorHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsExceptionHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsUserIdHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
|
||||
|
|
@ -25,8 +25,8 @@ class FirebaseAnalyticsHandler(
|
|||
client.clearUserId()
|
||||
}
|
||||
|
||||
override fun send(eventId: String, params: Map<String, String>) {
|
||||
client.logEvent(eventId, params)
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
client.logEvent(event.id, event.params)
|
||||
}
|
||||
|
||||
override fun sendException(event: ExceptionAnalyticsEvent) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ internal class FirebaseClient : FirebaseAnalyticsClient {
|
|||
private val fbAnalytics = Firebase.analytics
|
||||
private val fbCrashlytics = Firebase.crashlytics
|
||||
|
||||
private val eventConverter = FirebaseAnalyticsEventConverter()
|
||||
private val eventConverter = UnderscoreAnalyticsEventConverter()
|
||||
|
||||
override fun setUserId(userId: String) {
|
||||
Firebase.analytics.setUserId(userId)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.handlers.firebase
|
||||
|
||||
internal class FirebaseAnalyticsEventConverter {
|
||||
internal class UnderscoreAnalyticsEventConverter {
|
||||
|
||||
fun convertEventName(event: String): String {
|
||||
return convertString(event, FIREBASE_EVENT_NAME_MAX_LENGTH)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.core.analytics.models
|
||||
|
||||
/**
|
||||
* Marker interface for AppsFlyer events
|
||||
* Only events implementing this interface will be sent to AppsFlyer
|
||||
*/
|
||||
interface AppsFlyerOnlyEvent
|
||||
|
||||
/**
|
||||
* Marker interface for AppsFlyer included events
|
||||
* Events implementing this interface will be sent to AppsFlyer along with other analytics handlers
|
||||
*/
|
||||
interface AppsFlyerIncludedEvent {
|
||||
val appsFlyerReplacedEvent: String
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.core.analytics.models.event
|
|||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerOnlyEvent
|
||||
|
||||
sealed class OnboardingAnalyticsEvent(
|
||||
category: String,
|
||||
|
|
@ -14,6 +16,8 @@ sealed class OnboardingAnalyticsEvent(
|
|||
params: Map<String, String> = mapOf(),
|
||||
) : OnboardingAnalyticsEvent(category = "Onboarding", event = event, params = params) {
|
||||
|
||||
class AppsFlyerOnlyEntryScreenView : Onboarding(event = "wallet_entry_screen_view"), AppsFlyerOnlyEvent
|
||||
|
||||
class Started(
|
||||
source: String,
|
||||
) : Onboarding(
|
||||
|
|
@ -64,7 +68,12 @@ sealed class OnboardingAnalyticsEvent(
|
|||
put("Seed Phrase Length", seedPhraseLength.toString())
|
||||
}
|
||||
},
|
||||
)
|
||||
), AppsFlyerIncludedEvent {
|
||||
override val appsFlyerReplacedEvent = when (creationType) {
|
||||
WalletCreationType.NewSeed -> "wallet_created_successfully"
|
||||
WalletCreationType.SeedImport -> "wallet_imported"
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WalletCreationType(val value: String) {
|
||||
data object NewSeed : WalletCreationType(value = "New Seed")
|
||||
|
|
@ -85,6 +94,7 @@ sealed class OnboardingAnalyticsEvent(
|
|||
AnalyticsParam.SOURCE to source,
|
||||
),
|
||||
)
|
||||
|
||||
class ButtonImportWallet : SeedPhrase("Button - Import Wallet")
|
||||
class ImportSeedPhraseScreenOpened : SeedPhrase("Import Seed Phrase Screen Opened")
|
||||
class ButtonImport : SeedPhrase("Button - Import")
|
||||
|
|
|
|||
|
|
@ -27,11 +27,7 @@ interface AnalyticsHandler : AnalyticsEventHandler {
|
|||
|
||||
fun id(): String
|
||||
|
||||
fun send(eventId: String, params: Map<String, String> = emptyMap())
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
send(event.id, event.params)
|
||||
}
|
||||
override fun send(event: AnalyticsEvent)
|
||||
}
|
||||
|
||||
interface AnalyticsHandlerHolder {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.core.analytics.filter
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.AppsFlyerOnlyEvent
|
||||
|
||||
class AppsFlyerEventFilter : AnalyticsEventFilter {
|
||||
|
||||
override fun canBeAppliedTo(event: AnalyticsEvent): Boolean =
|
||||
event is AppsFlyerOnlyEvent || event is AppsFlyerIncludedEvent
|
||||
|
||||
override suspend fun canBeSent(event: AnalyticsEvent): Boolean = true
|
||||
|
||||
override fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean {
|
||||
return when (event) {
|
||||
is AppsFlyerOnlyEvent -> handler.id() == "AppsFlyer"
|
||||
is AppsFlyerIncludedEvent -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,9 +60,8 @@ internal class CreateMobileWalletModel @Inject constructor(
|
|||
|
||||
init {
|
||||
trackingContextProxy.addHotWalletContext()
|
||||
analyticsEventHandler.send(
|
||||
event = OnboardingAnalyticsEvent.Onboarding.Started(source = params.source),
|
||||
)
|
||||
analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.Started(source = params.source))
|
||||
analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.AppsFlyerOnlyEntryScreenView())
|
||||
analyticsEventHandler.send(
|
||||
event = OnboardingAnalyticsEvent.SeedPhrase.CreateMobileScreenOpened(source = params.source),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.onboarding.v2.common.analytics
|
|||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
|
||||
sealed class OnboardingEvent(
|
||||
category: String,
|
||||
|
|
@ -33,7 +34,12 @@ sealed class OnboardingEvent(
|
|||
put("Seed Phrase Length", seedPhraseLength.toString())
|
||||
}
|
||||
},
|
||||
)
|
||||
), AppsFlyerIncludedEvent {
|
||||
override val appsFlyerReplacedEvent = when (creationType) {
|
||||
WalletCreationType.NewSeed, WalletCreationType.PrivateKey -> "wallet_created_successfully"
|
||||
WalletCreationType.SeedImport -> "wallet_imported"
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WalletCreationType(val value: String) {
|
||||
data object PrivateKey : WalletCreationType(value = "Private Key")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue