diff --git a/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviAnalyticsHelper.kt b/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviAnalyticsHelper.kt index e24a6a363e..f405641a52 100644 --- a/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviAnalyticsHelper.kt +++ b/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviAnalyticsHelper.kt @@ -35,6 +35,134 @@ object NaviAnalyticsHelper { return whiteListedAppsFlyerEvent?.contains(eventName) ?: false } + /** + * Adds base properties to a ScreenLand event to create a unified schema. + * + * This method checks if the provided event is a ScreenLand event by inspecting its name. If it + * is identified as a ScreenLand event, it enriches the event's attributes with additional base + * properties such as the vertical (current section) and a boolean flag indicating that it is a + * ScreenLand event. The method also ensures a consistent identifier for the screen name, either + * by extracting it from the provided attributes or deriving it from the event name itself. This + * helps in maintaining a unified schema for ScreenLand events, making them easier to track, + * analyze, and debug across different parts of the application. + * + * **Usage**: This method can be used in event tracking systems where a consistent schema for + * ScreenLand events is required. It helps in creating a single identifier for these events and + * standardizes the properties associated with them. + * + * @param eventName The name of the event to check and enhance if it is a ScreenLand event. + * @param eventAttributes A map of existing event attributes. It can be null if there are no + * attributes. + * @param currentVertical The current vertical or section of the application in the foreground. + * @return A map of enhanced event attributes with base properties added, or the original + * attributes if the event is not identified as a ScreenLand event. + */ + fun addBasePropertiesToScreenLandEvent( + eventName: String, + eventAttributes: Map?, + vertical: String + ): Map? { + return if (isScreenLandEvent(eventName)) { + // Create a mutable copy of event attributes or initialize a new map + val attributes = eventAttributes?.toMutableMap() ?: mutableMapOf() + + // Extract screen name from event attributes or derive it from the event name + var screenName = extractScreenNameFromAttributes(eventAttributes) + if (screenName.isNullOrBlank()) { + screenName = deriveScreenNameFromEventName(eventName) + } + + // Add additional properties + attributes["screen"] = screenName + attributes["isScreenLandEvent"] = true.toString() + attributes["vertical"] = + extractVerticalNameFromAttributes( + attributes = eventAttributes, + defaultVertical = vertical, + eventName = screenName + ) + attributes + } else { + eventAttributes + } + } + + private fun isScreenLandEvent(eventName: String): Boolean { + return eventName.contains("_land", ignoreCase = true) || + eventName.contains("_appeared", ignoreCase = true) || + eventName.contains("HI_event_init_screen_", ignoreCase = true) || + eventName.equals("hi_insurance_tab_screen_init", ignoreCase = true) || + (eventName.startsWith("hi_rn_", ignoreCase = true) && + eventName.endsWith("_init", ignoreCase = true)) + } + + private fun extractScreenNameFromAttributes(attributes: Map?): String? { + // Attempt to retrieve the screen name using different possible keys + return attributes?.get("screen") + ?: attributes?.get("screenName") + ?: attributes?.get("screen_name") + } + + private fun deriveScreenNameFromEventName(eventName: String): String { + return when { + eventName.contains("_landed", ignoreCase = true) -> + eventName.replace("_landed", "", ignoreCase = true) + eventName.contains("_lands", ignoreCase = true) -> + eventName.replace("_lands", "", ignoreCase = true) + eventName.contains("_land", ignoreCase = true) -> + eventName.replace("_land", "", ignoreCase = true) + eventName.contains("_appeared", ignoreCase = true) -> + eventName.replace("_appeared", "", ignoreCase = true) + eventName.contains("HI_event_init_screen_", ignoreCase = true) -> + eventName.replace("HI_event_init_screen_", "", ignoreCase = true) + eventName.equals("hi_insurance_tab_screen_init", ignoreCase = true) -> eventName + eventName.startsWith("hi_rn_", ignoreCase = true) && + eventName.endsWith("_init", ignoreCase = true) -> + eventName + .replace("hi_rn_", "", ignoreCase = true) + .replace("_init", "", ignoreCase = true) + else -> eventName + } + } + + /** + * Extracts the vertical name from the given attributes or infers it from the event name. + * + * @param attributes A map of event attributes that may contain the "vertical" key. + * @param defaultVertical The default vertical to return if no specific vertical is identified. + * @param eventName The name of the event used to infer the vertical if it is not explicitly + * provided. + * @return The determined vertical name based on attributes or inferred from the event name. + */ + private fun extractVerticalNameFromAttributes( + attributes: Map?, + defaultVertical: String, + eventName: String + ): String { + // Retrieve vertical from attributes, or use default if not present + val vertical = attributes?.get("vertical") ?: defaultVertical + + // If vertical is not "COMMON", return it directly + if (vertical != "COMMON" && vertical != "FORGE") return vertical + + // Infer vertical from the event name if the vertical is "COMMON" or "FORGE" + // This logic is temporary and will be removed once each vertical starts using its correct + // module name + return when { + eventName.contains("home", ignoreCase = true) || + eventName.contains("notification", ignoreCase = true) -> "App" + eventName.contains("investment", ignoreCase = true) -> "Investment" + eventName.contains("amc", ignoreCase = true) -> "AMC" + eventName.contains("gold", ignoreCase = true) -> "GOLD" + eventName.contains("insurance", ignoreCase = true) || + eventName.contains("hi_", ignoreCase = true) || + eventName.contains("gi_", ignoreCase = true) || + eventName.contains("react", ignoreCase = true) -> "Insurance" + eventName.contains("loan", ignoreCase = true) -> "loan" + else -> defaultVertical + } + } + private fun buildAppsFlyerWhiteListedEvent() { whiteListedAppsFlyerEvent = HashSet() whiteListedAppsFlyerEvent?.let { diff --git a/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviTrackEvent.kt b/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviTrackEvent.kt index ea9bce177d..7bd5328d16 100644 --- a/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviTrackEvent.kt +++ b/android/navi-analytics/src/main/java/com/navi/analytics/utils/NaviTrackEvent.kt @@ -17,6 +17,7 @@ import com.navi.analytics.BuildConfig import com.navi.analytics.appsflyer.AppsFlyerUtil import com.navi.analytics.firebase.FcmAnalyticsUtil import com.navi.analytics.model.AnalyticsConfiguration +import com.navi.analytics.utils.NaviAnalyticsHelper.addBasePropertiesToScreenLandEvent import com.navi.analytics.utils.NaviAnalyticsHelper.isEventWhiteListedForAppsflyer import com.navi.base.model.AnalyticsEvent import com.navi.base.model.CtaData @@ -155,7 +156,7 @@ object NaviTrackEvent { isNeededForFirebase: Boolean = false ) { if (isNeededForFirebase) FcmAnalyticsUtil.analytics.trackEvent(eventName, eventValues) - PulseManager.trackEvent(eventName, eventValues) + trackEventOnClickStream(eventName, eventValues) if (isNeededForAppsflyer || isEventWhiteListedForAppsflyer(eventName)) { AppsFlyerUtil.instance.trackEvent(applicationContext, eventName, eventValues) } @@ -163,8 +164,10 @@ object NaviTrackEvent { } fun trackEventOnClickStream(eventName: String, eventValues: Map? = null) { - PulseManager.trackEvent(eventName, eventValues) - Timber.d(eventName.plus(" ").plus(eventValues?.toString())) + val attributes = + addBasePropertiesToScreenLandEvent(eventName, eventValues, foregroundVertical.orEmpty()) + PulseManager.trackEvent(eventName, attributes) + Timber.d(eventName.plus(" ").plus(attributes?.toString())) } fun trackEventOnAllThirdParty(eventName: String, eventValues: Map? = null) { @@ -250,8 +253,8 @@ object NaviTrackEvent { sendEvent(ctaData.analyticsEventProperties, screen) } - fun setForegroundScreenAndVertical(screen: String, vertical: String) { + fun setForegroundScreenAndVertical(screen: String, vertical: String? = null) { foregroundScreen = screen - foregroundVertical = vertical + vertical?.let { foregroundVertical = it } } } diff --git a/android/navi-common/src/main/java/com/navi/common/ui/activity/NaviCoreActivity.kt b/android/navi-common/src/main/java/com/navi/common/ui/activity/NaviCoreActivity.kt index 2aa3889a34..bc112ecebd 100644 --- a/android/navi-common/src/main/java/com/navi/common/ui/activity/NaviCoreActivity.kt +++ b/android/navi-common/src/main/java/com/navi/common/ui/activity/NaviCoreActivity.kt @@ -9,6 +9,7 @@ package com.navi.common.ui.activity import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import com.navi.analytics.utils.NaviTrackEvent import com.navi.common.checkmate.core.CheckMateLatencyMapper import com.navi.common.checkmate.core.CheckMateMapper import com.navi.common.model.ModuleNameV2 @@ -22,5 +23,17 @@ abstract class NaviCoreActivity : AppCompatActivity(), CheckMateMapper by CheckM override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) recordScreenLandTime(screenName) + NaviTrackEvent.setForegroundScreenAndVertical( + screen = screenName, + vertical = moduleName.name + ) + } + + override fun onResume() { + super.onResume() + NaviTrackEvent.setForegroundScreenAndVertical( + screen = screenName, + vertical = moduleName.name + ) } } diff --git a/android/navi-common/src/main/java/com/navi/common/ui/fragment/NaviCoreFragment.kt b/android/navi-common/src/main/java/com/navi/common/ui/fragment/NaviCoreFragment.kt index 97f846b1e1..95c1360733 100644 --- a/android/navi-common/src/main/java/com/navi/common/ui/fragment/NaviCoreFragment.kt +++ b/android/navi-common/src/main/java/com/navi/common/ui/fragment/NaviCoreFragment.kt @@ -9,6 +9,7 @@ package com.navi.common.ui.fragment import android.os.Bundle import androidx.fragment.app.Fragment +import com.navi.analytics.utils.NaviTrackEvent import com.navi.common.checkmate.core.CheckMateLatencyMapper import com.navi.common.checkmate.core.CheckMateMapper @@ -19,5 +20,11 @@ abstract class NaviCoreFragment : Fragment(), CheckMateMapper by CheckMateLatenc override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) recordScreenLandTime(screenName) + NaviTrackEvent.setForegroundScreenAndVertical(screen = screenName) + } + + override fun onResume() { + super.onResume() + NaviTrackEvent.setForegroundScreenAndVertical(screen = screenName) } }