Updated on 2026-08-14

This commit is contained in:
Tangem 2022-03-02 19:29:13 +03:00
parent b5bbf6e8d9
commit 8a8907e415
9 changed files with 113 additions and 2 deletions

View file

@ -1,5 +1,6 @@
package com.tangem.tap.common.analytics
import com.shopify.buy3.Storefront
import com.tangem.common.card.Card
import com.tangem.common.core.TangemSdkError
import com.tangem.tap.common.extensions.filterNotNull
@ -13,6 +14,11 @@ abstract class AnalyticsHandler {
params: Map<String, String> = emptyMap()
)
abstract fun triggerEvent(
event: String,
params: Map<String, String>
)
abstract fun logCardSdkError(
error: TangemSdkError,
actionToLog: Analytics.ActionToLog,
@ -71,6 +77,13 @@ abstract class AnalyticsHandler {
)
}
}
}
fun logShopifyOrder(order: Storefront.Order) {
triggerEvent(getOrderEvent(), getOrderParams(order))
}
protected abstract fun getOrderEvent(): String
protected abstract fun getOrderParams(order: Storefront.Order): Map<String, String>
}

View file

@ -1,7 +1,10 @@
package com.tangem.tap.common.analytics
import android.app.Application
import com.appsflyer.AFInAppEventParameterName
import com.appsflyer.AFInAppEventType
import com.appsflyer.AppsFlyerLib
import com.shopify.buy3.Storefront
import com.tangem.common.card.Card
import com.tangem.common.core.TangemSdkError
@ -30,4 +33,30 @@ class AppsFlyerAnalyticsHandler(val context: Application): AnalyticsHandler() {
//TODO
}
override fun getOrderEvent(): String = AFInAppEventType.PURCHASE
override fun getOrderParams(order: Storefront.Order): Map<String, String> {
val sku = order.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: "unknown"
val discountCode =
(order.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 order.totalPriceV2.amount,
AFInAppEventParameterName.CURRENCY to order.currencyCode.name
) + discountParams
}
override fun triggerEvent(event: String, params: Map<String, String>) {
AppsFlyerLib.getInstance().logEvent(context, event, params)
}
}

View file

@ -2,9 +2,11 @@ package com.tangem.tap.common.analytics
import android.os.Bundle
import androidx.core.os.bundleOf
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.ktx.Firebase
import com.shopify.buy3.Storefront
import com.tangem.common.card.Card
import com.tangem.common.core.TangemSdkError
@ -57,4 +59,30 @@ object FirebaseAnalyticsHandler : AnalyticsHandler() {
params.forEach { (key, value) -> FirebaseCrashlytics.getInstance().setCustomKey(key, value) }
FirebaseCrashlytics.getInstance().recordException(error)
}
override fun getOrderEvent(): String = FirebaseAnalytics.Event.PURCHASE
override fun getOrderParams(order: Storefront.Order): Map<String, String> {
val sku = order.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: "unknown"
val discountCode =
(order.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 order.totalPriceV2.amount,
FirebaseAnalytics.Param.CURRENCY to order.currencyCode.name
) + discountParams
}
override fun triggerEvent(event: String, params: Map<String, String>) {
Firebase.analytics.logEvent(event, params.toBundle())
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.tap.common.analytics
import android.app.Application
import com.shopify.buy3.Storefront
import com.tangem.common.card.Card
import com.tangem.common.core.TangemSdkError
@ -15,6 +16,10 @@ class GlobalAnalyticsHandler(val analyticsHandlers: List<AnalyticsHandler>) :
analyticsHandlers.forEach { it.triggerEvent(event, card, blockchain) }
}
override fun triggerEvent(event: String, params: Map<String, String>) {
analyticsHandlers.forEach { it.triggerEvent(event, params) }
}
override fun logCardSdkError(
error: TangemSdkError,
actionToLog: Analytics.ActionToLog,
@ -28,6 +33,14 @@ class GlobalAnalyticsHandler(val analyticsHandlers: List<AnalyticsHandler>) :
analyticsHandlers.forEach { it.logError(error, params) }
}
override fun getOrderEvent(): String {
return ""
}
override fun getOrderParams(order: Storefront.Order): Map<String, String> {
return emptyMap()
}
companion object {
fun createDefaultAnalyticHandlers(context: Application): GlobalAnalyticsHandler {
return GlobalAnalyticsHandler(

View file

@ -4,9 +4,11 @@ import android.app.Application
import android.content.Intent
import com.google.android.gms.wallet.PaymentData
import com.shopify.buy3.Storefront
import com.tangem.tap.common.analytics.AnalyticsHandler
import com.tangem.tap.common.shop.data.ProductType
import com.tangem.tap.common.shop.data.TangemProduct
import com.tangem.tap.common.shop.data.TotalSum
import com.tangem.tap.common.shop.shopify.ShopifyService
import com.tangem.tap.common.shop.shopify.ShopifyShop
import com.tangem.tap.common.shop.shopify.data.CheckoutItem
import kotlinx.coroutines.async
@ -197,6 +199,18 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
return checkouts[productType]!!.webUrl
}
suspend fun waitForCheckout(
productType: ProductType,
analyticsHandler: AnalyticsHandler?
) {
val result = shopifyService.checkout(true, checkouts[productType]!!.id)
result.onSuccess {
if (it.order != null) {
analyticsHandler?.logShopifyOrder(order = it.order)
}
}
}
companion object {
const val TANGEM_WALLET_2_CARDS_SKU = "TG115x2"
const val TANGEM_WALLET_3_CARDS_SKU = "TG115x3"

View file

@ -34,5 +34,7 @@ sealed class ShopAction : Action {
data class SelectProduct(val productType: ProductType) : ShopAction()
object FinishSuccessfulOrder : ShopAction()
object ResetState : ShopAction()
}

View file

@ -110,7 +110,18 @@ private fun handle(action: Action) {
}
ShopAction.StartWebCheckout -> {
store.dispatchOpenUrl(shopService.getCheckoutUrl(shopState.selectedProduct))
store.dispatch(ShopAction.FinishSuccessfulOrder)
}
is ShopAction.FinishSuccessfulOrder -> {
scope.launch {
shopService.waitForCheckout(
productType = shopState.selectedProduct,
analyticsHandler = store.state.globalState.analyticsHandlers
)
}
}
}
}

View file

@ -63,6 +63,7 @@ private fun internalReduce(action: Action, state: ShopState): ShopState {
ShopAction.BuyWithGooglePay.UserCancelled -> {
state
}
ShopAction.FinishSuccessfulOrder -> state
ShopAction.ResetState -> ShopState()
}
}

View file

@ -137,7 +137,7 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber<
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
imvThird?.show(show)
imvThird.show(show)
}
})
}