diff --git a/.changeset/giant-melons-leave.md b/.changeset/giant-melons-leave.md new file mode 100644 index 00000000..9760d36a --- /dev/null +++ b/.changeset/giant-melons-leave.md @@ -0,0 +1,5 @@ +--- +'@theoplayer/react-native-analytics-adobe': patch +--- + +Fixed an issue on Android where the properties from the passed metadata was not included with the `sessions` request. diff --git a/.changeset/huge-groups-appear.md b/.changeset/huge-groups-appear.md new file mode 100644 index 00000000..6a3126df --- /dev/null +++ b/.changeset/huge-groups-appear.md @@ -0,0 +1,5 @@ +--- +'@theoplayer/react-native-analytics-adobe': patch +--- + +Fixed an issue where the required `visitor.marketingCloudUserId` property was not included with the `sessions` request. diff --git a/adobe/android/src/main/java/com/theoplayer/reactnative/adobe/AdobeConnector.kt b/adobe/android/src/main/java/com/theoplayer/reactnative/adobe/AdobeConnector.kt index 6fd12870..6cd18492 100644 --- a/adobe/android/src/main/java/com/theoplayer/reactnative/adobe/AdobeConnector.kt +++ b/adobe/android/src/main/java/com/theoplayer/reactnative/adobe/AdobeConnector.kt @@ -104,7 +104,7 @@ class AdobeConnector( private var isPlayingAd = false - private var customMetadata: AdobeMetaData = AdobeMetaData() + private var currentMetadata: AdobeMetaData = AdobeMetaData() private var currentChapter: TextTrackCue? = null @@ -143,7 +143,7 @@ class AdobeConnector( private val onAdSkip: EventListener = EventListener { event -> handleAdSkip() } init { - this.customMetadata = metadata ?: AdobeMetaData() + this.currentMetadata = metadata ?: AdobeMetaData() this.customUserAgent = userAgent ?: buildUserAgent() addEventListeners() @@ -156,7 +156,7 @@ class AdobeConnector( } fun updateMetadata(metadata: AdobeMetaData) { - customMetadata.add(metadata) + currentMetadata.add(metadata) } fun setError(metadata: AdobeMetaData) { @@ -405,6 +405,9 @@ class AdobeConnector( return } val initialBody = createBaseRequest(AdobeEventTypes.SESSION_START) + /** + * https://experienceleague.adobe.com/en/docs/media-analytics/using/implementation/analytics-only/streaming-media-apis/mc-api-req-params + */ initialBody.params = mutableMapOf( "analytics.reportSuite" to sid, "analytics.trackingServer" to trackingUrl, @@ -414,10 +417,12 @@ class AdobeConnector( "media.length" to mediaLength, "media.playerName" to "THEOplayer", "visitor.marketingCloudOrgId" to this.ecid, + "visitor.marketingCloudUserId" to (currentMetadata.customMetadata?.get("visitorMID") ?: NA) ) player.source?.metadata?.get("title")?.let { initialBody.params?.put("media.name", it) } + currentMetadata.params?.forEach { initialBody.params?.set(it.key, it.value) } val body = addCustomMetadata(AdobeEventTypes.SESSION_START, initialBody) @@ -467,9 +472,9 @@ class AdobeConnector( AdobeEventTypes.SESSION_START ) ) { - body.customMetadata = customMetadata.customMetadata ?: mutableMapOf() + body.customMetadata = currentMetadata.customMetadata ?: mutableMapOf() } - body.qoeData = (body.qoeData.orEmpty() + customMetadata.qoeData.orEmpty()).toMutableMap() + body.qoeData = (body.qoeData.orEmpty() + currentMetadata.qoeData.orEmpty()).toMutableMap() return body } diff --git a/adobe/ios/Connector/AdobeConnector.swift b/adobe/ios/Connector/AdobeConnector.swift index d905ccbf..63abb80b 100644 --- a/adobe/ios/Connector/AdobeConnector.swift +++ b/adobe/ios/Connector/AdobeConnector.swift @@ -14,6 +14,7 @@ enum ContentType: String { let CONTENT_PING_INTERVAL = 10.0 let AD_PING_INTERVAL = 1.0 +let NA = "N/A" class AdobeConnector { private weak var player: THEOplayer? @@ -361,12 +362,13 @@ class AdobeConnector { var params: [String:Any] = [:] params["analytics.reportSuite"] = self.sid params["analytics.trackingServer"] = self.trackingUrl - params["media.channel"] = "N/A" + params["media.channel"] = NA params["media.contentType"] = self.getContentType().rawValue - params["media.id"] = "N/A" + params["media.id"] = NA params["media.length"] = mediaLength params["media.playerName"] = "THEOplayer" params["visitor.marketingCloudOrgId"] = self.ecid + params["visitor.marketingCloudUserId"] = self.currentMetadata?.customMetadata?["visitorMID"] ?? NA if let friendlyName = player.source?.metadata?.title { params["media.name"] = friendlyName } diff --git a/adobe/src/internal/DefaultAdobeConnectorAdapter.ts b/adobe/src/internal/DefaultAdobeConnectorAdapter.ts index c53df326..7fa604aa 100644 --- a/adobe/src/internal/DefaultAdobeConnectorAdapter.ts +++ b/adobe/src/internal/DefaultAdobeConnectorAdapter.ts @@ -10,6 +10,7 @@ import { AdobeConnectorAdapter } from './AdobeConnectorAdapter'; const TAG = 'AdobeConnector'; const CONTENT_PING_INTERVAL = 10000; const AD_PING_INTERVAL = 1000; +const NA = 'N/A'; /** * An all-TypeScript implementation of the AdobeConnector. @@ -47,7 +48,7 @@ export class DefaultAdobeConnectorAdapter implements AdobeConnectorAdapter { private isPlayingAd = false; - private customMetadata: AdobeMetaData = {}; + private currentMetadata: AdobeMetaData = {}; private currentChapter: TextTrackCue | undefined; @@ -71,7 +72,7 @@ export class DefaultAdobeConnectorAdapter implements AdobeConnectorAdapter { this.sid = sid; this.debug = debug; this.trackingUrl = trackingUrl; - this.customMetadata = { ...this.customMetadata, ...metadata }; + this.currentMetadata = { ...this.currentMetadata, ...metadata }; this.customUserAgent = userAgent || buildUserAgent(); this.addEventListeners(); @@ -84,7 +85,7 @@ export class DefaultAdobeConnectorAdapter implements AdobeConnectorAdapter { } updateMetadata(metadata: AdobeMetaData): void { - this.customMetadata = { ...this.customMetadata, ...metadata }; + this.currentMetadata = { ...this.currentMetadata, ...metadata }; } setError(metadata: AdobeMetaData): void { @@ -316,17 +317,21 @@ export class DefaultAdobeConnectorAdapter implements AdobeConnectorAdapter { 'media.name': this.player.source.metadata.title, }; } + /** + * https://experienceleague.adobe.com/en/docs/media-analytics/using/implementation/analytics-only/streaming-media-apis/mc-api-req-params + */ initialBody.params = { 'analytics.reportSuite': this.sid, 'analytics.trackingServer': this.trackingUrl, - 'media.channel': 'N/A', + 'media.channel': NA, 'media.contentType': this.getContentType(), - 'media.id': 'N/A', + 'media.id': NA, 'media.length': mediaLength, 'media.playerName': 'THEOplayer', // TODO make distinctions between platforms? 'visitor.marketingCloudOrgId': this.ecid, + 'visitor.marketingCloudUserId': this.currentMetadata.customMetadata?.['visitorMID'] || NA, ...friendlyName, - ...this.customMetadata.params, + ...this.currentMetadata.params, }; const body = this.addCustomMetadata(AdobeEventTypes.SESSION_START, initialBody); @@ -370,11 +375,11 @@ export class DefaultAdobeConnectorAdapter implements AdobeConnectorAdapter { eventType === AdobeEventTypes.AD_START || eventType === AdobeEventTypes.SESSION_START ) { - body.customMetadata = { ...this.customMetadata.customMetadata }; + body.customMetadata = { ...this.currentMetadata.customMetadata }; } // TODO check params which are fine and which need more limitations? } - body.qoeData = { ...body.qoeData, ...this.customMetadata.qoeData }; + body.qoeData = { ...body.qoeData, ...this.currentMetadata.qoeData }; return body; }