diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt index fe2add9b71..a90e193a92 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt @@ -104,7 +104,6 @@ sealed class AnalyticsParam { const val PERMISSION_TYPE = "Permission Type" const val PRODUCT_TYPE = "Product Type" const val FIRMWARE = "Firmware" - const val USER_WALLET_ID = "User Wallet ID" const val CURRENCY = "Currency" const val ERROR_DESCRIPTION = "Error Description" const val ERROR_CODE = "Error Code" diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt index 2aa36c5413..d28504b612 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt @@ -1,14 +1,23 @@ 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.tap.common.analytics.api.AnalyticsHandlerBuilder class AmplitudeAnalyticsHandler( private val client: AmplitudeAnalyticsClient, -) : AnalyticsHandler { +) : AnalyticsHandler, AnalyticsUserIdHandler { override fun id(): String = ID + override fun setUserId(userId: String) { + client.setUserId(userId) + } + + override fun clearUserId() { + client.clearUserId() + } + override fun send(eventId: String, params: Map) { client.logEvent(eventId, params) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt index 74cec2eaf2..a5ffec919c 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt @@ -4,13 +4,14 @@ import android.app.Application import com.amplitude.api.Amplitude import com.amplitude.api.AmplitudeClient import com.tangem.core.analytics.api.EventLogger +import com.tangem.core.analytics.api.UserIdHolder import com.tangem.utils.converter.Converter import org.json.JSONObject /** [REDACTED_AUTHOR] */ -interface AmplitudeAnalyticsClient : EventLogger +interface AmplitudeAnalyticsClient : EventLogger, UserIdHolder internal class AmplitudeClient( application: Application, @@ -24,6 +25,14 @@ internal class AmplitudeClient( client.enableForegroundTracking(application) } + override fun setUserId(userId: String) { + client.setUserId(userId) + } + + override fun clearUserId() { + client.setUserId(null) + } + override fun logEvent(event: String, params: Map) { client.logEvent(event, ParamsToJSONObjectConverter().convert(params)) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeLogClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeLogClient.kt index f60d2edfcf..f24a5925a3 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeLogClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeLogClient.kt @@ -12,6 +12,16 @@ internal class AmplitudeLogClient( private val logger: AnalyticsEventsLogger = AnalyticsEventsLogger(AmplitudeAnalyticsHandler.ID, jsonConverter) + private var userId: String? = null + + override fun setUserId(userId: String) { + this.userId = userId + } + + override fun clearUserId() { + this.userId = null + } + override fun logEvent(event: String, params: Map) { logger.logEvent(event, params) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt index 298874dcef..fbea91a9f4 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt @@ -3,6 +3,7 @@ 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.AnalyticsUserIdHandler import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder @@ -10,12 +11,20 @@ import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter class FirebaseAnalyticsHandler( private val client: FirebaseAnalyticsClient, -) : AnalyticsHandler, AnalyticsErrorHandler, AnalyticsExceptionHandler { +) : AnalyticsHandler, AnalyticsErrorHandler, AnalyticsExceptionHandler, AnalyticsUserIdHandler { private val errorConverter = AnalyticsErrorConverter() override fun id(): String = ID + override fun setUserId(userId: String) { + client.setUserId(userId) + } + + override fun clearUserId() { + client.clearUserId() + } + override fun send(eventId: String, params: Map) { client.logEvent(eventId, params) } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt index 06ccf50709..6268ebf230 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt @@ -8,11 +8,12 @@ import com.google.firebase.crashlytics.recordException import com.google.firebase.ktx.Firebase import com.tangem.core.analytics.api.ExceptionLogger import com.tangem.core.analytics.api.EventLogger +import com.tangem.core.analytics.api.UserIdHolder /** [REDACTED_AUTHOR] */ -interface FirebaseAnalyticsClient : EventLogger, ExceptionLogger +interface FirebaseAnalyticsClient : EventLogger, ExceptionLogger, UserIdHolder internal class FirebaseClient : FirebaseAnalyticsClient { @@ -21,6 +22,14 @@ internal class FirebaseClient : FirebaseAnalyticsClient { private val eventConverter = FirebaseAnalyticsEventConverter() + override fun setUserId(userId: String) { + Firebase.analytics.setUserId(userId) + } + + override fun clearUserId() { + Firebase.analytics.setUserId(null) + } + override fun logEvent(event: String, params: Map) { fbAnalytics.logEvent( eventConverter.convertEventName(event), diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseLogClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseLogClient.kt index 4b818bdf51..391b7e7470 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseLogClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseLogClient.kt @@ -11,6 +11,15 @@ internal class FirebaseLogClient( ) : FirebaseAnalyticsClient { private val logger: AnalyticsEventsLogger = AnalyticsEventsLogger(FirebaseAnalyticsHandler.ID, jsonConverter) + private var userId: String? = null + + override fun setUserId(userId: String) { + this.userId = userId + } + + override fun clearUserId() { + this.userId = null + } override fun logEvent(event: String, params: Map) { logger.logEvent(event, params) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt index 42a7f46c75..f0f3326917 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt @@ -40,9 +40,6 @@ class CardContextInterceptor( params[AnalyticsParam.BATCH] = card.batchId params[AnalyticsParam.PRODUCT_TYPE] = getProductType() params[AnalyticsParam.FIRMWARE] = card.firmwareVersion.stringValue - if (userWalletId != null) { - params[AnalyticsParam.USER_WALLET_ID] = userWalletId.stringValue - } ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver)?.let { params[AnalyticsParam.CURRENCY] = it.value diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt b/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt index 8e79d07381..d8dc74443d 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt @@ -2,6 +2,7 @@ package com.tangem.tap.common.extensions import com.tangem.core.analytics.Analytics import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.builder.UserWalletIdBuilder import com.tangem.tap.common.analytics.paramsInterceptor.LinkedCardContextInterceptor /** @@ -12,6 +13,11 @@ import com.tangem.tap.common.analytics.paramsInterceptor.LinkedCardContextInterc * Sets the new context */ fun Analytics.setContext(scanResponse: ScanResponse) { + val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() + if (userWalletId != null) { + setUserId(userWalletId.stringValue) + } + addParamsInterceptor(LinkedCardContextInterceptor(scanResponse)) } @@ -19,6 +25,7 @@ fun Analytics.setContext(scanResponse: ScanResponse) { * Erases the context */ fun Analytics.eraseContext() { + clearUserId() removeParamsInterceptor(LinkedCardContextInterceptor.id()) } @@ -26,6 +33,11 @@ fun Analytics.eraseContext() { * Adds a new context and keeps a previous context as the parent of the new one */ fun Analytics.addContext(scanResponse: ScanResponse) { + val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() + if (userWalletId != null) { + setUserId(userWalletId.stringValue) + } + val currentContext = removeParamsInterceptor(LinkedCardContextInterceptor.id()) as? LinkedCardContextInterceptor val newContext = LinkedCardContextInterceptor(scanResponse, parent = currentContext) diff --git a/core/analytics/build.gradle.kts b/core/analytics/build.gradle.kts index 99c29cd55d..819db765b9 100644 --- a/core/analytics/build.gradle.kts +++ b/core/analytics/build.gradle.kts @@ -22,4 +22,7 @@ dependencies { /** Core shouldn't depend on core, but in case with utils and logging its necessary */ implementation(projects.core.utils) + + /** For calculating user id hash */ + implementation(tangemDeps.card.core) } \ No newline at end of file diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt b/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt index 081a583c06..57633c428a 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/Analytics.kt @@ -1,5 +1,7 @@ package com.tangem.core.analytics +import com.tangem.common.extensions.calculateSha256 +import com.tangem.common.extensions.toHexString import com.tangem.core.analytics.api.* import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.ExceptionAnalyticsEvent @@ -19,7 +21,8 @@ interface GlobalAnalyticsEventHandler : AnalyticsFilterHolder, ParamsInterceptorHolder, AnalyticsErrorHandler, - AnalyticsExceptionHandler + AnalyticsExceptionHandler, + AnalyticsUserIdHandler object Analytics : GlobalAnalyticsEventHandler { @@ -57,6 +60,26 @@ object Analytics : GlobalAnalyticsEventHandler { return paramsInterceptors.remove(interceptorId) } + override fun setUserId(userId: String) { + analyticsScope.launch { + val userIdHash = userId.calculateSha256().toHexString() + + analyticsMutex.withLock { + analyticsHandlers.filterIsInstance() + .forEach { handler -> handler.setUserId(userIdHash) } + } + } + } + + override fun clearUserId() { + analyticsScope.launch { + analyticsMutex.withLock { + analyticsHandlers.filterIsInstance() + .forEach { handler -> handler.clearUserId() } + } + } + } + override fun send(event: AnalyticsEvent) { analyticsScope.launch { event.params = applyParamsInterceptors(event) diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt b/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt index 6c98379d6d..08e59781a0 100644 --- a/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt +++ b/core/analytics/src/main/java/com/tangem/core/analytics/api/EventHandlerApi.kt @@ -18,6 +18,11 @@ interface AnalyticsExceptionHandler { fun sendException(event: ExceptionAnalyticsEvent) } +interface AnalyticsUserIdHandler { + fun setUserId(userId: String) + fun clearUserId() +} + interface AnalyticsHandler : AnalyticsEventHandler { fun id(): String diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/api/UserIdHolder.kt b/core/analytics/src/main/java/com/tangem/core/analytics/api/UserIdHolder.kt new file mode 100644 index 0000000000..50a3af361e --- /dev/null +++ b/core/analytics/src/main/java/com/tangem/core/analytics/api/UserIdHolder.kt @@ -0,0 +1,8 @@ +package com.tangem.core.analytics.api + +interface UserIdHolder { + + fun setUserId(userId: String) + + fun clearUserId() +} \ No newline at end of file