From 0c15dd6400ed6106e984191df87d551eef59deaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 10:00:52 +0200 Subject: [PATCH 01/11] Add ComScore persistent labels --- .../pillarbox/analytics/SRGAnalytics.kt | 47 +++++++++++++++++++ .../pillarbox/analytics/comscore/ComScore.kt | 22 +++++++++ .../analytics/comscore/ComScoreSrg.kt | 15 ++++++ .../analytics/TestSRGAnalyticsPageViews.kt | 13 +++++ 4 files changed, 97 insertions(+) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt index 35eeb0eb6..137a6b279 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt @@ -92,6 +92,38 @@ object SRGAnalytics { instance?.sendEvent(event) } + /** + * Put persistent labels + * + * @param commandersActLabels CommandersAct specific permanent label. + * @param comScoreLabels ComScore specific persistent label. + */ + fun putPersistentLabels( + commandersActLabels: Map? = null, + comScoreLabels: Map? = null + ) { + instance?.putPersistentLabels(commandersActLabels = commandersActLabels, comScoreLabels = comScoreLabels) + } + + /** + * Remove persistent label for CommandersAct and/or ComScore. + * + * @param label The label to remove. + */ + fun removePersistentLabel(label: String) { + instance?.removePersistentLabel(label) + } + + /** + * Get ComScore persistent label + * + * @param label The label to get. + * @return associated ComScore label or null if nothing found. + */ + fun getComScorePersistentLabel(label: String): String? { + return instance?.getComScorePersistentLabel(label) + } + /** * Init SRGAnalytics * @@ -115,5 +147,20 @@ object SRGAnalytics { this.commandersAct.sendEvent(commandersAct) // Business decision to not send those event to comScore. } + + fun putPersistentLabels( + commandersActLabels: Map? = null, + comScoreLabels: Map? = null + ) { + comScore.putPersistentLabels(comScoreLabels) + } + + fun removePersistentLabel(label: String) { + comScore.removePersistentLabel(label) + } + + fun getComScorePersistentLabel(label: String): String? { + return comScore.getPersistentLabel(label) + } } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt index 99f3c0c79..1763a5650 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt @@ -15,4 +15,26 @@ interface ComScore { * @param pageView The [ComScorePageView] to send. */ fun sendPageView(pageView: ComScorePageView) + + /** + * Put persistent labels + * + * @param labels The values to put. + */ + fun putPersistentLabels(labels: Map? = null) + + /** + * Remove persistent label + * + * @param label The label to remove. + */ + fun removePersistentLabel(label: String) + + /** + * Get persistent label + * + * @param label The label to get. + * @return null if not found. + */ + fun getPersistentLabel(label: String): String? } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt index bc6eed7be..c375d8f2f 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt @@ -102,6 +102,21 @@ internal object ComScoreSrg : ComScore { } } + override fun putPersistentLabels(labels: Map?) { + val configuration = Analytics.getConfiguration().getPublisherConfiguration(publisherId) + configuration.addPersistentLabels(labels) + } + + override fun removePersistentLabel(label: String) { + val configuration = Analytics.getConfiguration().getPublisherConfiguration(publisherId) + configuration.removePersistentLabel(label) + } + + override fun getPersistentLabel(label: String): String? { + val configuration = Analytics.getConfiguration().getPublisherConfiguration(publisherId) + return configuration.getPersistentLabel(label) + } + private fun checkInitialized() { requireNotNull(config) { "ComScore init has to be called before start." } } diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt index dde26fca1..7d5fc413d 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt @@ -70,6 +70,19 @@ class TestSRGAnalyticsPageViews { override fun sendPageView(pageView: ComScorePageView) { Assert.assertTrue(pageViewFlow.tryEmit(pageView)) } + + override fun putPersistentLabels(labels: Map?) { + // Nothing + } + + override fun removePersistentLabel(label: String) { + // Nothing + } + + override fun getPersistentLabel(label: String): String? { + // Nothing + return null + } } private class DummyCommandersAct : CommandersAct { From 450b2031652154cba5fd7c8c3a956627987bb0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 10:23:39 +0200 Subject: [PATCH 02/11] Add persistent labels to CommandersAct --- .../pillarbox/analytics/SRGAnalytics.kt | 29 +++++++++++++++++++ .../analytics/commandersact/CommandersAct.kt | 22 ++++++++++++++ .../commandersact/CommandersActSrg.kt | 15 ++++++++++ .../analytics/TestSRGAnalyticsPageViews.kt | 13 +++++++++ .../core/business/CommandersActTrackerTest.kt | 15 +++++++++- 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt index 137a6b279..d03df982e 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt @@ -114,6 +114,19 @@ object SRGAnalytics { instance?.removePersistentLabel(label) } + /** + * Remove multiple persistent label. + * + * @param labels List of labels to remove. + */ + fun removePersistentLabels(labels: List) { + instance?.let { analytics -> + for (label in labels) { + analytics.removePersistentLabel(label) + } + } + } + /** * Get ComScore persistent label * @@ -124,6 +137,16 @@ object SRGAnalytics { return instance?.getComScorePersistentLabel(label) } + /** + * Get CommandersAct persistent label + * + * @param label The label to get. + * @return associated CommandersAct label or null if nothing found. + */ + fun getCommandersActPersistentLabel(label: String): String? { + return instance?.getCommandersActPermanentData(label) + } + /** * Init SRGAnalytics * @@ -153,14 +176,20 @@ object SRGAnalytics { comScoreLabels: Map? = null ) { comScore.putPersistentLabels(comScoreLabels) + commandersAct.putPermanentData(commandersActLabels) } fun removePersistentLabel(label: String) { comScore.removePersistentLabel(label) + commandersAct.removePermanentData(label) } fun getComScorePersistentLabel(label: String): String? { return comScore.getPersistentLabel(label) } + + fun getCommandersActPermanentData(label: String): String? { + return commandersAct.getPermanentDataLabel(label) + } } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt index 51a7b5e67..b7afaaf28 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt @@ -33,4 +33,26 @@ interface CommandersAct { * Enable running in background */ fun enableRunningInBackground() {} + + /** + * Put permanent data + * + * @param labels The values to put. + */ + fun putPermanentData(labels: Map? = null) + + /** + * Remove permanent data + * + * @param label The label to remove. + */ + fun removePermanentData(label: String) + + /** + * Get permanent label + * + * @param label The label to get. + * @return null if not found. + */ + fun getPermanentDataLabel(label: String): String? } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt index d866a0da2..e2b579ee5 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt @@ -84,6 +84,21 @@ internal class CommandersActSrg( tcServerSide.enableRunningInBackground() } + override fun putPermanentData(labels: Map?) { + if (labels == null) return + for (entry in labels.entries) { + tcServerSide.addPermanentData(entry.key, entry.value) + } + } + + override fun removePermanentData(label: String) { + tcServerSide.removePermanentData(label) + } + + override fun getPermanentDataLabel(label: String): String? { + return tcServerSide.getPermanentData(label) + } + /** * Override application name if [AnalyticsConfig.nonLocalizedApplicationName] is not empty. * Useful for application that localized their application name and want to have same name for analytics. diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt index 7d5fc413d..1557ff329 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt @@ -100,5 +100,18 @@ class TestSRGAnalyticsPageViews { } + override fun putPermanentData(labels: Map?) { + // Nothing + } + + override fun removePermanentData(label: String) { + // Nothing + } + + override fun getPermanentDataLabel(label: String): String? { + // Nothing + return null + } + } } diff --git a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt index b2b7cf6af..af58096dd 100644 --- a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt +++ b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt @@ -148,7 +148,7 @@ class CommandersActTrackerTest { @FlakyTest(detail = "POS and UPTIME not always send due to timers") @Test - fun testPosTime() =runTest(timeout = TEST_TIMEOUT) { + fun testPosTime() = runTest(timeout = TEST_TIMEOUT) { val expected = listOf( MediaEventType.Pos.toString(), MediaEventType.Pos.toString(), @@ -272,6 +272,19 @@ class CommandersActTrackerTest { events.add(Event(name = event.name, position = position, timeshift = timeshift)) } + override fun putPermanentData(labels: Map?) { + // Nothing + } + + override fun removePermanentData(label: String) { + // Nothing + } + + override fun getPermanentDataLabel(label: String): String? { + // Nothing + return null + } + override fun sendPageView(pageView: CommandersActPageView) { // Ignored } From dda7c5e5d084b064ea95f9ebe7ce44a703e89eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 10:47:23 +0200 Subject: [PATCH 03/11] Add initial persistent labels --- .../ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt | 12 ++++++++---- .../analytics/commandersact/CommandersAct.kt | 2 +- .../analytics/commandersact/CommandersActSrg.kt | 6 +++++- .../srgssr/pillarbox/analytics/comscore/ComScore.kt | 2 +- .../pillarbox/analytics/comscore/ComScoreSrg.kt | 6 +++++- .../pillarbox/analytics/TestSRGAnalyticsPageViews.kt | 2 +- .../core/business/CommandersActTrackerTest.kt | 2 +- 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt index 6f51b20f4..f7c9b8b2e 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt @@ -8,16 +8,20 @@ package ch.srgssr.pillarbox.analytics * SRG Analytics config * * @property vendor business unit. - * @property nonLocalizedApplicationName Application name for the analytics, by default the application name defined in the manifest. You can set - * it to null if the application name is not localized. * @property appSiteName The App/Site name given by the analytics team. * @property sourceKey The CommandersAct sourceKey given by the analytics team. + * @property nonLocalizedApplicationName Application name for the analytics, by default the application name defined in the manifest. You can set + * it to null if the application name is not localized. + * @property comScorePersistentLabels initial ComScore persistent labels. + * @property commandersActPersistentLabels initial CommandersAct persistent labels. */ data class AnalyticsConfig( val vendor: Vendor, - val nonLocalizedApplicationName: String? = null, val appSiteName: String, - val sourceKey: String + val sourceKey: String, + val nonLocalizedApplicationName: String? = null, + val comScorePersistentLabels: Map? = null, + val commandersActPersistentLabels: Map? = null, ) { /** diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt index b7afaaf28..520bb9353 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt @@ -39,7 +39,7 @@ interface CommandersAct { * * @param labels The values to put. */ - fun putPermanentData(labels: Map? = null) + fun putPermanentData(labels: Map) /** * Remove permanent data diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt index e2b579ee5..2bb5ddf38 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt @@ -47,6 +47,10 @@ internal class CommandersActSrg( tcServerSide = TCServerSide(SITE_SRG, config.sourceKey, appContext) TCDebug.setDebugLevel(if (BuildConfig.DEBUG) Log.DEBUG else Log.INFO) + config.commandersActPersistentLabels?.let { + putPermanentData(it) + } + // Data send with all events that never change tcServerSide.addPermanentData(APP_LIBRARY_VERSION, "${BuildConfig.VERSION_NAME} ${BuildConfig.BUILD_DATE}") tcServerSide.addPermanentData(NAVIGATION_APP_SITE_NAME, config.appSiteName) @@ -84,7 +88,7 @@ internal class CommandersActSrg( tcServerSide.enableRunningInBackground() } - override fun putPermanentData(labels: Map?) { + override fun putPermanentData(labels: Map) { if (labels == null) return for (entry in labels.entries) { tcServerSide.addPermanentData(entry.key, entry.value) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt index 1763a5650..8840d1d16 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt @@ -21,7 +21,7 @@ interface ComScore { * * @param labels The values to put. */ - fun putPersistentLabels(labels: Map? = null) + fun putPersistentLabels(labels: Map) /** * Remove persistent label diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt index c375d8f2f..50f14a028 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt @@ -54,6 +54,10 @@ internal object ComScoreSrg : ComScore { } this.config = config val persistentLabels = HashMap() + config.comScorePersistentLabels?.let { labels -> + persistentLabels.putAll(labels) + } + val versionName: String = try { // When unit testing from library packageInfo.versionName is null! context.applicationContext.packageManager.getPackageInfo(context.applicationContext.packageName, 0).versionName @@ -102,7 +106,7 @@ internal object ComScoreSrg : ComScore { } } - override fun putPersistentLabels(labels: Map?) { + override fun putPersistentLabels(labels: Map) { val configuration = Analytics.getConfiguration().getPublisherConfiguration(publisherId) configuration.addPersistentLabels(labels) } diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt index 1557ff329..784a687ee 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt @@ -100,7 +100,7 @@ class TestSRGAnalyticsPageViews { } - override fun putPermanentData(labels: Map?) { + override fun putPermanentData(labels: Map) { // Nothing } diff --git a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt index af58096dd..e759a4232 100644 --- a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt +++ b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt @@ -272,7 +272,7 @@ class CommandersActTrackerTest { events.add(Event(name = event.name, position = position, timeshift = timeshift)) } - override fun putPermanentData(labels: Map?) { + override fun putPermanentData(labels: Map) { // Nothing } From 54d3f53cd2a7188cb33da1446981a25f5cb29492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 10:54:28 +0200 Subject: [PATCH 04/11] Add user consent key label --- .../pillarbox/analytics/commandersact/CommandersActLabels.kt | 3 +++ .../ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActLabels.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActLabels.kt index f0beffa4c..7139f46e1 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActLabels.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActLabels.kt @@ -23,4 +23,7 @@ enum class CommandersActLabels(val label: String) { // Page View NAVIGATION_LEVEL_I("navigation_level_"), NAVIGATION_BU_DISTRIBUTER("navigation_bu_distributer"), + + // User consent + CONSENT_SERVICES("consent_services") } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt index d001949b8..5292c1e34 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt @@ -8,4 +8,8 @@ internal enum class ComScoreLabel(val label: String) { C8("c8"), MP_BRAND("mp_brand"), MP_V("mp_v"), + /** + * Please refer to ComScore android implementation guide section 2.5. + */ + USER_CONSENT("cs_ucfr"), } From 84783017e50db866077bd9df8e1757f922134269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 11:20:38 +0200 Subject: [PATCH 05/11] Fix nullability changes --- .../java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt index d03df982e..911687541 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt @@ -99,8 +99,8 @@ object SRGAnalytics { * @param comScoreLabels ComScore specific persistent label. */ fun putPersistentLabels( - commandersActLabels: Map? = null, - comScoreLabels: Map? = null + commandersActLabels: Map, + comScoreLabels: Map ) { instance?.putPersistentLabels(commandersActLabels = commandersActLabels, comScoreLabels = comScoreLabels) } @@ -172,8 +172,8 @@ object SRGAnalytics { } fun putPersistentLabels( - commandersActLabels: Map? = null, - comScoreLabels: Map? = null + commandersActLabels: Map, + comScoreLabels: Map ) { comScore.putPersistentLabels(comScoreLabels) commandersAct.putPermanentData(commandersActLabels) From 8378e6a217c4677aa6485af7cd783f672d1a21b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 11:33:21 +0200 Subject: [PATCH 06/11] Add public comscore user consent label --- .../ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt | 6 +++--- .../pillarbox/analytics/comscore/ComScoreLabel.kt | 10 +++++----- .../analytics/comscore/ComScoreLabelInternal.kt | 11 +++++++++++ .../pillarbox/analytics/comscore/ComScorePageView.kt | 2 +- .../pillarbox/analytics/comscore/ComScoreSrg.kt | 4 ++-- .../srgssr/pillarbox/analytics/ComScoreEventTest.kt | 6 +++--- .../java/ch/srgssr/pillarbox/demo/DemoApplication.kt | 6 +++++- 7 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt diff --git a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt index 3ffcfb050..2238b3624 100644 --- a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt +++ b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt @@ -5,7 +5,7 @@ package ch.srgssr.pillarbox.analytics import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation -import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel +import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabelInternal import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView import ch.srgssr.pillarbox.analytics.comscore.ComScoreSrg import kotlinx.coroutines.CoroutineDispatcher @@ -41,7 +41,7 @@ class TestComScoreSrg { val pageTitle = "Title" val pageView = ComScorePageView(name = pageTitle) val actualLabels = ArrayList>() - val expectedLabels = listOf(mapOf(Pair(ComScoreLabel.C8.label, pageTitle))) + val expectedLabels = listOf(mapOf(Pair(ComScoreLabelInternal.C8.label, pageTitle))) val job = launch(dispatcher) { tracker.pageViewFlow.take(1).toList(actualLabels) } @@ -58,7 +58,7 @@ class TestComScoreSrg { val labels = mapOf(Pair("key1", "value01"), Pair("key2", " ")) val pageView = ComScorePageView(name = pageTitle, labels = labels) val actualLabels = ArrayList>() - val expectedLabels = listOf(mapOf(Pair(ComScoreLabel.C8.label, pageTitle), Pair("key1", "value01"))) + val expectedLabels = listOf(mapOf(Pair(ComScoreLabelInternal.C8.label, pageTitle), Pair("key1", "value01"))) val job = launch(dispatcher) { tracker.pageViewFlow.take(1).toList(actualLabels) } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt index 5292c1e34..d1f79c578 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt @@ -4,12 +4,12 @@ */ package ch.srgssr.pillarbox.analytics.comscore -internal enum class ComScoreLabel(val label: String) { - C8("c8"), - MP_BRAND("mp_brand"), - MP_V("mp_v"), +/** + * Public ComScore label + */ +object ComScoreLabel { /** * Please refer to ComScore android implementation guide section 2.5. */ - USER_CONSENT("cs_ucfr"), + const val USER_CONSENT = "cs_ucfr" } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt new file mode 100644 index 000000000..a6b7f48e3 --- /dev/null +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023. SRG SSR. All rights reserved. + * License information is available from the LICENSE file. + */ +package ch.srgssr.pillarbox.analytics.comscore + +internal enum class ComScoreLabelInternal(val label: String) { + C8("c8"), + MP_BRAND("mp_brand"), + MP_V("mp_v"), +} diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt index ecf477065..5711ed8df 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt @@ -24,7 +24,7 @@ data class ComScorePageView( fun toLabels(): Map { val labels = HashMap() labels.putAll(this.labels.filterValues { value -> value.isNotBlank() }) - labels[ComScoreLabel.C8.label] = name + labels[ComScoreLabelInternal.C8.label] = name return labels } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt index 50f14a028..aa0c86af3 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt @@ -66,8 +66,8 @@ internal object ComScoreSrg : ComScore { Log.e("COMSCORE", "Cannot find package", e) BuildConfig.VERSION_NAME } - persistentLabels[ComScoreLabel.MP_V.label] = versionName - persistentLabels[ComScoreLabel.MP_BRAND.label] = config.vendor.toString() + persistentLabels[ComScoreLabelInternal.MP_V.label] = versionName + persistentLabels[ComScoreLabelInternal.MP_BRAND.label] = config.vendor.toString() val publisher = PublisherConfiguration.Builder() .publisherId(publisherId) .persistentLabels(persistentLabels) diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt index e9de50dcc..809694411 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt @@ -4,7 +4,7 @@ */ package ch.srgssr.pillarbox.analytics -import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel +import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabelInternal import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView import org.junit.Assert import org.junit.Test @@ -17,7 +17,7 @@ class ComScoreEventTest { val pageView = ComScorePageView(title) val actual = pageView.toLabels() val expected = HashMap().apply { - this[ComScoreLabel.C8.label] = "title 1" + this[ComScoreLabelInternal.C8.label] = "title 1" } Assert.assertEquals(actual, expected) } @@ -36,7 +36,7 @@ class ComScoreEventTest { val pageView = ComScorePageView(title, customLabels) val actual = pageView.toLabels() val expected = HashMap().apply { - this[ComScoreLabel.C8.label] = "title 1" + this[ComScoreLabelInternal.C8.label] = "title 1" this["key1"] = "value1" } Assert.assertEquals(actual, expected) diff --git a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt index 487f616e1..bd2f9d9d6 100644 --- a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt +++ b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt @@ -7,6 +7,8 @@ package ch.srgssr.pillarbox.demo import android.app.Application import ch.srgssr.pillarbox.analytics.AnalyticsConfig import ch.srgssr.pillarbox.analytics.SRGAnalytics.initSRGAnalytics +import ch.srgssr.pillarbox.analytics.commandersact.CommandersActLabels +import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel /** * Demo application @@ -20,7 +22,9 @@ class DemoApplication : Application() { vendor = AnalyticsConfig.Vendor.SRG, nonLocalizedApplicationName = "Pillarbox", appSiteName = "pillarbox-demo-android", - sourceKey = AnalyticsConfig.SOURCE_KEY_SRG_DEBUG + sourceKey = AnalyticsConfig.SOURCE_KEY_SRG_DEBUG, + commandersActPersistentLabels = mapOf(Pair(CommandersActLabels.CONSENT_SERVICES.label, "service1,service2")), + comScorePersistentLabels = mapOf(Pair(ComScoreLabel.USER_CONSENT, "")) ) initSRGAnalytics(config = config) } From 156937cbf4fe730e3c3b7bc9fe633a0194f86308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Tue, 5 Sep 2023 14:33:18 +0200 Subject: [PATCH 07/11] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Samuel Défago --- .../java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt index 911687541..4294bb4a2 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt @@ -95,7 +95,7 @@ object SRGAnalytics { /** * Put persistent labels * - * @param commandersActLabels CommandersAct specific permanent label. + * @param commandersActLabels CommandersAct specific persistent label. * @param comScoreLabels ComScore specific persistent label. */ fun putPersistentLabels( @@ -115,7 +115,7 @@ object SRGAnalytics { } /** - * Remove multiple persistent label. + * Remove multiple persistent labels. * * @param labels List of labels to remove. */ @@ -131,7 +131,7 @@ object SRGAnalytics { * Get ComScore persistent label * * @param label The label to get. - * @return associated ComScore label or null if nothing found. + * @return associated ComScore label or null if not found. */ fun getComScorePersistentLabel(label: String): String? { return instance?.getComScorePersistentLabel(label) @@ -141,7 +141,7 @@ object SRGAnalytics { * Get CommandersAct persistent label * * @param label The label to get. - * @return associated CommandersAct label or null if nothing found. + * @return associated CommandersAct label or null if not found. */ fun getCommandersActPersistentLabel(label: String): String? { return instance?.getCommandersActPermanentData(label) From a98ee19c9f390afc3fa56f83d2fea4a1aeaaf2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Wed, 6 Sep 2023 11:22:17 +0200 Subject: [PATCH 08/11] Add user consent api. --- .../pillarbox/analytics/TestComScoreSrg.kt | 31 ++++++++++++++++-- .../pillarbox/analytics/TestCommandersAct.kt | 9 ++++++ .../pillarbox/analytics/AnalyticsConfig.kt | 2 ++ .../srgssr/pillarbox/analytics/UserConsent.kt | 18 +++++++++++ .../analytics/commandersact/CommandersAct.kt | 7 ++++ .../commandersact/CommandersActSrg.kt | 4 +++ .../pillarbox/analytics/comscore/ComScore.kt | 7 ++++ .../analytics/comscore/ComScoreLabel.kt | 13 +++----- .../comscore/ComScoreLabelInternal.kt | 11 ------- .../analytics/comscore/ComScorePageView.kt | 2 +- .../analytics/comscore/ComScoreSrg.kt | 25 +++++++++++++-- .../analytics/comscore/ComScoreUserConsent.kt | 32 +++++++++++++++++++ .../pillarbox/analytics/ComScoreEventTest.kt | 6 ++-- .../analytics/TestSRGAnalyticsPageViews.kt | 11 ++++++- .../srgssr/pillarbox/demo/DemoApplication.kt | 12 ++++--- 15 files changed, 157 insertions(+), 33 deletions(-) create mode 100644 pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/UserConsent.kt delete mode 100644 pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt create mode 100644 pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt diff --git a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt index 2238b3624..d92f2bae0 100644 --- a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt +++ b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt @@ -5,9 +5,10 @@ package ch.srgssr.pillarbox.analytics import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation -import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabelInternal +import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView import ch.srgssr.pillarbox.analytics.comscore.ComScoreSrg +import ch.srgssr.pillarbox.analytics.comscore.ComScoreUserConsent import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow @@ -41,7 +42,7 @@ class TestComScoreSrg { val pageTitle = "Title" val pageView = ComScorePageView(name = pageTitle) val actualLabels = ArrayList>() - val expectedLabels = listOf(mapOf(Pair(ComScoreLabelInternal.C8.label, pageTitle))) + val expectedLabels = listOf(mapOf(Pair(ComScoreLabel.C8.label, pageTitle))) val job = launch(dispatcher) { tracker.pageViewFlow.take(1).toList(actualLabels) } @@ -58,7 +59,7 @@ class TestComScoreSrg { val labels = mapOf(Pair("key1", "value01"), Pair("key2", " ")) val pageView = ComScorePageView(name = pageTitle, labels = labels) val actualLabels = ArrayList>() - val expectedLabels = listOf(mapOf(Pair(ComScoreLabelInternal.C8.label, pageTitle), Pair("key1", "value01"))) + val expectedLabels = listOf(mapOf(Pair(ComScoreLabel.C8.label, pageTitle), Pair("key1", "value01"))) val job = launch(dispatcher) { tracker.pageViewFlow.take(1).toList(actualLabels) } @@ -67,6 +68,30 @@ class TestComScoreSrg { job.cancel() } + @Test + fun testUserConsentGiven() { + val userConsent = ComScoreUserConsent.GIVEN + val expectedLabel = "1" + comScore.setUserConsent(userConsent) + Assert.assertEquals(expectedLabel, comScore.getPersistentLabel(ComScoreLabel.CS_UC_FR.label)) + } + + @Test + fun testUserConsentNotGiven() { + val userConsent = ComScoreUserConsent.REFUSED + val expectedLabel = "0" + comScore.setUserConsent(userConsent) + Assert.assertEquals(expectedLabel, comScore.getPersistentLabel(ComScoreLabel.CS_UC_FR.label)) + } + + @Test + fun testUserConsentUnknown() { + val userConsent = ComScoreUserConsent.UNKNOWN + val expectedLabel = "" + comScore.setUserConsent(userConsent) + Assert.assertEquals(expectedLabel, comScore.getPersistentLabel(ComScoreLabel.CS_UC_FR.label)) + } + private class PageViewTracking : ComScoreSrg.DebugListener { val pageViewFlow = MutableSharedFlow>(extraBufferCapacity = 1, replay = 1) diff --git a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestCommandersAct.kt b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestCommandersAct.kt index 101e49681..4c5debc38 100644 --- a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestCommandersAct.kt +++ b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestCommandersAct.kt @@ -6,6 +6,7 @@ package ch.srgssr.pillarbox.analytics import androidx.test.platform.app.InstrumentationRegistry import ch.srgssr.pillarbox.analytics.commandersact.CommandersActEvent +import ch.srgssr.pillarbox.analytics.commandersact.CommandersActLabels import ch.srgssr.pillarbox.analytics.commandersact.CommandersActPageView import ch.srgssr.pillarbox.analytics.commandersact.CommandersActSrg import org.junit.Assert @@ -39,4 +40,12 @@ class TestCommandersAct { ) Assert.assertTrue(true) } + + @Test + fun testConsentServices() { + val services = listOf("service1", "service2") + val expected = "service1,service2" + commandersAct.setConsentServices(services) + Assert.assertEquals(expected, commandersAct.getPermanentDataLabel(CommandersActLabels.CONSENT_SERVICES.label)) + } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt index f7c9b8b2e..7993c6f8d 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/AnalyticsConfig.kt @@ -12,6 +12,7 @@ package ch.srgssr.pillarbox.analytics * @property sourceKey The CommandersAct sourceKey given by the analytics team. * @property nonLocalizedApplicationName Application name for the analytics, by default the application name defined in the manifest. You can set * it to null if the application name is not localized. + * @property userConsent User consent to transmit to ComScore and CommandersAct. * @property comScorePersistentLabels initial ComScore persistent labels. * @property commandersActPersistentLabels initial CommandersAct persistent labels. */ @@ -20,6 +21,7 @@ data class AnalyticsConfig( val appSiteName: String, val sourceKey: String, val nonLocalizedApplicationName: String? = null, + val userConsent: UserConsent = UserConsent(), val comScorePersistentLabels: Map? = null, val commandersActPersistentLabels: Map? = null, ) { diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/UserConsent.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/UserConsent.kt new file mode 100644 index 000000000..c17109dbc --- /dev/null +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/UserConsent.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023. SRG SSR. All rights reserved. + * License information is available from the LICENSE file. + */ +package ch.srgssr.pillarbox.analytics + +import ch.srgssr.pillarbox.analytics.comscore.ComScoreUserConsent + +/** + * User consent + * + * @property comScore ComScore user consent. + * @property commandersActConsentServices CommandersAct consent services list. + */ +data class UserConsent( + val comScore: ComScoreUserConsent = ComScoreUserConsent.UNKNOWN, + val commandersActConsentServices: List = emptyList() +) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt index 520bb9353..fad119868 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersAct.kt @@ -55,4 +55,11 @@ interface CommandersAct { * @return null if not found. */ fun getPermanentDataLabel(label: String): String? + + /** + * Set consent services + * + * @param consentServices The list of consent services by the user. + */ + fun setConsentServices(consentServices: List) } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt index 2bb5ddf38..d37f81c58 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/commandersact/CommandersActSrg.kt @@ -103,6 +103,10 @@ internal class CommandersActSrg( return tcServerSide.getPermanentData(label) } + override fun setConsentServices(consentServices: List) { + tcServerSide.addPermanentData(CommandersActLabels.CONSENT_SERVICES.label, consentServices.joinToString(",")) + } + /** * Override application name if [AnalyticsConfig.nonLocalizedApplicationName] is not empty. * Useful for application that localized their application name and want to have same name for analytics. diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt index 8840d1d16..a1b2d568d 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScore.kt @@ -37,4 +37,11 @@ interface ComScore { * @return null if not found. */ fun getPersistentLabel(label: String): String? + + /** + * Set user consent + * + * @param userConsent + */ + fun setUserConsent(userConsent: ComScoreUserConsent) } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt index d1f79c578..24c20ba55 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabel.kt @@ -4,12 +4,9 @@ */ package ch.srgssr.pillarbox.analytics.comscore -/** - * Public ComScore label - */ -object ComScoreLabel { - /** - * Please refer to ComScore android implementation guide section 2.5. - */ - const val USER_CONSENT = "cs_ucfr" +internal enum class ComScoreLabel(val label: String) { + C8("c8"), + MP_BRAND("mp_brand"), + MP_V("mp_v"), + CS_UC_FR("cs_ucfr") } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt deleted file mode 100644 index a6b7f48e3..000000000 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreLabelInternal.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023. SRG SSR. All rights reserved. - * License information is available from the LICENSE file. - */ -package ch.srgssr.pillarbox.analytics.comscore - -internal enum class ComScoreLabelInternal(val label: String) { - C8("c8"), - MP_BRAND("mp_brand"), - MP_V("mp_v"), -} diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt index 5711ed8df..ecf477065 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScorePageView.kt @@ -24,7 +24,7 @@ data class ComScorePageView( fun toLabels(): Map { val labels = HashMap() labels.putAll(this.labels.filterValues { value -> value.isNotBlank() }) - labels[ComScoreLabelInternal.C8.label] = name + labels[ComScoreLabel.C8.label] = name return labels } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt index aa0c86af3..fd1c053c8 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt @@ -53,11 +53,15 @@ internal object ComScoreSrg : ComScore { return this } this.config = config + val persistentLabels = HashMap() config.comScorePersistentLabels?.let { labels -> persistentLabels.putAll(labels) } + val userConsentLabel = getUserConsentPair(config.userConsent.comScore) + persistentLabels[userConsentLabel.first] = userConsentLabel.second + val versionName: String = try { // When unit testing from library packageInfo.versionName is null! context.applicationContext.packageManager.getPackageInfo(context.applicationContext.packageName, 0).versionName @@ -66,8 +70,8 @@ internal object ComScoreSrg : ComScore { Log.e("COMSCORE", "Cannot find package", e) BuildConfig.VERSION_NAME } - persistentLabels[ComScoreLabelInternal.MP_V.label] = versionName - persistentLabels[ComScoreLabelInternal.MP_BRAND.label] = config.vendor.toString() + persistentLabels[ComScoreLabel.MP_V.label] = versionName + persistentLabels[ComScoreLabel.MP_BRAND.label] = config.vendor.toString() val publisher = PublisherConfiguration.Builder() .publisherId(publisherId) .persistentLabels(persistentLabels) @@ -121,6 +125,23 @@ internal object ComScoreSrg : ComScore { return configuration.getPersistentLabel(label) } + override fun setUserConsent(userConsent: ComScoreUserConsent) { + putPersistentLabels(mapOf(getUserConsentPair(userConsent))) + // Analytics.notifyHiddenEvent() // FIXME Send updated user consent or wait next page view or media event? + } + + /** + * Values from ComScore documentation section 2.5.2 + */ + private fun getUserConsentPair(userConsent: ComScoreUserConsent): Pair { + val value = when (userConsent) { + ComScoreUserConsent.GIVEN -> "1" + ComScoreUserConsent.REFUSED -> "0" + ComScoreUserConsent.UNKNOWN -> "" + } + return Pair(ComScoreLabel.CS_UC_FR.label, value) + } + private fun checkInitialized() { requireNotNull(config) { "ComScore init has to be called before start." } } diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt new file mode 100644 index 000000000..13cb48734 --- /dev/null +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023. SRG SSR. All rights reserved. + * License information is available from the LICENSE file. + */ +package ch.srgssr.pillarbox.analytics.comscore + +/** + * Com score user consent + */ +enum class ComScoreUserConsent { + /** + * Unknown + * + * User has not taken an action. + */ + UNKNOWN, + + /** + * Given + * + * User has given consent. + */ + GIVEN, + + /** + * Refuse + * + * User has not given consent or has opted out. + */ + REFUSED, + ; +} diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt index 809694411..e9de50dcc 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/ComScoreEventTest.kt @@ -4,7 +4,7 @@ */ package ch.srgssr.pillarbox.analytics -import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabelInternal +import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView import org.junit.Assert import org.junit.Test @@ -17,7 +17,7 @@ class ComScoreEventTest { val pageView = ComScorePageView(title) val actual = pageView.toLabels() val expected = HashMap().apply { - this[ComScoreLabelInternal.C8.label] = "title 1" + this[ComScoreLabel.C8.label] = "title 1" } Assert.assertEquals(actual, expected) } @@ -36,7 +36,7 @@ class ComScoreEventTest { val pageView = ComScorePageView(title, customLabels) val actual = pageView.toLabels() val expected = HashMap().apply { - this[ComScoreLabelInternal.C8.label] = "title 1" + this[ComScoreLabel.C8.label] = "title 1" this["key1"] = "value1" } Assert.assertEquals(actual, expected) diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt index 784a687ee..89900a348 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/TestSRGAnalyticsPageViews.kt @@ -10,6 +10,7 @@ import ch.srgssr.pillarbox.analytics.commandersact.CommandersActPageView import ch.srgssr.pillarbox.analytics.commandersact.TCMediaEvent import ch.srgssr.pillarbox.analytics.comscore.ComScore import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView +import ch.srgssr.pillarbox.analytics.comscore.ComScoreUserConsent import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow @@ -71,7 +72,7 @@ class TestSRGAnalyticsPageViews { Assert.assertTrue(pageViewFlow.tryEmit(pageView)) } - override fun putPersistentLabels(labels: Map?) { + override fun putPersistentLabels(labels: Map) { // Nothing } @@ -83,6 +84,10 @@ class TestSRGAnalyticsPageViews { // Nothing return null } + + override fun setUserConsent(userConsent: ComScoreUserConsent) { + // Nothing + } } private class DummyCommandersAct : CommandersAct { @@ -113,5 +118,9 @@ class TestSRGAnalyticsPageViews { return null } + override fun setConsentServices(consentServices: List) { + // Nothing + } + } } diff --git a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt index bd2f9d9d6..b650de040 100644 --- a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt +++ b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/DemoApplication.kt @@ -7,8 +7,8 @@ package ch.srgssr.pillarbox.demo import android.app.Application import ch.srgssr.pillarbox.analytics.AnalyticsConfig import ch.srgssr.pillarbox.analytics.SRGAnalytics.initSRGAnalytics -import ch.srgssr.pillarbox.analytics.commandersact.CommandersActLabels -import ch.srgssr.pillarbox.analytics.comscore.ComScoreLabel +import ch.srgssr.pillarbox.analytics.UserConsent +import ch.srgssr.pillarbox.analytics.comscore.ComScoreUserConsent /** * Demo application @@ -18,13 +18,17 @@ class DemoApplication : Application() { override fun onCreate() { super.onCreate() + // Defaults values + val initialUserConsent = UserConsent( + comScore = ComScoreUserConsent.UNKNOWN, + commandersActConsentServices = emptyList() + ) val config = AnalyticsConfig( vendor = AnalyticsConfig.Vendor.SRG, nonLocalizedApplicationName = "Pillarbox", appSiteName = "pillarbox-demo-android", sourceKey = AnalyticsConfig.SOURCE_KEY_SRG_DEBUG, - commandersActPersistentLabels = mapOf(Pair(CommandersActLabels.CONSENT_SERVICES.label, "service1,service2")), - comScorePersistentLabels = mapOf(Pair(ComScoreLabel.USER_CONSENT, "")) + userConsent = initialUserConsent ) initSRGAnalytics(config = config) } From f32eec411a8dd9b179f5e6bfb706dad3bf17863d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Wed, 6 Sep 2023 11:45:40 +0200 Subject: [PATCH 09/11] Fix tests --- .../pillarbox/core/business/CommandersActTrackerTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt index e759a4232..a7d137b8a 100644 --- a/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt +++ b/pillarbox-core-business/src/androidTest/java/ch/srgssr/pillarbox/core/business/CommandersActTrackerTest.kt @@ -289,6 +289,10 @@ class CommandersActTrackerTest { // Ignored } + override fun setConsentServices(consentServices: List) { + // Nothing + } + override fun sendEvent(event: ch.srgssr.pillarbox.analytics.commandersact.CommandersActEvent) { // Ignored } From f2322e0b8084e58a6317d772b84dd054a3b50f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Mon, 11 Sep 2023 11:52:33 +0200 Subject: [PATCH 10/11] Rename ComScore user consent enum. --- .../java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt | 4 ++-- .../ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt | 5 ++--- .../pillarbox/analytics/comscore/ComScoreUserConsent.kt | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt index d92f2bae0..c0dfb1db4 100644 --- a/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt +++ b/pillarbox-analytics/src/androidTest/java/ch/srgssr/pillarbox/analytics/TestComScoreSrg.kt @@ -70,7 +70,7 @@ class TestComScoreSrg { @Test fun testUserConsentGiven() { - val userConsent = ComScoreUserConsent.GIVEN + val userConsent = ComScoreUserConsent.ACCEPTED val expectedLabel = "1" comScore.setUserConsent(userConsent) Assert.assertEquals(expectedLabel, comScore.getPersistentLabel(ComScoreLabel.CS_UC_FR.label)) @@ -78,7 +78,7 @@ class TestComScoreSrg { @Test fun testUserConsentNotGiven() { - val userConsent = ComScoreUserConsent.REFUSED + val userConsent = ComScoreUserConsent.DECLINED val expectedLabel = "0" comScore.setUserConsent(userConsent) Assert.assertEquals(expectedLabel, comScore.getPersistentLabel(ComScoreLabel.CS_UC_FR.label)) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt index fd1c053c8..b9d41e051 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrg.kt @@ -127,7 +127,6 @@ internal object ComScoreSrg : ComScore { override fun setUserConsent(userConsent: ComScoreUserConsent) { putPersistentLabels(mapOf(getUserConsentPair(userConsent))) - // Analytics.notifyHiddenEvent() // FIXME Send updated user consent or wait next page view or media event? } /** @@ -135,8 +134,8 @@ internal object ComScoreSrg : ComScore { */ private fun getUserConsentPair(userConsent: ComScoreUserConsent): Pair { val value = when (userConsent) { - ComScoreUserConsent.GIVEN -> "1" - ComScoreUserConsent.REFUSED -> "0" + ComScoreUserConsent.ACCEPTED -> "1" + ComScoreUserConsent.DECLINED -> "0" ComScoreUserConsent.UNKNOWN -> "" } return Pair(ComScoreLabel.CS_UC_FR.label, value) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt index 13cb48734..111485a4b 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreUserConsent.kt @@ -16,17 +16,17 @@ enum class ComScoreUserConsent { UNKNOWN, /** - * Given + * Accepted * * User has given consent. */ - GIVEN, + ACCEPTED, /** - * Refuse + * Declined * * User has not given consent or has opted out. */ - REFUSED, + DECLINED, ; } From 87295d059c7d9ce7a69863392a849446151a5728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaquim=20St=C3=A4hli?= Date: Mon, 11 Sep 2023 11:52:50 +0200 Subject: [PATCH 11/11] Add missing set user consent to SRGAnalytics. --- .../ch/srgssr/pillarbox/analytics/SRGAnalytics.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt index 4294bb4a2..3561f3411 100644 --- a/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt +++ b/pillarbox-analytics/src/main/java/ch/srgssr/pillarbox/analytics/SRGAnalytics.kt @@ -147,6 +147,15 @@ object SRGAnalytics { return instance?.getCommandersActPermanentData(label) } + /** + * Set user consent + * + * @param userConsent The user consent to apply. + */ + fun setUserConsent(userConsent: UserConsent) { + instance?.setUserConsent(userConsent) + } + /** * Init SRGAnalytics * @@ -191,5 +200,10 @@ object SRGAnalytics { fun getCommandersActPermanentData(label: String): String? { return commandersAct.getPermanentDataLabel(label) } + + fun setUserConsent(userConsent: UserConsent) { + comScore.setUserConsent(userConsent.comScore) + commandersAct.setConsentServices(userConsent.commandersActConsentServices) + } } }