From c204af29737419436c6da74d78c90c1271236685 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 2 Nov 2022 11:56:53 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/common/analytics/Analytics.kt | 5 ++- .../common/analytics/api/EventHandlerApi.kt | 3 +- .../tap/common/analytics/events/Shop.kt | 34 +++++++++++++-- .../appsFlyer/AppsFlyerAnalyticsHandler.kt | 34 +++------------ .../firebase/FirebaseAnalyticsHandler.kt | 31 +++----------- .../tap/common/shop/TangemShopService.kt | 41 +++++++++---------- .../tap/features/shop/ui/ShopFragment.kt | 4 ++ 7 files changed, 72 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt b/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt index 9eaee82a3a..386213f341 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/Analytics.kt @@ -11,6 +11,7 @@ import com.tangem.tap.common.analytics.api.ErrorEventLogger import com.tangem.tap.common.analytics.api.ShopifyOrderEventHandler import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.extensions.filterNotNull +import com.tangem.tap.common.shop.data.ProductType /** [REDACTED_AUTHOR] @@ -85,9 +86,9 @@ object Analytics : GlobalAnalyticsEventHandler { } } - override fun send(order: Storefront.Order) { + override fun send(order: Storefront.Order, productType: ProductType) { analyticsHandlers.filterIsInstance().forEach { - it.send(order) + it.send(order, productType) } } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt index ea77e75dfd..5eda855ec2 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/api/EventHandlerApi.kt @@ -13,6 +13,7 @@ import com.tangem.tap.common.analytics.AnalyticsParamAnOld import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.extensions.filterNotNull +import com.tangem.tap.common.shop.data.ProductType import com.tangem.tap.domain.configurable.config.Config /** @@ -83,7 +84,7 @@ interface BlockchainSdkErrorEventHandler { } interface ShopifyOrderEventHandler { - fun send(order: Storefront.Order) + fun send(order: Storefront.Order, productType: ProductType) } interface AnalyticsHandlerBuilder { diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt index c09bf89ab3..90fdf6e08f 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt @@ -1,5 +1,10 @@ package com.tangem.tap.common.analytics.events +import com.shopify.buy3.Storefront +import com.tangem.common.Converter +import com.tangem.tap.common.extensions.filterNotNull +import com.tangem.tap.common.shop.data.ProductType + /** [REDACTED_AUTHOR] */ @@ -10,13 +15,36 @@ sealed class Shop( class ScreenOpened : IntroductionProcess("Shop Screen Opened") - class Purchased(productSku: String) : Shop( + class Purchased(params: Map) : Shop( event = "Purchased", - params = mapOf("SKU" to productSku), + params = params, ) class Redirected(partnerName: String) : Shop( event = "Redirected", params = mapOf("Partner" to partnerName), ) -} \ No newline at end of file +} + +class OrderToParamsConverter : Converter, Map> { + override fun convert(value: Pair): Map { + val order = value.first + val productType = value.second + + val code = (order.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code + val sku = order.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: productType.sku + + val count = when (productType) { + ProductType.WALLET_2_CARDS -> "2" + ProductType.WALLET_3_CARDS -> "3" + } + val amount = "${order.totalPriceV2.amount} ${order.totalPriceV2.currencyCode.name}" + + return mapOf( + "Coupon Code" to code, + "SKU" to sku, + "Count" to count, + "Amount" to amount, + ).filterNotNull() + } +} diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt index 008b6189b9..8264b4c501 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt @@ -1,12 +1,12 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer -import com.appsflyer.AFInAppEventParameterName -import com.appsflyer.AFInAppEventType import com.shopify.buy3.Storefront -import com.tangem.common.Converter import com.tangem.tap.common.analytics.api.AnalyticsEventHandler import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.api.ShopifyOrderEventHandler +import com.tangem.tap.common.analytics.events.OrderToParamsConverter +import com.tangem.tap.common.analytics.events.Shop +import com.tangem.tap.common.shop.data.ProductType class AppsFlyerAnalyticsHandler( private val client: AppsFlyerAnalyticsClient, @@ -18,12 +18,12 @@ class AppsFlyerAnalyticsHandler( client.logEvent(event, params) } - override fun send(order: Storefront.Order) { - send(ORDER_EVENT, OrderToParamsConverter().convert(order)) + override fun send(order: Storefront.Order, productType: ProductType) { + val eventParams = OrderToParamsConverter().convert(order to productType) + send(Shop.Purchased(eventParams)) } companion object { - const val ORDER_EVENT = AFInAppEventType.PURCHASE const val ID = "AppsFlyer" } @@ -34,26 +34,4 @@ class AppsFlyerAnalyticsHandler( else -> null }?.let { AppsFlyerAnalyticsHandler(it) } } -} - -private class OrderToParamsConverter : Converter> { - - override fun convert(value: Storefront.Order): Map { - val sku = value.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: "unknown" - - val discountCode = - (value.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code - - val discountParams = if (discountCode != null) { - mapOf(AFInAppEventParameterName.COUPON_CODE to discountCode) - } else { - mapOf() - } - - return mapOf( - AFInAppEventParameterName.CONTENT_ID to sku, - AFInAppEventParameterName.REVENUE to value.totalPriceV2.amount, - AFInAppEventParameterName.CURRENCY to value.currencyCode.name, - ) + discountParams - } } \ No newline at end of file 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 65ef31ac8e..1c79942d4f 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 @@ -1,9 +1,7 @@ package com.tangem.tap.common.analytics.handlers.firebase -import com.google.firebase.analytics.FirebaseAnalytics import com.shopify.buy3.Storefront import com.tangem.blockchain.common.BlockchainError -import com.tangem.common.Converter import com.tangem.common.card.Card import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.analytics.AnalyticsAnOld @@ -15,6 +13,9 @@ import com.tangem.tap.common.analytics.api.SdkErrorEventHandler import com.tangem.tap.common.analytics.api.ShopifyOrderEventHandler import com.tangem.tap.common.analytics.converters.BlockchainSdkErrorConverter import com.tangem.tap.common.analytics.converters.CardSdkErrorConverter +import com.tangem.tap.common.analytics.events.OrderToParamsConverter +import com.tangem.tap.common.analytics.events.Shop +import com.tangem.tap.common.shop.data.ProductType class FirebaseAnalyticsHandler( private val client: FirebaseAnalyticsClient, @@ -57,8 +58,9 @@ class FirebaseAnalyticsHandler( } } - override fun send(order: Storefront.Order) { - send(FirebaseClient.ORDER_EVENT, OrderToParamsConverter().convert(order)) + override fun send(order: Storefront.Order, productType: ProductType) { + val eventParams = OrderToParamsConverter().convert(order to productType) + send(Shop.Purchased(eventParams)) } companion object { @@ -72,25 +74,4 @@ class FirebaseAnalyticsHandler( else -> null }?.let { FirebaseAnalyticsHandler(it) } } -} - -private class OrderToParamsConverter : Converter> { - override fun convert(value: Storefront.Order): Map { - val sku = value.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: "unknown" - - val discountCode = - (value.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code - - val discountParams = if (discountCode != null) { - mapOf(FirebaseAnalytics.Param.DISCOUNT to discountCode) - } else { - mapOf() - } - - return mapOf( - FirebaseAnalytics.Param.ITEM_ID to sku, - FirebaseAnalytics.Param.VALUE to value.totalPriceV2.amount, - FirebaseAnalytics.Param.CURRENCY to value.currencyCode.name, - ) + discountParams - } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 87dacd7bc1..3d2c060786 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -22,7 +22,6 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { private val shopifyService = ShopifyService(application, shopifyShop) - private val checkouts = mutableMapOf() private val variants = mutableMapOf() @@ -40,24 +39,27 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { variants.putAll(availableVariants) if (variants.size < SKUS_TO_DISPLAY.size) { - return Result.failure(Exception( - "Shopify: products are missing, " + - "\nproducts available: ${variants.keys.map { it.sku }}")) + return Result.failure( + Exception( + "Shopify: products are missing, " + + "\nproducts available: ${variants.keys.map { it.sku }}", + ), + ) } val twoCardsProduct = TangemProduct( type = ProductType.WALLET_2_CARDS, totalSum = TotalSum( finalValue = variants[ProductType.WALLET_2_CARDS]?.priceV2?.format(), - beforeDiscount = variants[ProductType.WALLET_2_CARDS]?.compareAtPriceV2?.format() - ) + beforeDiscount = variants[ProductType.WALLET_2_CARDS]?.compareAtPriceV2?.format(), + ), ) val threeCardsProduct = TangemProduct( type = ProductType.WALLET_3_CARDS, totalSum = TotalSum( finalValue = variants[ProductType.WALLET_3_CARDS]?.priceV2?.format(), - beforeDiscount = variants[ProductType.WALLET_3_CARDS]?.compareAtPriceV2?.format() - ) + beforeDiscount = variants[ProductType.WALLET_3_CARDS]?.compareAtPriceV2?.format(), + ), ) createCheckouts() return Result.success(listOf(twoCardsProduct, threeCardsProduct)) @@ -85,7 +87,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { val totalPrice = checkouts[productType]!!.totalPriceV2.amount googlePayService.payWithGooglePay( totalPriceCents = totalPrice, currencyCode = checkouts[productType]!!.currencyCode.name, - merchantID = shopifyService.shop.merchantID + merchantID = shopifyService.shop.merchantID, ) } @@ -104,7 +106,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { suspend fun handleGooglePayResult( resultCode: Int, data: Intent?, - productType: ProductType + productType: ProductType, ): Result { val result = googlePayService.handleResponseFromGooglePay(resultCode, data) result.onSuccess { @@ -119,7 +121,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { private suspend fun completeTokenizedPayment( paymentData: PaymentData, - productType: ProductType + productType: ProductType, ): Result { val checkout = checkouts[productType]!! val googlePayResponse = @@ -140,19 +142,18 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { phone = addressGPay.phoneNumber } - val payment = Storefront.TokenizedPaymentInputV3( amount, idempotencyKey, address, paymentData.toJson(), - Storefront.PaymentTokenType.GOOGLE_PAY + Storefront.PaymentTokenType.GOOGLE_PAY, ) .setTest(true) return shopifyService.completeWithTokenizedPayment( payment = payment, - checkoutID = checkout.id + checkoutID = checkout.id, ) } @@ -181,12 +182,12 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { productType, TotalSum( finalValue = it.totalPriceV2.format(), - beforeDiscount = variants[productType]!!.compareAtPriceV2.format() + beforeDiscount = variants[productType]!!.compareAtPriceV2.format(), ), - appliedDiscount = it.getAppliedDiscount() - ) + appliedDiscount = it.getAppliedDiscount(), + ), - ) + ) } return Result.failure(result.exceptionOrNull()!!) } @@ -197,9 +198,7 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { suspend fun waitForCheckout(productType: ProductType) { val result = shopifyService.checkout(true, checkouts[productType]!!.id) - result.onSuccess { - it.order?.let { Analytics.send(it) } - } + result.onSuccess { checkout -> checkout.order?.let { Analytics.send(it, productType) } } } companion object { diff --git a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt index 51fe6cb54c..338561267b 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt @@ -12,6 +12,8 @@ import androidx.activity.OnBackPressedCallback import by.kirich1409.viewbindingdelegate.viewBinding import com.tangem.tap.common.GlobalLayoutStateHandler import com.tangem.tap.common.KeyboardObserver +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.common.shop.data.ProductType @@ -41,6 +43,8 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber< override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + Analytics.send(Shop.ScreenOpened()) + activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { store.dispatch(NavigationAction.PopBackTo())