diff --git a/app/build.gradle b/app/build.gradle index 0b4c0d646..0a79159e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -152,9 +152,9 @@ dependencies { api "com.google.firebase:firebase-messaging" // Segment Library - implementation "com.segment.analytics.kotlin:android:1.14.2" + implementation "com.segment.analytics.kotlin:android:1.16.3" // Segment's Firebase integration - implementation 'com.segment.analytics.kotlin.destinations:firebase:1.5.2' + implementation 'com.segment.analytics.kotlin.destinations:firebase:1.5.6' // Braze SDK Integration implementation "com.braze:braze-segment-kotlin:1.4.2" implementation "com.braze:android-sdk-ui:30.2.0" diff --git a/app/src/main/java/org/openedx/app/analytics/AnalyticsUtils.kt b/app/src/main/java/org/openedx/app/analytics/AnalyticsUtils.kt new file mode 100644 index 000000000..e20e3f5a9 --- /dev/null +++ b/app/src/main/java/org/openedx/app/analytics/AnalyticsUtils.kt @@ -0,0 +1,35 @@ +package org.openedx.app.analytics + +import android.os.Bundle +import com.braze.support.toBundle +import com.segment.analytics.kotlin.core.Properties +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put + +object AnalyticsUtils { + fun makeFirebaseAnalyticsKey(value: String): String { + return value.replace(Regex("[:\\- ]+"), "_").take(40) + } + + fun formatFirebaseAnalyticsData(input: Map): Bundle { + return input.entries.associate { (key, value) -> + // Format the key + val formattedKey = makeFirebaseAnalyticsKey(key) + // Truncate the string converted value to 100 characters + val formattedValue = value.toString().take(100) + // Return a Pair of the formatted key and value + formattedKey to formattedValue + }.toBundle() + } + + fun formatFirebaseAnalyticsDataForSegment(properties: Properties): Properties { + return buildJsonObject { + for ((key, value) in properties) { + put( + makeFirebaseAnalyticsKey(key), + value.toString().take(100) + ) + } + } + } +} diff --git a/app/src/main/java/org/openedx/app/analytics/FirebaseAnalytics.kt b/app/src/main/java/org/openedx/app/analytics/FirebaseAnalytics.kt index 17d3b3b62..5f2981c39 100644 --- a/app/src/main/java/org/openedx/app/analytics/FirebaseAnalytics.kt +++ b/app/src/main/java/org/openedx/app/analytics/FirebaseAnalytics.kt @@ -2,26 +2,26 @@ package org.openedx.app.analytics import android.content.Context import com.google.firebase.analytics.FirebaseAnalytics -import org.openedx.core.extension.toBundle import org.openedx.core.utils.Logger class FirebaseAnalytics(context: Context) : Analytics { private val logger = Logger(TAG) - private var tracker: FirebaseAnalytics - - init { - tracker = FirebaseAnalytics.getInstance(context) - logger.d { "Firebase Analytics Builder Initialised" } - } + private val tracker: FirebaseAnalytics = FirebaseAnalytics.getInstance(context) override fun logScreenEvent(screenName: String, params: Map) { - tracker.logEvent(screenName, params.toBundle()) + tracker.logEvent( + AnalyticsUtils.makeFirebaseAnalyticsKey(screenName), + AnalyticsUtils.formatFirebaseAnalyticsData(params) + ) logger.d { "Firebase Analytics log Screen Event: $screenName + $params" } } override fun logEvent(eventName: String, params: Map) { - tracker.logEvent(eventName, params.toBundle()) + tracker.logEvent( + AnalyticsUtils.makeFirebaseAnalyticsKey(eventName), + AnalyticsUtils.formatFirebaseAnalyticsData(params) + ) logger.d { "Firebase Analytics log Event $eventName: $params" } } diff --git a/app/src/main/java/org/openedx/app/analytics/SegmentAnalytics.kt b/app/src/main/java/org/openedx/app/analytics/SegmentAnalytics.kt index 3a9532a71..ef28e0c4b 100644 --- a/app/src/main/java/org/openedx/app/analytics/SegmentAnalytics.kt +++ b/app/src/main/java/org/openedx/app/analytics/SegmentAnalytics.kt @@ -1,6 +1,11 @@ package org.openedx.app.analytics import android.content.Context +import com.segment.analytics.kotlin.core.BaseEvent +import com.segment.analytics.kotlin.core.ScreenEvent +import com.segment.analytics.kotlin.core.TrackEvent +import com.segment.analytics.kotlin.core.platform.EventPlugin +import com.segment.analytics.kotlin.core.platform.Plugin import com.segment.analytics.kotlin.destinations.braze.BrazeDestination import com.segment.analytics.kotlin.destinations.firebase.FirebaseDestination import org.openedx.app.BuildConfig @@ -12,18 +17,40 @@ import com.segment.analytics.kotlin.core.Analytics as SegmentTracker class SegmentAnalytics(context: Context, config: Config) : Analytics { private val logger = Logger(TAG) - private var tracker: SegmentTracker - init { - // Create an analytics client with the given application context and Segment write key. - tracker = SegmentAnalyticsBuilder(config.getSegmentConfig().segmentWriteKey, context) { + // Create an analytics client with the given application context and Segment write key. + private val tracker: SegmentTracker = + SegmentAnalyticsBuilder(config.getSegmentConfig().segmentWriteKey, context) { // Automatically track Lifecycle events trackApplicationLifecycleEvents = true flushAt = 20 flushInterval = 30 } + + init { if (config.getFirebaseConfig().isSegmentAnalyticsSource()) { tracker.add(plugin = FirebaseDestination(context = context)) + + // Override the default event plugin to format the event and properties + // according to Firebase Analytics guidelines + tracker.find(FirebaseDestination::class)?.add(object : EventPlugin { + override lateinit var analytics: SegmentTracker + override val type = Plugin.Type.Before + + override fun track(payload: TrackEvent): BaseEvent { + return payload.apply { + this.event = AnalyticsUtils.makeFirebaseAnalyticsKey(this.event) + properties = + AnalyticsUtils.formatFirebaseAnalyticsDataForSegment(properties) + } + } + + override fun screen(payload: ScreenEvent): BaseEvent { + return payload.apply { + name = AnalyticsUtils.makeFirebaseAnalyticsKey(name) + } + } + }) } if (config.getFirebaseConfig()