diff --git a/README.md b/README.md index 599111f..828b33f 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,24 @@ Adobe Analytics for Audio and Video is an add-on to the base Analytics offering Starting with v2.2 release, the Video Heartbeat Library (VHL) SDKs are renamed to Media SDKs to support Audio and Video tracking. The Media 2.2 SDK is fully backwards compatible with the VHL 2.x SDK series. The name change does not represent a functional break, simply a change in naming convention. -Starting with v3.0, the SDK uses Media Collection API for tracking. The 3.x SDK is not backward compatible with 2.x SDK series. -For more information on media collection endpoint, contact your Adobe representative. +Starting with v3.0, the SDK uses Media Collection API for tracking. The 3.x SDK is not backward compatible with the 2.x SDK. -For additional information regarding Adobe Analytics for Audio and Video, please visit our [documentation](https://docs.adobe.com/content/help/en/media-analytics/using/media-overview.html) +For additional information regarding Adobe Analytics for Audio and Video, see the [Streaming Media services documentation](https://experienceleague.adobe.com/docs/media-analytics/using/media-overview.html). -### Links for API documentation. +## SDK documentation and guides -[Android](https://adobe-marketing-cloud.github.io/media-sdks/reference/android/) +See the [docs/](./docs/) folder for setup guides, migration references, and validation docs organized by SDK version: -[iOS](https://adobe-marketing-cloud.github.io/media-sdks/reference/ios/) +| Version | Status | Platforms | +|---|---|---| +| [3.x](https://experienceleague.adobe.com/docs/media-analytics/using/implementation/overview.html) | Supported (Analytics only) | JavaScript, Chromecast, Roku | +| [2.x](./docs/2.x/) | End of support Aug 31, 2021 | Android, iOS, JavaScript | +| [1.x](https://github.com/Adobe-Marketing-Cloud/video-heartbeat/tree/master/docs) | Deprecated | Android, iOS, JavaScript, Apple TV, Chromecast, Roku, TVML | -[Javascript (Browser)](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/) +### Links for API documentation -[Javascript 3.x (Browser)](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript_3x/index.html) - -[Chromecast](https://adobe-marketing-cloud.github.io/media-sdks/reference/chromecast/) \ No newline at end of file +* [Android](https://adobe-marketing-cloud.github.io/media-sdks/reference/android/) +* [iOS](https://adobe-marketing-cloud.github.io/media-sdks/reference/ios/) +* [Javascript (Browser)](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/) +* [Javascript 3.x (Browser)](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript_3x/index.html) +* [Chromecast](https://adobe-marketing-cloud.github.io/media-sdks/reference/chromecast/) diff --git a/docs/2.x/README.md b/docs/2.x/README.md new file mode 100644 index 0000000..27db43d --- /dev/null +++ b/docs/2.x/README.md @@ -0,0 +1,112 @@ +# Media SDK 2.x Setup Overview + +> **End of Support:** The Media SDK 2.x reached end of support on August 31, 2021. Migrate to the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/home/) or the [Edge Network implementation](https://experienceleague.adobe.com/docs/media-analytics/using/implementation/overview.html). + +After you download the Media SDK for your video app or player, follow the information in this section to setup and implement the Media SDK. + +## General Implementation Guidelines + +There are three main SDK components used in tracking with streaming media services: + +* Media Heartbeat Config: The `MediaHeartbeatConfig` contains the basic settings for reporting. +* Media Heartbeat Delegate: The `MediaHeartbeatDelegate` controls playback time and the QoS object. +* Media Heartbeat: The `MediaHeartbeat` is the primary library containing members and methods. + +## Implement the Streaming Media SDK + +To setup and use the Streaming Media SDK, complete the following implementation steps: + +1. Create a `MediaHeartbeatConfig` instance and set your configuration parameter values. + + | Variable Name | Description | Required | Default Value | + |---|---|:---:|---| + | `trackingServer` | Tracking server for media analytics. This is different from your analytics tracking server. | Yes | Empty String | + | `channel` | Channel name | No | Empty String | + | `ovp` | Name of the online media platform through which content gets distributed | No | Empty String | + | `appVersion` | Version of the media player app/SDK | No | Empty String | + | `playerName` | Name of the media player in use. For example, "AVPlayer", "HTML5 Player", "My Custom Player" | No | Empty String | + | `ssl` | Indicates whether calls should be made over HTTPS | No | `false` | + | `debugLogging` | Indicates whether debug logging is enabled | No | `false` | + +1. Implement the `MediaHeartbeatDelegate`. + + | Method name | Description | Required | + | --- | --- | :---: | + | `getQoSObject()` | Returns the `MediaObject` instance that contains the current QoS information. This method will be called multiple times during a playback session. Player implementation must always return the most recently available QoS data. | Yes | + | `getCurrentPlaybackTime()` | Returns the current position of the playhead. For VOD tracking, the value is specified in seconds from the beginning of the media item. For live streaming, if the player does not provide information about the content duration, the value can be specified as the number of seconds since midnight UTC of that day. Note: When using progress markers, the content duration is required and the playhead needs to be updated as number of seconds from the beginning of the media item, starting with 0. | Yes | + + > The Quality of Service (QoS) object is optional. If QoS data is available for your player and you wish to track that data, then the following variables are required: + + | Variable name | Description | Required | + | --- | --- | :---: | + | `bitrate` | The bitrate of media in bits per second. | Yes | + | `startupTime` | The start up time of media in milliseconds. | Yes | + | `fps` | The frames displayed per second. | Yes | + | `droppedFrames` | The number of dropped frames so far. | Yes | + +1. Create the `MediaHeartbeat` instance. + + Use the `MediaHeartbeatConfig` and `MediaHeartbeatDelegate` to create the `MediaHeartbeat` instance. + + > Make sure that your `MediaHeartbeat` instance is accessible and does not get deallocated until the end of the session. This instance will be used for all the following media tracking events. + + > `MediaHeartbeat` requires an instance of `AppMeasurement` to send calls to Adobe Analytics. + +1. Combine all of the pieces. + + The following sample code utilizes our JavaScript 2.x SDK for an HTML5 video player: + + ```javascript + // Create local references to the heartbeat classes + var MediaHeartbeat = ADB.va.MediaHeartbeat; + var MediaHeartbeatConfig = ADB.va.MediaHeartbeatConfig; + var MediaHeartbeatDelegate = ADB.va.MediaHeartbeatDelegate; + + //Media Heartbeat Config + var mediaConfig = new MediaHeartbeatConfig(); + mediaConfig.trackingServer = "[your_namespace].hb.omtrdc.net"; + mediaConfig.playerName = "HTML5 Basic"; + mediaConfig.channel = "Video Channel"; + mediaConfig.debugLogging = true; + mediaConfig.appVersion = "2.0"; + mediaConfig.ssl = false; + mediaConfig.ovp = ""; + + // Media Heartbeat Delegate + var mediaDelegate = new MediaHeartbeatDelegate(); + + // Set mediaDelegate CurrentPlaybackTime + mediaDelegate.getCurrentPlaybackTime = function() { + return video.currentTime; + }; + + // Set mediaDelegate QoSObject - OPTIONAL + mediaDelegate.getQoSObject = function() { + return MediaHeartbeat.createQoSObject(video.bitrate, + video.startuptime, + video.fps, + video.droppedframes); + } + // Create mediaHeartbeat instance + this.mediaHeartbeat = + new MediaHeartbeat(mediaDelegate, mediaConfig, appMeasurementInstance); + ``` + +## Validate + +Media Analytics tracking implementations generate two types of tracking calls: + +* Media and ad Start calls are sent directly to the Adobe Analytics (AppMeasurement) server. +* Heartbeat calls are sent to the Media Analytics (heartbeats) tracking server, processed there, and passed on to the Adobe Analytics server. + +**Adobe Analytics (AppMeasurement) server** + +For more information about tracking server options, see [`trackingServerSecure`](https://experienceleague.adobe.com/en/docs/analytics/implementation/vars/config-vars/trackingserversecure). + +> An RDC tracking server or CNAME resolving to an RDC server is required for the Visitor ID service. + +**Media Analytics (Heartbeats) server** + +This always has the format "`[your_namespace].hb.omtrdc.net`". The value of "`[your_namespace]`" specifies your company, and is provided by Adobe. + +Media tracking works the same across all platforms, desktop and mobile. Audio tracking currently works on mobile platforms. For all tracking calls there are a few key universal variables to be validated. diff --git a/docs/2.x/android-setup.md b/docs/2.x/android-setup.md new file mode 100644 index 0000000..e287675 --- /dev/null +++ b/docs/2.x/android-setup.md @@ -0,0 +1,121 @@ +# Set up Android + +> **End of Support:** The Media SDK 2.x for Android reached end of support on August 31, 2021. Migrate to the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/home/) or the [Edge Network implementation](https://experienceleague.adobe.com/docs/media-analytics/using/implementation/overview.html). For additional information, see [Media Analytics SDK End-of-Support FAQs](https://experienceleague.adobe.com/docs/media-analytics/using/additional-resources/end-of-support-faqs.html). + +Learn how to set up streaming media services for Android devices. + +## Prerequisites + +* **Obtain valid configuration parameters for the Media SDK**: These parameters can be obtained from an Adobe representative after you set up your analytics account. +* **Implement ADBMobile for Android in your application**: For more information about the Adobe Mobile SDK documentation, see the [Android SDK 4.x documentation](https://github.com/Adobe-Marketing-Cloud/mobile-services/blob/master/docs/android/overview.md) + +* **Provide the following capabilities in your media player:** + * *An API to subscribe to player events*: The Media SDK requires that you call a set of simple APIs when events occur in your player. + * *An API that provides player information*: This information includes details such as the media name and the play head position. + +## SDK Implementation + +1. Add your downloaded Media SDK to your project. + + 1. Expand the Android zip file (e.g., `MediaSDK-android-v2.*.zip`). + 1. Verify that the `MediaSDK.jar` file exists in the `libs/` directory. + + 1. Add the library to your project. + + **IntelliJ IDEA:** + + 1. Right click your project in the **Project navigation** panel. + 1. Select **Open Module Settings**. + 1. Under **Project Settings**, select **Libraries**. + 1. Click **+** to add a new library. + 1. Select **Java** and navigate to the `MediaSDK.jar` file. + 1. Select the modules in which you plan to use the mobile library. + 1. Click **Apply** and then **OK** to close the Module Settings window. + + **Eclipse:** + + 1. In the Eclipse IDE, right-click on the project name. + 1. Click **Build Path** > **Add External Archives**. + 1. Select `MediaSDK.jar`. + 1. Click **Open**. + 1. Right-click the project again, and click **Build Path** > **Configure Build Path**. + 1. Click the **Order** and **Export** tabs. + 1. Ensure that the `MediaSDK.jar` file is selected. + +1. Import the library. + + ```java + import com.adobe.primetime.va.simple.MediaHeartbeat; + import com.adobe.primetime.va.simple.MediaHeartbeat.MediaHeartbeatDelegate; + import com.adobe.primetime.va.simple.MediaHeartbeatConfig; + import com.adobe.primetime.va.simple.MediaObject; + ``` + +1. Create the `MediaHeartbeatConfig` instance. + + Here is a sample `MediaHeartbeatConfig` initialization: + + ```java + // Media Heartbeat Initialization + config.trackingServer = __; + config.channel = ; + config.appVersion = ; + config.ovp = ; + config.playerName = ; + config.ssl = ; + config.debugLogging = ; + ``` + +1. Implement the `MediaHeartbeatDelegate` interface. + + ```java + public class VideoAnalyticsProvider implements Observer, MediaHeartbeatDelegate{} + ``` + + ```java + // Replace , , , and + // with the current playback QoS values. + @Override + public MediaObject getQoSObject() { + return MediaHeartbeat.createQoSObject(, + , + , + ); + } + + //Replace with the video player current playback time + @Override + public Double getCurrentPlaybackTime() { + return ; + } + ``` + +1. Create the `MediaHeartbeat` instance. + + Use the `MediaHeartbeatConfig` instance and the `MediaHeartbeatDelegate` instance to create the `MediaHeartbeat` instance. + + ```java + // Replace with your delegate instance + MediaHeartbeat _heartbeat = + new MediaHeartbeat(, config); + ``` + + > Make sure that your `MediaHeartbeat` instance is accessible and *does not get deallocated until the end of the session*. This instance is used for all of the following tracking events. + +## Adding App Permissions + +Your app using the Media SDK requires the following permissions to send data in tracking calls: + +* `INTERNET` +* `ACCESS_NETWORK_STATE` + +To add these permissions, add the following lines to your `AndroidManifest.xml` file in the application project directory: + +* `` +* `` + +## Migrating from version 1.x to 2.x in Android + +In versions 2.x, all of the public methods are consolidated into the `com.adobe.primetime.va.simple.MediaHeartbeat` class to make it easier on developers. Also, all configs are now consolidated into the `com.adobe.primetime.va.simple.MediaHeartbeatConfig` class. + +For information about migrating from 1.x to 2.x, see the [1.x to 2.x migration guide](./migration/1x-to-2x.md). diff --git a/docs/2.x/ios-setup.md b/docs/2.x/ios-setup.md new file mode 100644 index 0000000..14de69c --- /dev/null +++ b/docs/2.x/ios-setup.md @@ -0,0 +1,149 @@ +# Set up iOS + +> **End of Support:** The Media SDK 2.x for iOS reached end of support on August 31, 2021. Migrate to the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/home/) or the [Edge Network implementation](https://experienceleague.adobe.com/docs/media-analytics/using/implementation/overview.html). For additional information, see [Media Analytics SDK End-of-Support FAQs](https://experienceleague.adobe.com/docs/media-analytics/using/additional-resources/end-of-support-faqs.html). + +Learn to set up the streaming media services for iOS devices. + +## Prerequisites + +* **Obtain valid configuration parameters for the Media SDK**: These parameters can be obtained from an Adobe representative after you set up your analytics account. +* **Implement ADBMobile for iOS in your application**: For more information about the Adobe Mobile SDK documentation, see the [iOS SDK 4.x documentation](https://github.com/Adobe-Marketing-Cloud/mobile-services/blob/master/docs/ios/overview.md) + + > Beginning with iOS 9, Apple introduced a feature called App Transport Security (ATS). This feature aims to improve network security by ensuring that your apps use only industry-standard protocols and ciphers. This feature is enabled by default, but you have configuration options that provide you with choices for working with ATS. For details on ATS, see [App Transport Security.](https://experienceleague.adobe.com/docs/mobile-services/ios/config-ios/app-transport-security.html) + +* **Provide the following capabilities in your media player:** + + * *An API to subscribe to player events*: The Media SDK requires that you call a set of simple APIs when events occur in your player. + * *An API that provides player information*: This information includes details such as the media name and the play head position. + +## SDK Implementation + +> Starting with version 2.3.0, the SDK is distributed via XCFrameworks. +> +> Version 2.3.0 of the SDK requires Xcode 12.0 or newer and, if applicable, Cocoapods 1.10.0 or newer. + +* Any time a binary library file is mentioned, its XCFramework replacement should be used instead: + * MediaSDK.a > MediaSDK.xcframework + * MediaSDK_TV.a > MediaSDKTV.xcframework +* If manually adding the Adobe XCFrameworks to your project, ensure that they are not embedded. + +1. Add your [downloaded](https://experienceleague.adobe.com/docs/media-analytics/using/getting-started/download-sdks.html) Media SDK to your project. + + 1. Verify that the following software components exist in the `libs` directory: + + * `ADBMediaHeartbeat.h`: The Objective-C header file that is used for iOS heartbeat tracking APIs. + * `ADBMediaHeartbeatConfig.h`: The Objective-C header file for the SDK configuration. + * `MediaSDK.a`: A bitcode-enabled fat binary that contains the library builds for iOS devices (armv7, armv7s, arm64) and simulators (i386 and x86_64). + + This binary should be linked when the target is intended for an iOS app. + + * `MediaSDK_TV.a`: A bitcode-enabled fat binary containing the library builds for new Apple TV devices (arm64) and simulator (x86_64). + + This binary should be linked when the target is intended for an Apple TV (tvOS) app. + + 1. Add the library to your project: + + 1. Launch the Xcode IDE and open your app. + 1. In **Project Navigator**, drag the `libs` directory and drop it under your project. + 1. Ensure that the **Copy Items if Needed** checkbox is selected, the **Create Groups** is selected, and none of the checkboxes in **Add to Target** are selected. + 1. Click **Finish**. + 1. In **Project Navigator**, select your app and select your targets. + 1. Link the required frameworks and libraries in the **Linked Frameworks** and **Libraries** section on the **General** tab. + + **iOS App Targets:** + + * **AdobeMobileLibrary.a** + * **MediaSDK.a** + * **libsqlite3.0.tbd** + + **Apple TV (tvOS) Targets:** + + * **AdobeMobileLibrary_TV.a** + * **MediaSDK_TV.a** + * **libsqlite3.0.tbd** + * **SystemConfiguration.framework** + + 1. Verify that your app builds without errors. + +1. Import the library. + + ```objc + #import "ADBMediaHeartbeat.h" + #import "ADBMediaHeartbeatConfig.h" + ``` + +1. Create a `ADBMediaHeartbeatConfig` instance. + + This section helps you to understand the `MediaHeartbeat` config parameters, and to set correct config values on your `MediaHeartbeat` instance for accurate tracking. + + Here is a sample `ADBMediaHeartbeatConfig` initialization: + + ```objc + // Media Heartbeat Initialization + ADBMediaHeartbeatConfig *config = [[ADBMediaHeartbeatConfig alloc] init]; + config.trackingServer = ; + config.channel = ; + config.appVersion = ; + config.ovp = ; + config.playerName = ; + config.ssl = ; + config.debugLogging = ; + ``` + +1. Implement the `ADBMediaHeartbeatDelegate` protocol. + + ```objc + @interface VideoAnalyticsProvider : NSObject + + @end + + @implementation VideoAnalyticsProvider + + // Replace , , and + // with the current playback QoS values. + - (ADBMediaObject *)getQoSObject { + return [ADBMediaHeartbeat createQoSObjectWithBitrate: + startupTime: + fps: + droppedFrames:]; + } + + // Return the current video player playhead position. + // Replace with the video player current playback time + - (NSTimeInterval)getCurrentPlaybackTime { + return ; + } + + @end + ``` + +1. Use the `ADBMediaHeartBeatConfig` and `ADBMediaHeartBeatDelegate` to create the `ADBMediaHeartbeat` instance. + + ```objc + //Replace with your delegate instance + _mediaHeartbeat = [[ADBMediaHeartbeat alloc] initWithDelegate: + config:config]; + ``` + + > Make sure that your `ADBMediaHeartbeat` instance is accessible and *does not get deallocated until the end of the session*. This instance will be used for all the following tracking events. + +## Migrating from version 1.x to 2.x in iOS + +In version 2.x, all of the public methods are consolidated into the `ADBMediaHeartbeat` class to make it easier on developers. All configurations have been consolidated into the `ADBMediaHeartbeatConfig` class. + +For information about migrating from 1.x to 2.x, see the [1.x to 2.x migration guide](./migration/1x-to-2x.md). + +## Configure a Native App for tvOS + +With the release of the new Apple TV, you can now create applications to run in the native tvOS environment. You can either create a purely native app, using any of several frameworks available in iOS, or you can create your app using XML templates and JavaScript. Starting with MediaSDK version 2.0, support for tvOS is available. For more information about tvOS, see [tvOS Developer site.](https://developer.apple.com/tvos/) + +Perform the following steps in your Xcode project. This guide is written assuming your project has a target that is an Apple TV app targeting tvOS: + +1. Drag the `VideoHeartbeat_TV.a` library file into your project's `lib` folder. + +1. In the **Build Phases** tab of your tvOS app's target, expand the **Link Binary with Libraries** section and add the following libraries: + + * `MediaSDK_TV.a` + * `AdobeMobileLibrary_TV.a` + * `libsqlite3.0.tbd` + * `SystemConfiguration.framework` diff --git a/docs/2.x/javascript-setup.md b/docs/2.x/javascript-setup.md new file mode 100644 index 0000000..faeb01e --- /dev/null +++ b/docs/2.x/javascript-setup.md @@ -0,0 +1,105 @@ +# Set up JavaScript 2.x + +> **End of Support:** The Media SDK 2.x for JavaScript reached end of support on August 31, 2021. Migrate to the [Adobe Experience Platform Web SDK](https://experienceleague.adobe.com/docs/experience-platform/edge/home.html) or the [Edge Network implementation](https://experienceleague.adobe.com/docs/media-analytics/using/implementation/overview.html). + +## Prerequisites + +* **Obtain valid configuration parameters**: These parameters can be obtained from an Adobe representative after you set up your analytics account. +* **Implement `AppMeasurement` for JavaScript in your media application**: For more information about the Adobe Mobile SDK documentation, see [Implementing Analytics Using JavaScript.](https://experienceleague.adobe.com/docs/analytics/implementation/js/overview.html) + +* **Provide the following capabilities in your media player:** + + * *An API to subscribe to player events*: The Media SDK requires that you call a set of simple APIs when events occur in your player. + * *An API that provides player information*: This information includes details such as the media name and the play head position. + +## SDK Implementation + +1. Add your [downloaded](https://experienceleague.adobe.com/docs/media-analytics/using/getting-started/download-sdks.html) library to your project. Create local references to the classes for convenience. + + 1. Expand the `MediaSDK-js-v2.*.zip` file that you downloaded. + 1. Verify that the `MediaSDK.min.js` file exists in the `libs` directory. + 1. Host the `MediaSDK.min.js` file. + + This core JavaScript file must be hosted on a web server that is accessible to all pages on your site. You need the path to these files for the next step. + + 1. Reference `MediaSDK.min.js` on all site pages. + + Include `MediaSDK` for JavaScript by adding the following line of code in the `` or `` tag on each page. For example: + + ```html + + ``` + + 1. To quickly verify that the library was successfully imported, instantiate the `ADB.va.MediaHeartbeatConfig` class. + + > From Version 2.1.0, the JavaScript SDK is compliant with the AMD and CommonJS module specifications, and `VideoHeartbeat.min.js` can also be used with compatible module loaders. + +1. For easy access to the APIs, create local references to the `MediaHeartbeat` classes. + + ```js + var MediaHeartbeat = ADB.va.MediaHeartbeat; + var MediaHeartbeatConfig = ADB.va.MediaHeartbeatConfig; + var MediaHeartbeatDelegate = ADB.va.MediaHeartbeatDelegate; + ``` + +1. Create a `MediaHeartbeatConfig` instance. + + This section helps you to understand `MediaHeartbeat` config parameters and how to set correct config values on your `MediaHeartbeat` instance, for accurate tracking. + + Here is a sample `MediaHeartbeatConfig` initialization: + + ```js + //Media Heartbeat initialization + var mediaConfig = new MediaHeartbeatConfig(); + mediaConfig.trackingServer = Configuration.HEARTBEAT.TRACKING_SERVER; + mediaConfig.playerName = Configuration.PLAYER.NAME; + mediaConfig.channel = Configuration.HEARTBEAT.CHANNEL; + mediaConfig.debugLogging = true; + mediaConfig.appVersion = Configuration.HEARTBEAT.SDK; + mediaConfig.ssl = false; + mediaConfig.ovp = Configuration.HEARTBEAT.OVP; + ``` + +1. Implement the `MediaHeartbeatDelegate` protocol. + + ```js + var mediaDelegate = new MediaHeartbeatDelegate(); + + // Replace with the video player current playback time + mediaDelegate.getCurrentPlaybackTime = function() { + return ; + }; + + // Replace , , and with the current playback QoS values. + mediaDelegate.getQoSObject = function() { + return MediaHeartbeat.createQoSObject(, , , ); + }; + ``` + +1. Create the `MediaHeartbeat` instance. + + Use the `MediaHeartbeatConfig` and `MediaHeartbeatDelegate` to create the `MediaHeartbeat` instance. + + ```js + this.mediaHeartbeat = new MediaHeartbeat(mediaDelegate, mediaConfig, appMeasurement); + ``` + + > Make sure that your `MediaHeartbeat` instance is accessible and does not get deallocated until the end of the media session. This instance will be used for all of the following tracking events. + + > `MediaHeartbeat` requires an instance of `AppMeasurement` to send calls to Adobe Analytics. Here is an example of an `AppMeasurement` instance: + + ```js + var appMeasurement = new AppMeasurement(); + appMeasurement.visitor = visitor; + appMeasurement.trackingServer = ".sc.omtrdc.net"; + appMeasurement.account = ; + appMeasurement.pageName = ; + appMeasurement.charSet = "UTF-8"; + ``` + +## Migrate from JavaScript 1.x to 2.x + +In version 2.x, all of the public methods are consolidated into the `ADB.va.MediaHeartbeat` class to make it easier on developers. Also, all configs are now consolidated into the `ADB.va.MediaHeartbeatConfig` class. + +For information about migrating from 1.x to 2.x, see the [1.x to 2.x migration guide](./migration/1x-to-2x.md). diff --git a/docs/2.x/migration/1x-to-2x.md b/docs/2.x/migration/1x-to-2x.md new file mode 100644 index 0000000..18c65e0 --- /dev/null +++ b/docs/2.x/migration/1x-to-2x.md @@ -0,0 +1,816 @@ +# Migrating from Media SDK 1.x to 2.x + +## Overview + +The migration from VHL 1.x to VHL 2.x is straightforward, with the new version featuring simplified APIs for initialization, configuration, and player delegates. + +Here are the primary differences between 1.x and 2.x: + +* **Plugins and delegates**: You no longer need to implement plugins and delegates for Analytics, VideoPlayer, and Heartbeat. +* **Configuration**: You no longer need to instantiate configurations for the 1.x plugins. + +### Benefits of 2.x + +* All of the public methods are consolidated into the `MediaHeartbeat` class to make implementation easier on developers. +* All configs are now consolidated into the `MediaHeartbeatConfig` class. +* You no longer need to instantiate configs for the Analytics, VideoPlayer, and Heartbeat plugins. You only need to instantiate the `MediaHeartbeat` class with `MediaHeartbeatDelegate` and `MediaHeartbeatConfig` instances. This is the only implementation that is required to initialize Media Analytics. + + With the initialization of `MediaHeartbeat`, you can safely delete all of the implementation for Analytics Plugin, VideoPlayer Plugin, and Heartbeat Plugin. Also, remove all the existing implementation for initialization that takes in an array of plugins as an input. + +--- + +## Code Comparison + +All of the configuration parameters and tracking APIs are now consolidated into the `MediaHeartbeats` and `MediaHeartbeatConfig` classes. + +**Configuration API changes:** + +* `AdobeHeartbeatPluginConfig.sdk`: Renamed to `MediaConfig.appVersion` +* `MediaHeartbeatConfig.playerName`: Now set through `MediaHeartbeatConfig` instead of `VideoPlayerPluginDelegate` +* The `AppMeasurement` instance (JavaScript only): Now sent through the `MediaHeartbeat` constructor. + +**Configuration properties changes:** + +* `sdk`: Renamed to `appVersion` +* `publisher`: Removed; IMS Org ID is used instead as a publisher +* `quietMode`: Removed + +**Links to 1.x and 2.x sample players:** + +* [1.x Sample Player](https://github.com/Adobe-Marketing-Cloud/video-heartbeat/blob/master/sdks/js/samples/BasicPlayerSample/script/app/analytics/video.analytics.provider.js#L58) +* [2.x Sample Player](https://github.com/Adobe-Marketing-Cloud/media-sdks/blob/master/sdks/js/2.x/samples/BasicPlayerSample/script/app/analytics/video.analytics.provider.js#L47) + +The following sections provide code comparisons between 1.x and 2.x, covering Initialization, Core Playback, Ad Playback, Chapter Playback, and some additional events. + +### VHL Code Comparison: INITIALIZATION + +#### Object Initialization + +| 1.x API | 2.x API | +| --- | --- | +| `Heartbeat()` | `MediaHeartbeat()` | +| `VideoPlayerPlugin()` | `MediaHeartbeatConfig()` | +| `AdobeAnalyticsPlugin()` | | +| `HeartbeatPlugin()` | | + +#### Video player plugin initialization (1.x) + +```js +this._playerPlugin = new VideoPlayerPlugin( new SampleVideoPlayerPluginDelegate(this._player)); +var playerPluginConfig = new VideoPlayerPluginConfig(); +playerPluginConfig.debugLogging = true; + +// Set up the AppMeasurement plugin +this._aaPlugin = new AdobeAnalyticsPlugin( appMeasurement, new SampleAdobeAnalyticsPluginDelegate()); +var aaPluginConfig = new AdobeAnalyticsPluginConfig(); +aaPluginConfig.channel = Configuration.HEARTBEAT.CHANNEL; +aaPluginConfig.debuglogging = true; +this._aaPlugin.configure(aaPluginConfig); + +// Set up the AdobeHeartbeat plugin +var ahPlugin = new AdobeHeartbeatPlugin( new SampleAdobeHeartbeatPluginDelegate()); +var ahPluginConfig = new AdobeHeartbeatPluginConfig( configuration.HEARTBEAT.TRACKING_SERVER, configuration.HEARTBEAT.PUBLISHER); +ahPluginConfig.ovp = configuration.HEARTBEAT.OVP; +ahPluginConfig.sdk = configuration.HEARTBEAT.SDK; +ahPluginConfig.debugLogging = true; +ahPlugin.configure(ahPluginConfig); +var plugins = [this._playerPlugin, this._aaPlugin, ahPlugin]; + +// Set up and configure the heartbeat library +this._heartbeat = new Heartbeat(new SampleHeartbeatDelegate(), plugins); +var configData = new HeartbeatConfig(); +configData.debugLogging = true; +this._heartbeat.configure(configData); +``` + +#### Media Heartbeat initialization (2.x) + +```js +var mediaConfig = new MediaHeartbeatConfig(); +mediaConfig.trackingServer = Configuration.HEARTBEAT.TRACKING_SERVER; +mediaConfig.playerName = Configuration.PLAYER.NAME; +mediaConfig.debugLogging = true; +mediaConfig.channel = Configuration.HEARTBEAT.CHANNEL; +mediaConfig.ssl = false; +mediaConfig.ovp = Configuration.HEARTBEAT.OVP; +mediaConfig.appVersion = Configuration.HEARTBEAT.SDK; +this._mediaHeartbeat = new MediaHeartbeat( new SampleMediaHeartbeatDelegate(this._player), mediaConfig, appMeasurement); +``` + +#### Delegates + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPluginDelegate()` | `MediaHeartbeatDelegate()` | +| `VideoPlayerPluginDelegate().getVideoInfo` | `MediaHeartbeatDelegate().getCurrentPlaybackTime` | +| `VideoPlayerPluginDelegate().getAdBreakInfo` | `MediaHeartbeatDelegate().getQoSObject` | +| `VideoPlayerPluginDelegate().getAdInfo` | | +| `VideoPlayerPluginDelegate().getChapterInfo` | | +| `VideoPlayerPluginDelegate().getQoSInfo` | | +| `VideoPlayerPluginDelegate().get.onError` | | +| `AdobeAnalyticsPluginDelegate()` | | + +#### VideoPlayerPluginDelegate (1.x) + +```js +$.extend(SampleVideoPlayerPluginDelegate.prototype, VideoPlayerPluginDelegate.prototype); + +function SampleVideoPlayerPluginDelegate(player) { + this._player = player; +} + +SampleVideoPlayerPluginDelegate.prototype.getVideoInfo = function() { + return this._player.getVideoInfo(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getAdBreakInfo = function() { + return this._player.getAdBreakInfo(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getAdInfo = function() { + return this._player.getAdInfo(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getChapterInfo = function() { + return this._player.getChapterInfo(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getQoSInfo = function() { + return this._player.getQoSInfo(); +}; +``` + +#### AdobeAnalyticsPluginDelegate (1.x) + +```js +$.extend(SampleAdobeAnalyticsPluginDelegate.prototype, AdobeAnalyticsPluginDelegate.prototype); + +function SampleAdobeAnalyticsPluginDelegate() {} + +SampleAdobeAnalyticsPluginDelegate.prototype.onError = function(errorInfo) { + console.log("AdobeAnalyticsPlugin error: " + errorInfo.getMessage() + " | " + errorInfo.getDetails()); +}; +``` + +#### HeartbeatDelegate (1.x) + +```js +$.extend(SampleHeartbeatDelegate.prototype, HeartbeatDelegate.prototype); + +function SampleHeartbeatDelegate() {} + +SampleHeartbeatDelegate.prototype.onError = function(errorInfo) { + console.log("Heartbeat error: " + errorInfo.getMessage() + " | " + errorInfo.getDetails()); +}; +``` + +#### MediaHeartbeatDelegate (2.x) + +```js +ADB.core.extend(SampleMediaHeartbeatDelegate.prototype, MediaHeartbeatDelegate.prototype); + +function SampleMediaHeartbeatDelegate(player) { + this._player = player; +} + +SampleMediaHeartbeatDelegate.prototype.getCurrentPlaybackTime = function() { + return this._player.getCurrentPlaybackTime(); +}; + +SampleMediaHeartbeatDelegate.prototype.getQoSObject = function() { + return this._player.getQoSInfo(); +}; + +this._mediaHeartbeat = new MediaHeartbeat(new SampleMediaHeartbeatDelegate(this._player), mediaConfig, appMeasurement); +``` + +### VHL Code Comparison: CORE PLAYBACK + +#### Session Start + +| VHL 1.x | VHL 2.x | +| --- | --- | +| `VideoPlayerPluginDelegate.trackVideoLoad()` | `MediaHeartbeat.createMediaObject()` | +| `VideoPlayerPluginDelegate.getVideoInfo()` | `MediaHeartbeat.trackSessionStart()` | + +##### Session Start (1.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + this._playerPlugin.trackVideoLoad(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getVideoInfo = function() { + return this._player.getVideoInfo(); +}; + +VideoPlayer.prototype.getVideoInfo = function() { + this._videoInfo.playhead = vTime; + return this._videoInfo; +}; +``` + +##### Session Start (2.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = {}; + var videoInfo = this._player.getVideoInfo(); + var mediaInfo = MediaHeartbeat.createMediaObject(videoInfo.name, videoInfo.id, videoInfo.length, videoInfo.streamType); + this._mediaHeartbeat.trackSessionStart(mediaInfo, contextData); +}; +``` + +#### Standard Video Metadata + +| 1.x API | 2.x API | +| --- | --- | +| `VideoMetadataKeys()` | `MediaHeartbeat.createMediaObject()` | +| `AdobeAnalyticsPlugin.setVideoMetadata()` | `MediaHeartbeat.trackSessionStart()` | + +##### Standard Metadata (1.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = {}; + + // Setting Standard Video Metadata + contextData[VideoMetadataKeys.SEASON] = "sample season"; + contextData[VideoMetadataKeys.SHOW] = "sample show"; + contextData[VideoMetadataKeys.EPISODE] = "sample episode"; + contextData[VideoMetadataKeys.ASSET_ID] = "sample asset id"; + contextData[VideoMetadataKeys.GENRE] = "sample genre"; + contextData[VideoMetadataKeys.FIRST_AIR_DATE] = "sample air date"; + + this._aaPlugin.setVideoMetadata(contextData); + this._playerPlugin.trackVideoLoad(); +}; +``` + +##### Standard Metadata (2.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = {}; + var mediaInfo = MediaHeartbeat.createMediaObject(videoInfo.name, videoInfo.id, videoInfo.length, videoInfo.streamType); + + // Set standard Video Metadata + var standardVideoMetadata = {}; + standardVideoMetadata[VideoMetadataKeys.SEASON] = "sample season"; + standardVideoMetadata[VideoMetadataKeys.SHOW] = "sample show"; + standardVideoMetadata[VideoMetadataKeys.EPISODE] = "sample episode"; + standardVideoMetadata[VideoMetadataKeys.ASSET_ID] = "sample asset id"; + standardVideoMetadata[VideoMetadataKeys.GENRE] = "sample genre"; + standardVideoMetadata[VideoMetadataKeys.FIRST_AIR_DATE] = "sample air date"; + + mediaInfo.setValue(MediaHeartbeat.MediaObjectKey.StandardVideoMetadata, standardVideoMetadata); + this._mediaHeartbeat.trackSessionStart(mediaInfo, contextData); +}; +``` + +> Instead of setting the Standard Video Metadata through the `AdobeAnalyticsPlugin.setVideoMetadata()` API, in VHL 2.0, the Standard Video Metadata is set through the MediaObject key `MediaObject.MediaObjectKey.StandardVideoMetadata()`. + +#### Custom Video Metadata + +| 1.x API | 2.x API | +| --- | --- | +| `VideoMetadataKeys()` | `MediaHeartbeat.createMediaObject()` | +| `AdobeAnalyticsPlugin.setVideoMetadata()` | `MediaHeartbeat.trackSessionStart()` | + +##### Custom Metadata (1.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = { + isUserLoggedIn: "false", + tvStation: "Sample TV station", + programmer: "Sample programmer" + }; + this._aaPlugin.setVideoMetadata(contextData); + this._playerPlugin.trackVideoLoad(); +}; +``` + +##### Custom Metadata (2.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = { + isUserLoggedIn: "false", + tvStation: "Sample TV station", + programmer: "Sample programmer" + }; + var videoInfo = this._player.getVideoInfo(); + var mediaInfo = MediaHeartbeat.createMediaObject(videoInfo.name, videoInfo.id, videoInfo.length, videoInfo.streamType); + mediaInfo.setValue(MediaHeartbeat.MediaObjectKey.StandardVideoMetadata, standardVideoMetadata); + this._mediaHeartbeat.trackSessionStart(mediaInfo, contextData); +}; +``` + +> Instead of setting the Custom Video Metadata through the `AdobeAnalyticsPlugin.setVideoMetadata()` API, in VHL 2.0, the Standard Video Metadata is set through the `MediaHeartbeat.trackSessionStart()` API. + +#### Playback + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackPlay()` | `MediaHeartbeat.trackPlay()` | + +##### Playback (1.x) + +```js +VideoAnalyticsProvider.prototype._onSeekStart = function() { + this._playerPlugin.trackSeekStart(); +}; +``` + +##### Playback (2.x) + +```js +VideoAnalyticsProvider.prototype._onSeekStart = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.SeekStart); +}; +``` + +#### Pause + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackPause()` | `MediaHeartbeat.trackPause()` | + +##### Pause (1.x) + +```js +VideoAnalyticsProvider.prototype._onPause = function() { + this._playerPlugin.trackPause(); +}; +``` + +##### Pause (2.x) + +```js +VideoAnalyticsProvider.prototype._onBufferComplete = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.BufferComplete); +}; +``` + +#### Seek Complete + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackSeekComplete()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.SeekComplete)` | + +##### Seeking (1.x) + +```js +VideoAnalyticsProvider.prototype._onSeekComplete = function() { + this._playerPlugin.trackSeekComplete(); +}; +``` + +##### Seeking (2.x) + +```js +VideoAnalyticsProvider.prototype._onSeekComplete = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.SeekComplete); +}; +``` + +#### Buffer Start + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackBufferStart()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.BufferStart)` | + +##### Buffer Start (1.x) + +```js +VideoAnalyticsProvider.prototype._onBufferStart = function() { + this._playerPlugin.trackBufferStart(); +}; +``` + +##### Buffer Start (2.x) + +```js +VideoAnalyticsProvider.prototype._onBufferStart = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.BufferStart); +}; +``` + +#### Buffer Complete + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackBufferComplete()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.BufferComplete)` | + +##### Buffer Complete (1.x) + +```js +VideoAnalyticsProvider.prototype._onBufferComplete = function() { + this._playerPlugin.trackBufferComplete(); +}; +``` + +##### Buffer Complete (2.x) + +```js +VideoAnalyticsProvider.prototype._onBufferComplete = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.BufferComplete); +}; +``` + +#### Playback Complete + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackComplete()` | `MediaHeartbeat.trackComplete()` | + +##### Playback Complete (1.x) + +```js +VideoAnalyticsProvider.prototype._onComplete = function() { + this._playerPlugin.trackComplete(function() { + console.log( "The completion of the content has been tracked."); + }); +}; +``` + +##### Playback Complete (2.x) + +```js +VideoAnalyticsProvider.prototype._onComplete = function() { + this._mediaHeartbeat.trackComplete(); +}; +``` + +### VHL Code Comparison: AD PLAYBACK + +#### Ad Start + +| VHL 1.x | VHL 2.x | +| --- | --- | +| `VideoPlayerPlugin.trackAdStart()` | `MediaHeartbeat.createAdBreakObject()` | +| `VideoPlayerPluginDelegate.getAdBreakInfo()` | `MediaHeartbeat.createAdObject()` | +| `VideoPlayerPluginDelegate.getAdInfo()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakStart)` | +| | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdStart)` | + +##### Ad Start (1.x) + +```js +VideoAnalyticsProvider.prototype._onAdStart = function() { + this._playerPlugin.trackAdStart(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getAdInfo = function() { + return this._player.getAdInfo(); +}; +``` + +##### Ad Start (2.x) + +```js +VideoAnalyticsProvider.prototype._onAdStart = function() { + var adContextData = {}; + + var _adBreakInfo = this._player.getAdBreakInfo(); + var adBreakInfo = MediaHeartbeat.createAdBreakObject(_adBreakInfo.name, _adBreakInfo.position, _adBreakInfo.startTime); + + var _adInfo = this._player.getAdInfo(); + var adInfo = MediaHeartbeat.createAdObject(_adInfo.name, _adInfo.id, _adInfo.position, _adInfo.length); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakStart, adBreakInfo); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdStart, adInfo, adContextData); +}; +``` + +#### Standard Ad Metadata + +| 1.x API | 2.x API | +| --- | --- | +| `AdMetadataKeys()` | `MediaHeartbeat.createAdObject()` | +| `AdobeAnalyticsPlugin.setAdMetadata()` | `MediaHeartbeat.trackAdStart()` | + +##### Standard Ad Metadata (1.x) + +```js +VideoAnalyticsProvider.prototype._onAdStart = function() { + var contextData = {}; + contextData[AdMetadataKeys.ADVERTISER] = "sample advertiser"; + contextData[AdMetadataKeys.CAMPAIGN_ID] = "sample campaign"; + contextData[AdMetadataKeys.CREATIVE_ID] = "sample creative"; + contextData[AdMetadataKeys.CREATIVE_URL] = "sample url"; + contextData[AdMetadataKeys.SITE_ID] = "sample site"; + contextData[AdMetadataKeys.PLACEMENT_ID] = "sample placement"; + this._aaPlugin.setAdMetadata(contextData); + this._playerPlugin.trackAdStart(); +}; +``` + +##### Standard Ad Metadata (2.x) + +```js +VideoAnalyticsProvider.prototype._onAdStart = function() { + var adContextData = { }; + + var _adBreakInfo = this._player.getAdBreakInfo(); + var adBreakInfo = MediaHeartbeat.createAdBreakObject(_adBreakInfo.name, _adBreakInfo.position, _adBreakInfo.startTime); + + var _adInfo = this._player.getAdInfo(); + var adInfo = MediaHeartbeat.createAdObject(_adInfo.name, _adInfo.id, _adInfo.position, _adInfo.length); + + var standardAdMetadata = {}; + standardAdMetadata[MediaHeartbeat.AdMetadataKeys.ADVERTISER] = "Sample Advertiser"; + standardAdMetadata[MediaHeartbeat.AdMetadataKeys.CAMPAIGN_ID] = "Sample Campaign"; + adInfo.setValue(MediaHeartbeat.MediaObjectKey.StandardAdMetadata, standardAdMetadata); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakStart, adBreakInfo); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdStart, adInfo, adContextData); +}; +``` + +> Instead of setting the Standard Ad Metadata through the `AdobeAnalyticsPlugin.setVideoMetadata()` API, in VHL 2.0, the Standard Ad Metadata is set through the `AdMetadata` key `MediaObject.MediaObjectKey.StandardVideoMetadata`. + +#### Custom Ad Metadata + +| 1.x API | 2.x API | +| --- | --- | +| `AdobeAnalyticsPlugin.setAdMetadata()` | `MediaHeartbeat.createAdObject()` | +| | `MediaHeartbeat.trackAdStart()` | + +##### Custom Ad Metadata (2.x) + +```js +VideoAnalyticsProvider.prototype._onAdStart = function() { + var adContextData = { + affiliate: "Sample affiliate", + campaign: "Sample ad campaign" + }; + + var _adBreakInfo = this._player.getAdBreakInfo(); + var adBreakInfo = MediaHeartbeat.createAdBreakObject(_adBreakInfo.name, _adBreakInfo.position, _adBreakInfo.startTime); + + var _adInfo = this._player.getAdInfo(); + var adInfo = MediaHeartbeat.createAdObject(_adInfo.name, _adInfo.id, _adInfo.position, _adInfo.length); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakStart, adBreakInfo); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdStart, adInfo, adContextData); +}; +``` + +> Instead of setting the Custom Ad Metadata through the `AdobeAnalyticsPlugin.setVideoMetadata` API, in VHL 2.0, the Standard Ad Metadata is set through the `MediaHeartbeat.trackAdStart()` API. + +#### Ad Skip + +##### Ad Skip (1.x) + +```js +SampleVideoPlayerPluginDelegate.prototype.getAdInfo = function() { + return this._player.getAdInfo(); +}; +``` + +##### Ad Skip (2.x) + +```js +VideoAnalyticsProvider.prototype._onAdSkip = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdSkip); +}; +``` + +> In VHL 1.5.X APIs, `getAdinfo()` and `getAdBreakInfo()` must return null if the player is outside the Ad break boundaries. + +#### Ad Complete + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackAdComplete()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdComplete)` | +| | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakComplete)` | + +##### Ad Complete (1.x) + +```js +VideoAnalyticsProvider.prototype._onAdComplete = function() { + this._playerPlugin.trackAdComplete(); +}; +``` + +##### Ad Complete (2.x) + +```js +VideoAnalyticsProvider.prototype._onAdComplete = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdComplete); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.AdBreakComplete); +}; +``` + +### VHL Code Comparison: CHAPTER PLAYBACK + +#### Chapter Start + +| VHL 1.x | VHL 2.x | +| --- | --- | +| `VideoPlayerPluginDelegate.getChapterInfo()` | `MediaHeartbeat.createChapterObject` | +| `VideoPlayerPlugin.trackChapterStart()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterStart)` | + +##### Chapter Start (1.x) + +```js +VideoAnalyticsProvider.prototype._onChapterStart = function() { + this._playerPlugin.trackChapterStart(); +}; + +SampleVideoPlayerPluginDelegate.prototype.getChapterInfo = function() { + return this._player.getChapterInfo(); +}; +``` + +##### Chapter Start (2.x) + +```js +VideoAnalyticsProvider.prototype._onChapterStart = function() { + var chapterContextData = { }; + + var _chapterInfo = this._player.getChapterInfo(); + var chapterInfo = MediaHeartbeat.createChapterObject(_chapterInfo.name, _chapterInfo.position, _chapterInfo.length, _chapterInfo.startTime); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterStart, chapterInfo, chapterContextData); +}; +``` + +#### Chapter Skip + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPluginDelegate.getChapterInfo()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterSkip)` | + +##### Chapter Skip (1.x) + +```js +SampleVideoPlayerPluginDelegate.prototype.getChapterInfo = function() { + return this._player.getChapterInfo(); +}; +``` + +> In VHL 1.5.X APIs, `getChapterinfo()` must return null if the player is outside the Chapter boundaries. + +##### Chapter Skip (2.x) + +```js +VideoAnalyticsProvider.prototype._onChapterSkip = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterSkip); +}; +``` + +#### Chapter Custom Metadata + +| 1.x API | 2.x API | +| --- | --- | +| `VideoPlayerPlugin.trackChapterStart()` | `MediaHeartbeat.createChapterObject()` | +| `AdobeAnalyticsPlugin.setChapterMetadata()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterStart)` | + +##### Chapter Custom Metadata (1.x) + +```js +VideoAnalyticsProvider.prototype._onChapterStart = function() { + this._aaPlugin.setChapterMetadata({ + segmentType: "Sample segment type" + }); + this._playerPlugin.trackChapterStart(); +}; +``` + +##### Chapter Custom Metadata (2.x) + +```js +VideoAnalyticsProvider.prototype._onChapterStart = function() { + var chapterContextData = { + segmentType: "Sample segment type" + }; + + var _chapterInfo = this._player.getChapterInfo(); + var chapterInfo = MediaHeartbeat.createChapterObject(_chapterInfo.name, _chapterInfo.position, _chapterInfo.length, _chapterInfo.startTime); + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterStart, chapterInfo, chapterContextData); +}; +``` + +#### Chapter Complete + +| 1.x API | 2.x API | +| --- | --- | +| `trackChapterComplete()` | `trackEvent(MediaHeartbeat.Event.ChapterComplete)` | + +##### Chapter Complete (1.x) + +```js +VideoAnalyticsProvider.prototype._onChapterComplete = function() { + this._playerPlugin.trackChapterComplete(); +}; +``` + +##### Chapter Complete (2.x) + +```js +VideoAnalyticsProvider.prototype._onChapterComplete = function() { + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.ChapterComplete); +}; +``` + +### VHL Code Comparison: OTHER EVENTS + +#### Bitrate Change + +| VHL 1.x | VHL 2.x | +| --- | --- | +| `VideoPlayerPlugin.trackBitrateChange()` | `MediaHeartbeat.trackEvent(MediaHeartbeat.Event.BitrateChange)` | + +##### Bitrate Change (1.x) + +```js +VideoAnalyticsProvider.prototype._onBitrateChange = function() { + // Update getQosInfo to return the updated bitrate + this._playerPlugin.trackBitrateChange(); +}; +``` + +##### Bitrate Change (2.x) + +```js +VideoAnalyticsProvider.prototype._onBitrateChange = function() { + // Update getQosObject to return the updated bitrate + this._mediaHeartbeat.trackEvent(MediaHeartbeat.Event.BitrateChange); +}; +``` + +#### Video Resume + +| 1.x API | 2.x API | +| --- | --- | +| `VideoInfo.resumed()` | `MediaObject()` | +| `VideoPlayerPluginDelegate.getVideoInfo()` | `MediaHeartbeat.trackSessionStart()` | +| `VideoPlayerPlugin.trackVideoLoad()` | | + +##### Video Resume (1.x) + +```js +this._videoInfo.resumed=true; + +VideoPlayer.prototype.getVideoInfo = function() { + this._videoInfo.playhead = vTime; + return this._videoInfo; +}; +``` + +##### Video Resume (2.x) + +```js +VideoAnalyticsProvider.prototype._onLoad = function() { + var contextData = {}; + var videoInfo = this._player.getVideoInfo(); + var mediaInfo = MediaHeartbeat.createMediaObject(videoInfo.playerName, videoInfo.id, videoInfo.length, videoInfo.streamType); + mediaInfo.setValue(MediaHeartbeat.MediaObjectKey.VideoResumed, true); + this._mediaHeartbeat.trackSessionStart(mediaInfo, contextData); +}; +``` + +For more information on tracking video with 2.x, see [Track Core Video Playback](https://experienceleague.adobe.com/docs/media-analytics/using/use-cases/track-av-playback/track-core-overview.html). + +--- + +## API Reference + +### Media SDK 2.x API References + +* [Android API Reference](https://adobe-marketing-cloud.github.io/media-sdks/reference/android/index.html) +* [iOS API Reference](https://adobe-marketing-cloud.github.io/media-sdks/reference/ios/index.html) +* [JS API Reference](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/index.html) +* [Chromecast API Reference](https://adobe-marketing-cloud.github.io/media-sdks/reference/chromecast/index.html) + +### Required Track* APIs + +| VHL 1.x | VHL 2.x | +|---|---| +| `videoPlayerPlugin.trackVideoLoad()` | N/A | +| `videoPlayerPlugin.trackSessionStart()` | [mediaHeartbeat.trackSessionStart(mediaObject, mediaCustomMetadata)](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackSessionStart) | +| `videoPlayerPlugin.trackPlay()` | [mediaHeartbeat.trackPlay()](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackPlay) | +| `videoPlayerPlugin.trackPause()` | [mediaHeartbeat.trackPause()](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackPause) | +| `videoPlayerPlugin.trackComplete()` | [mediaHeartbeat.trackComplete()](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackComplete) | +| `videoPlayerPlugin.trackVideoUnload()` | [mediaHeartbeat.trackSessionEnd()](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackSessionEnd) | +| `videoPlayerPlugin.trackApplicationError()` | N/A | +| `videoPlayerPlugin.trackVideoPlayerError()` | [mediaHeartbeat.trackError()](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackError) | + +All of the optional tracking APIs such as (Ads, Chapters, Bitrate change, Seeking, and Buffering) are now part of a single `trackEvent` API. The [trackEvent](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html#trackEvent) API receives a constant parameter that represents the type of event that it is intended to track: + +### Optional trackEvent APIs + +| VHL 1.x | VHL 2.x | +|---|---| +| Return a valid `AdBreakInfo` in `VideoPlayerPlugin.getAdBreakInfo()` | `trackEvent(Event.AdBreakStart)` | +| Return null in `VideoPlayerPlugin.getAdBreakInfo()` | `trackEvent(Event.AdBreakComplete)` | +| `playerPlugin.trackAdStart()` | `trackEvent(Event.AdStart, adObject, adCustomMetadata)` | +| `playerPlugin.trackAdComplete()` | `trackEvent(Event.AdComplete)` | +| Return null in `VideoPlayerPlugin.getAdInfo()` | `trackEvent(Event.AdSkip)` | +| `playerPlugin.trackChapterStart()` | `trackEvent(Event.ChapterStart, chapterObject, chapterCustomMetadata)` | +| `playerPlugin.trackChapterComplete()` | `trackEvent(Event.ChapterComplete)` | +| Return null in `VideoPlayerPlugin.getChapterInfo()` | `trackEvent(Event.ChapterSkip)` | +| `playerPlugin.trackSeekStart()` | `trackEvent(Event.SeekStart)` | +| `playerPlugin.trackSeekComplete()` | `trackEvent(Event.SeekComplete)` | +| `playerPlugin.trackBufferStart()` | `trackEvent(Event.BufferStart)` | +| `playerPlugin.trackBufferComplete()` | `trackEvent(Event.BufferComplete)` | +| `playerPlugin.trackBitrateChange()` | `trackEvent(Event.BitrateChange)` | +| `playerPlugin.trackTimedMetadata()` | `trackEvent(Event.TimedMetadataUpdate)` | diff --git a/docs/2.x/migration/2.x-to-2.x-tags.md b/docs/2.x/migration/2.x-to-2.x-tags.md new file mode 100644 index 0000000..3f1a70c --- /dev/null +++ b/docs/2.x/migration/2.x-to-2.x-tags.md @@ -0,0 +1,503 @@ +# Migrating from the standalone 2.x Media SDK to Adobe Experience Platform Tags (2.x tag extension) + +This documentation covers Media Analytics implementation differences between the standalone 2.x Media SDK and its corresponding Media Analytics Tags extension. + +Tags gives customers a simple way to deploy and manage all of the analytics, marketing, and advertising solutions necessary to power relevant customer experiences across web and mobile. Tags empowers anyone to build and maintain their own integrations with Tags. These integrations are called extensions. Extensions are available to Tags customers in an app-store experience, so they can quickly install, configure, and deploy their solutions. + +Adobe Media Analytics for Audio and Video is available as a Tags extension for both web and mobile: + +* [Web Tags Documentation](https://experienceleague.adobe.com/docs/experience-platform/tags/extensions/adobe/media-analytics/overview.html) +* [Mobile Tags Documentation](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/) + +--- + +## Android + +### Configuration + +#### Standalone Media SDK + +In the standalone Media SDK, you configure tracking in the app, and pass it to the SDK when you create the tracker. + +```java +MediaHeartbeatConfig config = new MediaHeartbeatConfig(); +config.trackingServer = "namespace.hb.omtrdc.net"; +config.channel = "sample-channel"; +config.appVersion = "v2.0.0"; +config.ovp = "video-provider"; +config.playerName = "native-player"; +config.ssl = true; +config.debugLogging = true; + +MediaHeartbeat tracker = new MediaHeartbeat(... , config); +``` + +#### Tags Extension + +1. In Experience Platform Tags, click the **Extensions** tab for your mobile property. +1. On the **Catalog** tab, locate the Adobe Media Analytics for Audio and Video extension, and click **Install**. +1. In the extension settings page, configure the tracking parameters. The Media extension will use the configured parameters for tracking. + +[Using Mobile Extensions](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/) + +### Tracker Creation + +#### Standalone Media SDK + +In the standalone Media SDK you manually create the `MediaHeartbeatConfig` object and configure the tracking parameters. Implement the delegate interface exposing `getQoSObject()` and `getCurrentPlaybackTime()` functions. Create a `MediaHeartbeat` instance for tracking. + +```java +MediaHeartbeatConfig config = new MediaHeartbeatConfig(); +config.trackingServer = "namespace.hb.omtrdc.net"; +config.channel = "sample-channel"; +config.appVersion = "v2.0"; +config.ovp = "video-provider"; +config.playerName = "native-player"; +config.ssl = true; +config.debugLogging = true; + +MediaHeartbeatDelegate delegate = new MediaHeartbeatDelegate() { + @Override + public MediaObject getQoSObject() { + // When called should return the latest qos values. + return MediaHeartbeat.createQoSObject(, + , + , + ); + } + + @Override + public Double getCurrentPlaybackTime() { + // When called should return the current player time in seconds. + return ; + } + + MediaHeartbeat tracker = new MediaHeartbeat(delegate, config); +} +``` + +#### Tags Extension + +[Media API reference - Create a Media Tracker](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#createtracker) + +Before you create the tracker, you should register the media extension and dependent extensions with the mobile core. + +```java +// Register the extension once during app launch +try { + // Media needs Identity and Analytics extension to function properly + Identity.registerExtension(); + Analytics.registerExtension(); + + // Initialize media extension. + Media.registerExtension(); + MobileCore.start(new AdobeCallback () { + @Override + public void call(Object o) { + // Launch mobile property to pick extension settings. + MobileCore.configureWithAppID("LAUNCH_MOBILE_PROPERTY"); + } + }); +} catch (InvalidInitException ex) { + ... +} +``` + +Once you register the media extension, create the tracker using the following API. The tracker automatically picks the configuration from the configured Tags property. + +```java +Media.createTracker(new AdobeCallback() { + @Override + public void call(MediaTracker tracker) { + // Use the instance for tracking media. + } +}); +``` + +### Updating Playhead and Quality of Experience values + +#### Standalone Media SDK + +In the standalone Media SDK, you pass a delegate object that implements the `MediaHeartbeatDelegate` interface during tracker creation. The implementation should return the latest QoE and playhead whenever the tracker calls the `getQoSObject()` and `getCurrentPlaybackTime()` interface methods. + +#### Tags Extension + +The implementation should update the current player playhead by calling the `updateCurrentPlayhead` method exposed by the tracker. For accurate tracking you should call this method at least once per second. + +[Media API reference - Update Current Player](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#updatecurrentplayhead) + +The implementation should update the QoE information by calling the `updateQoEObject` method exposed by the tracker. Call this method whenever there is a change in the quality metrics. + +[Media API reference - Update QoE Object](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#createqoeobject) + +### Passing standard media / ad metadata + +#### Standalone Media SDK + +* Standard Media Metadata: + + ```java + MediaObject mediaInfo = + MediaHeartbeat.createMediaObject("media-name", + "media-id", + 60D, + MediaHeartbeat.StreamType.VOD, + MediaHeartbeat.MediaType.Video); + + Map standardVideoMetadata = new HashMap(); + standardVideoMetadata.put(MediaHeartbeat.VideoMetadataKeys.EPISODE, "Sample Episode"); + standardVideoMetadata.put(MediaHeartbeat.VideoMetadataKeys.SHOW, "Sample Show"); + standardVideoMetadata.put(MediaHeartbeat.VideoMetadataKeys.SEASON, "Sample Season"); + mediaInfo.setValue(MediaHeartbeat.MediaObjectKey.StandardMediaMetadata, standardVideoMetadata); + + HashMap mediaMetadata = new HashMap(); + mediaMetadata.put("isUserLoggedIn", "false"); + mediaMetadata.put("tvStation", "Sample TV Station"); + tracker.trackSessionStart(mediaInfo, mediaMetadata); + ``` + +* Standard Ad Metadata: + + ```java + MediaObject adInfo = + MediaHeartbeat.createAdObject("ad-name", "ad-id", 1L, 15D); + + Map standardAdMetadata = new HashMap(); + standardAdMetadata.put(MediaHeartbeat.AdMetadataKeys.ADVERTISER, "Sample Advertiser"); + standardAdMetadata.put(MediaHeartbeat.AdMetadataKeys.CAMPAIGN_ID, "Sample Campaign"); + adInfo.setValue(MediaHeartbeat.MediaObjectKey.StandardAdMetadata, standardAdMetadata); + + HashMap adMetadata = new HashMap(); + adMetadata.put("affiliate", "Sample affiliate"); + tracker.trackEvent(MediaHeartbeat.Event.AdStart, adObject, adMetadata); + ``` + +#### Tags Extension + +* Standard Media Metadata: + + ```java + HashMap mediaObject = + Media.createMediaObject("media-name", "media-id", 60D, + MediaConstants.StreamType.VOD, Media.MediaType.Video); + + HashMap mediaMetadata = new HashMap(); + mediaMetadata.put(MediaConstants.VideoMetadataKeys.EPISODE, "Sample Episode"); + mediaMetadata.put(MediaConstants.VideoMetadataKeys.SHOW, "Sample Show"); + mediaMetadata.put("isUserLoggedIn", "false"); + mediaMetadata.put("tvStation", "Sample TV Station"); + + tracker.trackSessionStart(mediaInfo, mediaMetadata); + ``` + +* Standard Ad Metadata: + + ```java + HashMap adObject = + Media.createAdObject("ad-name", "ad-id", 1L, 15D); + HashMap adMetadata = new HashMap(); + adMetadata.put(MediaConstants.AdMetadataKeys.ADVERTISER, "Sample Advertiser"); + adMetadata.put(MediaConstants.AdMetadataKeys.CAMPAIGN_ID, "Sample Campaign"); + adMetadata.put("affiliate", "Sample affiliate"); + _tracker.trackEvent(Media.Event.AdStart, adObject, adMetadata); + ``` + +--- + +## iOS + +### Configuration + +#### Standalone Media SDK + +In the standalone Media SDK, you configure the tracking configuration in the app, and pass it to the SDK when you create the tracker. + +```objective-c +ADBMediaHeartbeatConfig *config = [[ADBMediaHeartbeatConfig alloc] init]; + +config.trackingServer = @"namespace.hb.omtrdc.net"; +config.channel = @"sample-channel"; +config.appVersion = @"v2.0.0"; +config.ovp = @"video-provider"; +config.playerName = @"native-player"; +config.ssl = YES; +config.debugLogging = YES; + +ADBMediaHeartbeat* tracker = + [[ADBMediaHeartbeat alloc] initWithDelegate:self config:config]; +``` + +#### Tags Extension + +1. In Experience Platform Tags, click the **Extensions** tab for your mobile property. +1. On the **Catalog** tab, locate the Adobe Media Analytics for Audio and Video extension, and click **Install**. +1. In the extension settings page, configure the tracking parameters. The Media extension will use the configured parameters for tracking. + +[Configure the Media Analytics extension](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/) + +### Tracker Creation + +#### Standalone Media SDK + +In the standalone Media SDK you manually create the `ADBMediaHeartbeatConfig` object and configure the tracking parameters. Implement the delegate interface exposing the `getQoSObject()` and `getCurrentPlaybackTime()` functions. + +Create a MediaHeartbeat instance for tracking: + +```objective-c +@interface PlayerDelegate : NSObject +@end + +@implementation PlayerDelegate { +} + +- (NSTimeInterval) getCurrentPlaybackTime { + // When called should return the current player time in seconds. + return playhead_; +} + +- (nonnull ADBMediaObject*) getQoSObject { + // When called should return the latest qos values. + return qosObject_; +} +@end + +ADBMediaHeartbeatConfig *config = [[ADBMediaHeartbeatConfig alloc] init]; +config.trackingServer = @"namespace.hb.omtrdc.net"; +config.channel = @"sample-channel"; +config.appVersion = @"app-version"; +config.ovp = @"video-provider"; +config.playerName = @"native-player"; +config.ssl = YES; +config.debugLogging = YES; +ADBMediaHeartbeatDelegate* delegate = [[PlayerDelegate alloc] init]; + +ADBMediaHeartbeat* tracker = + [[ADBMediaHeartbeat alloc] initWithDelegate:delegate config:config]; +``` + +#### Tags Extension + +[Media API reference - Create Media Tracker](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#createtracker) + +Before creating the tracker, register the media extension and dependent extensions with the mobile core. + +```objective-c +// Register the extension once during app launch +#import +#import +#import +#import + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [ACPCore setLogLevel:ACPMobileLogLevelDebug]; + [ACPCore configureWithAppId:@"your-launch-app-id"]; + [ACPMedia registerExtension]; + [ACPAnalytics registerExtension]; + [ACPIdentity registerExtension]; + [ACPCore start:nil]; + return YES; +} +``` + +Once the media extension is registered, tracker can be created using the following API. The tracker automatically picks the configuration from the configured Tags property. + +```objective-c +[ACPMedia createTracker:^(ACPMediaTracker * _Nullable mediaTracker) { + // Use the instance for tracking media. +}]; +``` + +### Updating Playhead and Quality of Experience values + +#### Standalone Media SDK + +In the standalone Media SDK, a delegate object that implements the `ADBMediaHeartbeatDelegate` protocol is passed during tracker creation. The implementation should return the latest QoE and playhead whenever the tracker calls the `getQoSObject()` and `getCurrentPlaybackTime()` interface methods. + +#### Tags Extension + +The implementation should update the current player playhead by calling the `updateCurrentPlayhead` method exposed by the tracker. For accurate tracking you should call this method at least once per second. + +[Media API reference - Update Current Playhead](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#updatecurrentplayhead) + +The implementation should update the QoE information by calling the `updateQoEObject` method exposed by the tracker. Call this method whenever there is a change in the quality metrics. + +[Media API reference - Update QoE Object](https://developer.adobe.com/client-sdks/documentation/adobe-media-analytics/api-reference/#createqoeobject) + +### Passing standard media / ad metadata + +#### Standalone Media SDK + +* Standard Media Metadata: + + ```objective-c + ADBMediaObject *mediaObject = + [ADBMediaHeartbeat createMediaObjectWithName:@"media-name" + mediaId:@"media-id" + length:60 + streamType:ADBMediaHeartbeatStreamTypeVod + mediaType:ADBMediaTypeVideo]; + + NSMutableDictionary *standardMetadata = [[NSMutableDictionary alloc] init]; + [standardMetadata setObject:@"Sample show" forKey:ADBVideoMetadataKeySHOW]; + [standardMetadata setObject:@"Sample season" forKey:ADBVideoMetadataKeySEASON]; + [mediaObject setValue:standardMetadata forKey:ADBMediaObjectKeyStandardMediaMetadata]; + + NSMutableDictionary *videoMetadata = [[NSMutableDictionary alloc] init]; + [videoMetadata setObject:@"false" forKey:@"isUserLoggedIn"]; + [videoMetadata setObject:@"Sample TV station" forKey:@"tvStation"]; + + [tracker trackSessionStart:mediaObject data:videoMetadata]; + ``` + +* Standard Ad Metadata: + + ```objective-c + ADBMediaObject* adObject = + [ADBMediaHeartbeat createAdObjectWithName:[adData objectForKey:@"name"] + adId:[adData objectForKey:@"id"] + position:[[adData objectForKey:@"position"] doubleValue] + length:[[adData objectForKey:@"length"] doubleValue]]; + + NSMutableDictionary *standardMetadata = [[NSMutableDictionary alloc] init]; + [standardMetadata setObject:@"Sample Advertiser" forKey:ADBAdMetadataKeyADVERTISER]; + [standardMetadata setObject:@"Sample Campaign" forKey:ADBAdMetadataKeyCAMPAIGN_ID]; + [adObject setValue:standardMetadata forKey:ADBMediaObjectKeyStandardAdMetadata]; + + NSMutableDictionary *adDictionary = [[NSMutableDictionary alloc] init]; + [adDictionary setObject:@"Sample affiliate" forKey:@"affiliate"]; + + [tracker trackEvent:ADBMediaHeartbeatEventAdStart + mediaObject:adObject + data:adDictionary]; + ``` + +#### Tags Extension + +* Standard Media Metadata: + + ```objective-c + NSDictionary *mediaObject = + [ACPMedia createMediaObjectWithName:@"media-name" + mediaId:@"media-id" + length:60 + streamType:ACPMediaStreamTypeVod + mediaType:ACPMediaTypeVideo]; + + NSMutableDictionary *mediaMetadata = [[NSMutableDictionary alloc] init]; + [mediaMetadata setObject:@"Sample show" forKey:ACPVideoMetadataKeyShow]; + [mediaMetadata setObject:@"Sample season" forKey:ACPVideoMetadataKeySeason]; + [mediaMetadata setObject:@"false" forKey:@"isUserLoggedIn"]; + [mediaMetadata setObject:@"Sample TV station" forKey:@"tvStation"]; + [_tracker trackSessionStart:mediaObject data:mediaMetadata]; + ``` + +* Standard Ad Metadata: + + ```objective-c + NSDictionary* adObject = + [ACPMedia createAdObjectWithName:@"ad-name" + adId:@"ad-id" + position:1 + length:15]; + + NSMutableDictionary* adMetadata = [[NSMutableDictionary alloc] init]; + [adMetadata setObject:@"Sample Advertiser" forKey:ACPAdMetadataKeyAdvertiser]; + [adMetadata setObject:@"Sample Campaign" forKey:ACPAdMetadataKeyCampaignId]; + [adMetadata setObject:@"Sample affiliate" forKey:@"affiliate"]; + + [tracker trackEvent:ACPMediaEventAdStart mediaObject:adObject data:adMetadata]; + ``` + +--- + +## Web (JavaScript) + +### Feature differences + +* **Tags**: Tags provides you with a UI that walks you through setting up, configuring, and deploying your web-based media tracking solutions. Tags improves upon Dynamic Tag Management (DTM). +* **Media SDK**: The Media SDK provides you with media tracking libraries designed for specific platforms (e.g.: Android, iOS, etc.). Adobe recommends Media SDK for tracking media usage in your Mobile Apps. + +### Configuration + +#### Standalone Media SDK + +In the standalone Media SDK, you configure the tracking configuration in the app and pass it to the SDK when you create the tracker. + +```javascript +//Media Heartbeat initialization +var mediaConfig = new MediaHeartbeatConfig(); +mediaConfig.trackingServer = "namespace.hb.omtrdc.net"; +mediaConfig.playerName = "html5-player"; +mediaConfig.channel = "sample-channel"; +mediaConfig.ovp = "video-provider"; +mediaConfig.appVersion = "v2.0.0" +mediaConfig.ssl = true; +mediaConfig.debugLogging = true; +``` + +In addition to the `MediaHeartbeat` configuration, the page must configure and pass the `AppMeasurement` instance and `VisitorAPI` instance for media tracking in order to work properly. + +#### Tags Extension + +1. In Experience Platform Tags, click the **Extensions** tab for your web property. +1. On the **Catalog** tab, locate the Adobe Media Analytics for Audio and Video extension, and click **Install**. +1. In the extension settings page, configure the tracking parameters. The Media extension will use the configured parameters for tracking. + +[Tags User Guide - Install & configure the media extension](https://experienceleague.adobe.com/docs/experience-platform/tags/extensions/adobe/media-analytics/overview.html#install-and-configure-the-ma-extension) + +### Tracker creation differences + +#### Media SDK + +1. Add the Media Analytics library to your development project. +1. Create a config object (`MediaHeartbeatConfig`). +1. Implement the delegate protocol, exposing the `getQoSObject()` and `getCurrentPlaybackTime()` functions. +1. Create a Media Heartbeat instance (`MediaHeartbeat`). + +```javascript +// Media Heartbeat initialization +var mediaConfig = new MediaHeartbeatConfig(); +// Configuration settings +mediaConfig.trackingServer = Configuration.HEARTBEAT.TRACKING_SERVER; +// Implement Media Delegate (Quality of Service and Playhead) +var mediaDelegate = new MediaHeartbeatDelegate(); +mediaDelegate.getQoSObject = function() { + return MediaHeartbeat.createQoSObject(, , , ); +} +// Create your tracker +this.mediaHeartbeat = new MediaHeartbeat(mediaDelegate, mediaConfig, appMeasurement); +``` + +#### Tags + +Tags offers two approaches to creating the tracking infrastructure. Both approaches use the Media Analytics Tags Extension: + +1. Use the media tracking APIs from a web page. + + In this scenario, the Media Analytics Extension exports the media tracking APIs to a configured variable in the global window object: + + ```javascript + window["CONFIGURED_VARIABLE_NAME"].MediaHeartbeat.getInstance + ``` + +1. Use the media tracking APIs from another Tags extension. + + In this scenario, you use the media tracking APIs exposed by the `get-instance` and `media-heartbeat` Shared Modules. + + > Shared Modules are not available for use in web pages. You can only use Shared Modules from another extension. + + Create a `MediaHeartbeat` instance using the `get-instance` Shared Module. Pass a delegate object to `get-instance` that exposes `getQoSObject()` and `getCurrentPlaybackTime()` functions. + + ```javascript + var getMediaHeartbeatInstance = + turbine.getSharedModule('adobe-video-analytics', 'get-instance'); + ``` + + Access `MediaHeartbeat` constants via the `media-heartbeat` Shared Module. + +### Related Documentation + +* [Set up JavaScript 2.x](../2.x/javascript-setup.md) +* [Media SDK JS API](https://adobe-marketing-cloud.github.io/media-sdks/reference/javascript/MediaHeartbeat.html) +* [Tags overview](https://experienceleague.adobe.com/docs/experience-platform/tags/home.html) +* [Media Analytics Extension](https://experienceleague.adobe.com/docs/experience-platform/tags/extensions/adobe/media-analytics/overview.html) diff --git a/docs/2.x/validation/heartbeat-params.md b/docs/2.x/validation/heartbeat-params.md new file mode 100644 index 0000000..338ec1a --- /dev/null +++ b/docs/2.x/validation/heartbeat-params.md @@ -0,0 +1,70 @@ +# Media Analytics (heartbeats) parameter descriptions + +List of Media Analytics parameters that Adobe collects and processes on the Media Analytics (heartbeats) server: + +## All Events + +| Name | Data Source | Description | +| --- | --- | --- | +| `s:event:type` | Media SDK | (Required) The type of the event being tracked. Event types: `start`, `complete`, `chapter_start`, `chapter_complete`, `buffer`, `pause`, `resume`, `bitrate_change`, `aa_start`, `stall`, `end` | +| `l:event:prev_ts` | Media SDK | (Required) The timestamp of the last event of the same type in this session. The value is -1. | +| `l:event:ts` | Media SDK | (Required) The timestamp of the event. | +| `l:event:duration` | Media SDK | (Required) This value is set internally (in milliseconds) by the Media SDK, not by the player. It is used to compute the time spent metrics on the backend. E.g.: `a.media.totalTimePlayed` is computed as a sum of the duration for all of the Play (type=play) heartbeats that are generated. Note: This parameter is set to 0 for certain events because they are "state change events" (e.g., type=complete, type=chapter_complete, or type=bitrate_change.) | +| `l:event:playhead` | VideoInfo | (Required) The playhead was inside the currently active asset (main or ad), when the event was recorded. | +| `s:event:sid` | Media SDK | (Required) The session ID (a randomly generated string). All events in a certain session (video + ads) should be the same. | +| `l:asset:duration` / `l:asset:length` | VideoInfo | (Required) The video asset length of the main asset. | +| `s:asset:publisher` | MediaHeartbeatConfig | (Required) The publisher of the asset. | +| `s:asset:video_id` | VideoInfo | (Required) An ID uniquely identifying the video in the publisher's catalog. | +| `s:asset:type` | Media SDK | (Required) The asset type (main or ad). | +| `s:stream:type` | VideoInfo | (Required) The stream type. Can be one of the following: `live`, `vod`, `linear` | +| `s:user:id` | Config object for mobile, app measurement VisitorID | (Optional) User's specifically set Visitor ID. | +| `s:user:aid` | IMS Org | (Optional) The user's Analytics Visitor ID value. | +| `s:user:mid` | IMS Org | (Required) The user's ECID. | +| `s:cuser:customer_user_ids_x` | MediaHeartbeatConfig | (Optional) All customer user IDs set on Audience Manager. | +| `l:aam:loc_hint` | MediaHeartbeatConfig | (Required) AAM data sent on each payload after aa_start | +| `s:aam:blob` | MediaHeartbeatConfig | (Required) AAM data sent on each payload after aa_start | +| `s:sc:rsid` | Report Suite ID (or IDs) | (Required) Adobe Analytics RSID where reports should be sent. | +| `s:sc:tracking_server` | MediaHeartbeatConfig | (Required) Adobe Analytics tracking server. | +| `h:sc:ssl` | MediaHeartbeatConfig | (Required) Whether the traffic is over HTTPS (if set to 1) or over HTTP (is set to 0). | +| `s:sp:ovp` | MediaHeartbeatConfig | (Optional) Set to "primetime" for Primetime players, or the actual OVP for other players. | +| `s:sp:sdk` | MediaHeartbeatConfig | (Required) The OVP version string. | +| `s:sp:player_name` | VideoInfo | (Required) Video player name (the actual player software, used to identify the player). | +| `s:sp:channel` | MediaHeartbeatConfig | (Optional) The channel where the user is watching the content. For a mobile app, the app name. For a website, the domain name. | +| `s:sp:hb_version` | Media SDK | (Required) The version number of the Media SDK library issuing the call. | +| `l:stream:bitrate` | QoSInfo | (Required) The current value of the stream bitrate (in bps). | + +## Error Events + +| Name | Data Source | Description | +| --- | --- | --- | +| `s:event:source` | Media SDK | (Required) The source of the error, either player-internal, or the application-level. | +| `s:event:id` | Media SDK | (Required) Error ID, uniquely identifies the error. | + +## Ad Events + +| Name | Data Source | Description | +| --- | --- | --- | +| `s:asset:ad_id` | AdInfo | (Required) The name of the ad. | +| `s:asset:ad_sid` | Media SDK | (Required) A unique identifier generated by the Media SDK, appended to all ad-related pings. | +| `s:asset:pod_id` | Media SDK | (Required) Pod ID inside the video. This value is computed automatically based on the following formula: `MD5(video_id) + "_" + [pod index]` | +| `s:asset:pod_position` | AdBreakInfo | (Required) Index of the ad inside the pod (the first ad has index 0, the second ad has index 1, etc.). | +| `s:asset:resolver` | AdBreakInfo | (Required) The ad resolver. | +| `s:meta:custom_ad_metadata.x` | MediaHeartbeat | (Optional) The custom ad metadata. | + +## Chapter Events + +| Name | Data Source | Description | +| --- | --- | --- | +| `s:stream:chapter_sid` | Media SDK | (Required) The unique identifier associated to the playback instance of the chapter. Note: A chapter can be played multiple times due to seek-back operations performed by the user. | +| `s:stream:chapter_name` | ChapterInfo | (Optional) The chapter's friendly (i.e., human readable) name. | +| `s:stream:chapter_id` | Media SDK | (Required) The unique ID of the chapter. This value is computed automatically based on the following formula: `MD5(video_id) + "_" + chapter_pos` | +| `l:stream:chapter_pos` | ChapterInfo | (Required) The chapter's index in the list of chapters (starting with 1). | +| `l:stream:chapter_offset` | ChapterInfo | (Required) The chapter's offset (expressed in seconds) inside the main content, excluding ads. | +| `l:stream:chapter_length` | ChapterInfo | (Required) The chapter's duration (expressed in seconds). | +| `s:meta:custom_chapter_metadata.x` | ChapterInfo | (Optional) Custom chapter metadata. | + +## Session End Event + +| Name | Data Source | Description | +| --- | --- | --- | +| `s:event:type=end` | Media SDK | (Required) The `end` `close` | diff --git a/docs/2.x/validation/overview.md b/docs/2.x/validation/overview.md new file mode 100644 index 0000000..7bbfae8 --- /dev/null +++ b/docs/2.x/validation/overview.md @@ -0,0 +1,6 @@ +# Validation Overview + +Validation includes a list of required test cases that customers must run through (using Adobe Debug), to submit logs validating a proper implementation. There are expected results for each event and metadata parameter. + +* [Test 1: Standard playback](./test1-standard-playback.md) +* [Test 2: Media interruption](./test2-media-interrupt.md) diff --git a/docs/2.x/validation/test-call-details.md b/docs/2.x/validation/test-call-details.md new file mode 100644 index 0000000..2aadb79 --- /dev/null +++ b/docs/2.x/validation/test-call-details.md @@ -0,0 +1,291 @@ +# Test call details + +## Start the media player + +### Adobe Analytics (AppMeasurement) Start call + +| Parameter | Value (sample) | +|---|---| +| `pev2` | ms_s | +| `a.media.friendlyName` | Episode Title | +| `a.media.name` | 123456 | +| `a.media.length` | 120 | +| `a.media.playerName` | HTML5 | +| `a.media.view` | true | +| `a.contentType` | vod | +| `custom.[value]` | Custom metadata fields | +| `a.media.[value]` | Standard metadata fields | + +Notes: + +* Additional context data variables should be present and contain metadata. See metadata details below. +* Length for linear streams should be set to the best estimate for the current show. + +### Standard metadata in Adobe Analytics (AppMeasurement) Start call + +| Parameter | Value (sample) | +|---|---| +| `a.media.show` | Show Title | +| `a.media.season` | 6 | +| `a.media.episode` | Episode Title | +| `a.media.asset_id` | 123456 | +| `a.media.genre` | comedy | +| `a.media.first_air_date` | YYYY-07-04 | +| `a.media.rating` | TV-14 | +| `a.media.originator` | production house | +| `a.media.network` | network | +| `a.media.ad_load` | 1 | +| `a.media.mvpd` | mvpd | +| `a.media.authorized` | unlocked | +| `a.media.feed` | no feed | +| `a.media.stream_format` | 0 | + +### Custom metadata in Adobe Analytics (AppMeasurement) Start call + +| Parameter | Value (sample) | +|---|---| +| `custom.metadataA` | value | +| `custom.metadataB` | value | + +### Media Analytics (heartbeats) Start call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | start | +| `l:event:playhead` | 0 | +| `l:event:duration` | 4 | +| `s:asset:name` | Episode Title | +| `s:asset:video_id` | 123456 | +| `l:asset:length` | 120 | +| `s:stream:type` | vod | +| `s:asset:type` | main | +| `s:meta:custom.[value]` | Custom metadata fields | +| `s:meta:a.media.[value]` | Standard metadata fields | + +Notes: + +* Additional context data variables should be present and contain metadata. See metadata details below. +* Playhead position for linear streams on video start should be set to the seconds elapsed since the start of the current show, not 0. + +### Standard metadata in Media Analytics (heartbeats) Start call + +| Parameter | Value (sample) | +|---|---| +| `s:meta:a.media.show` | Show | +| `s:meta:a.media.season` | 6 | +| `s:meta:a.media.episode` | Episode Title | +| `s:meta:a.media.asset_id` | 123456 | +| `s:meta:a.media.genre` | comedy | +| `s:meta:a.media.first_air_date` | 2018-07-04 | +| `s:meta:a.media.rating` | TV-14 | +| `s:meta:a.media.originator` | production house | +| `s:meta:a.media.network` | network | +| `s:meta:a.media.ad_load` | 1 | +| `s:meta:a.media.mvpd` | mvpd | +| `s:meta:a.media.authorized` | unlocked | +| `s:meta:a.media.feed` | no feed | +| `s:meta:a.media.stream_format` | 0 | + +### Custom metadata in Media Analytics (heartbeats) Start call + +| Parameter | Value (sample) | +|---|---| +| `s:meta:custom.metadata` | value | +| `s:meta:custom.metadata` | value | + +### Media Analytics (heartbeats) Adobe Analytics Start call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | aa_start | +| `l:event:playhead` | 0 | +| `l:event:duration` | 4 | +| `s:asset:name` | Episode Title | +| `s:asset:video_id` | 123456 | +| `l:asset:length` | 120 | +| `s:stream:type` | vod | +| `s:asset:type` | main | + +Notes: + +* This call indicates that the Media SDK has requested that an Adobe Analytics `pev2=ms_s` call be sent to the Adobe Analytics (AppMeasurement) server. +* This call does not contain custom metadata. + +## View ad playback + +### Adobe Analytics (AppMeasurement) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `pev2` | msa_s | +| `a.media.name` | 123456 | +| `a.media.ad.name` | 9378 | +| `a.media.ad.friendlyName` | Video_VPAID_DFA | +| `a.media.ad.podFriendlyName` | preroll | +| `a.media.ad.length` | 15 | +| `a.media.ad.playerName` | HTML5 | +| `a.media.ad.pod` | c27aaf3ff8224bb6b9ebfe1b2e79073d_1 | +| `a.media.ad.podPosition` | 1 | +| `a.media.ad.podSecond` | 0.0 | +| `a.media.ad.view` | True | +| `custom.[value]` | Metadata fields | +| `a.media.[value]` | Standard metadata fields | + +Notes: + +* Additional context data variables should be present and contain metadata. See metadata details below. +* Ad length may be set to -1 if not available on ad start. + +### Standard metadata in Adobe Analytics (AppMeasurement) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `a.media.show` | Show Title | +| `a.media.season` | 6 | +| `a.media.episode` | Episode Title | +| `a.media.asset_id` | 123456 | +| `a.media.genre` | comedy | +| `a.media.first_air_date` | 2016-07-04 | +| `a.media.rating` | TV-14 | +| `a.media.originator` | production house | +| `a.media.network` | network | +| `a.media.ad_load` | 1 | +| `a.media.mvpd` | mvpd | +| `a.media.authorized` | unlocked | +| `a.media.feed` | no feed | +| `a.media.stream_format` | 0 | + +### Custom metadata in Adobe Analytics (AppMeasurement) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `custom.metadata` | value | +| `custom.metadata` | value | + +### Media Analytics (heartbeats) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | start | +| `l:event:playhead` | 0 | +| `l:event:duration` | 4 | +| `s:asset:ad_id` | 9378 | +| `l:asset:length` | 120 | +| `s:stream:type` | vod | +| `s:asset:type` | ad | +| `s:meta:custom.[value]` | Custom metadata fields | +| `s:meta:a.media.[value]` | Standard metadata fields | + +Notes: + +* Additional context data variables should be present and contain metadata. See metadata details below. +* Ad length may be set to -1 if not available on ad start. + +### Standard metadata in Media Analytics (heartbeats) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `s:meta:a.media.show` | Show | +| `s:meta:a.media.season` | 6 | +| `s:meta:a.media.episode` | Episode Title | +| `s:meta:a.media.asset_id` | 123456 | +| `s:meta:a.media.genre` | comedy | +| `s:meta:a.media.first_air_date` | YYYY-07-04 | +| `s:meta:a.media.rating` | TV-14 | +| `s:meta:a.media.originator` | production house | +| `s:meta:a.media.network` | network | +| `s:meta:a.media.ad_load` | 1 | +| `s:meta:a.media.mvpd` | mvpd | +| `s:meta:a.media.authorized` | unlocked | +| `s:meta:a.media.feed` | no feed | +| `s:meta:a.media.stream_format` | 0 | + +### Custom metadata in Media Analytics (heartbeats) Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `s:meta:custom.metadata` | value | +| `s:meta:custom.metadata` | value | + +### Media Analytics (heartbeats) Adobe Analytics Ad Start call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | aa_ad_start | +| `l:event:playhead` | 0 | +| `l:event:duration` | 0 | +| `s:asset:ad_id` | 9378 | +| `l:asset:ad_length` | 15 | +| `s:stream:type` | vod | +| `s:asset:type` | ad | + +### Media Analytics (heartbeats) Ad Play call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | play | +| `l:event:playhead` | 15 | +| `l:event:duration` | 0 | +| `s:asset:ad_id` | 9378 | +| `l:asset:ad_length` | 15 | +| `s:stream:type` | vod | +| `s:asset:type` | ad | + +### Media Analytics (heartbeats) Ad Pause call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | pause | +| `l:event:playhead` | 15 | +| `l:event:duration` | 0 | +| `s:asset:ad_id` | 9378 | +| `l:asset:ad_length` | 15 | +| `s:stream:type` | vod | +| `s:asset:type` | ad | + +### Media Analytics (heartbeats) Adobe Analytics Ad Complete call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | complete | +| `l:event:playhead` | 15 | +| `l:event:duration` | 0 | +| `s:asset:ad_id` | 9378 | +| `l:asset:ad_length` | 15 | +| `s:stream:type` | vod | +| `s:asset:type` | ad | + +## Play main content + +### Media Analytics (heartbeats) Play call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | play | +| `l:event:playhead` | 29 | +| `l:event:duration` | 10189 | +| `s:asset:name` | Episode Title | +| `s:asset:video_id` | 123456 | +| `l:asset:length` | 120 | +| `s:stream:type` | vod | +| `s:asset:type` | main | + +Notes: + +* The playhead position should increment by 10 seconds with every play call. +* The `l:event:duration` value represents the number of milliseconds since the last tracking call and should be roughly the same value on each 10 second call. + +## Pause main content + +### Media Analytics (heartbeats) Pause call + +| Parameter | Value (sample) | +|---|---| +| `s:event:type` | pause | +| `l:event:playhead` | 29 | +| `l:event:duration` | 10189 | +| `s:asset:name` | Episode Title | +| `s:asset:video_id` | 123456 | +| `l:asset:length` | 120 | +| `s:stream:type` | vod | +| `s:asset:type` | main | diff --git a/docs/2.x/validation/test1-standard-playback.md b/docs/2.x/validation/test1-standard-playback.md new file mode 100644 index 0000000..46b3493 --- /dev/null +++ b/docs/2.x/validation/test1-standard-playback.md @@ -0,0 +1,127 @@ +# Test 1: Standard playback + +This test case validates general playback and sequencing. + +Media Analytics implementations include two types of tracking calls: +* **Calls made directly to your Adobe Analytics (AppMeasurement) server**: These calls occur on "Media Start" and "Ad Start" events. +* **Calls made to the Media Analytics (heartbeats) server**: These include in-band and out-of-band calls: + * In-band: The SDK sends timed play calls or "pings" at 10-second intervals during content playback, and at one-second intervals during ads. + * Out-of-band: These calls can happen at any point, and include Pause, Buffering, errors, content complete, ad complete, etc. + +> Media tracking behaves the same across all platforms. + +## Test procedure + +Complete and record the following actions (in order): + +1. **Load the page or app** + + **Tracking Servers** (For all website and mobile apps): + + * **Adobe Analytics (AppMeasurement) server**: An RDC tracking server or CNAME that resolves to an RDC tracking server is required for the Experience Cloud Visitor ID service. The Adobe Analytics tracking server should end in "`.sc.omtrdc.net`" or be a CNAME. + + * **Media Analytics (Heartbeats) server**: This server always has the format "`[namespace].hb.omtrdc.net`", where `[namespace]` specifies your company name. This name is provided by Adobe. + + You need to validate certain key variables that are universal across all tracking calls: + + **Visitor ID (`mid`)**: The `mid` variable is used to capture the value set in the AMCV cookie. The `mid` variable is the primary identification value for both websites and mobile apps, and also indicates that the Experience Cloud Visitor ID service is set up properly. It is found in both Adobe Analytics (AppMeasurement) and Media Analytics (heartbeats) calls. + + * **Adobe Analytics Start call** + + | Parameter | Value (sample) | + |---|---| + | `pev2` | ms_s | + | `mid` | 30250035503789876473484580554595324209 | + + * **Website Page call** + + | Parameter | Value (sample) | + |---|---| + | `mid` | 30250035503789876473484580554595324209 | + + * **Lifecycle call** + + | Parameter | Value (sample) | + |---|---| + | `pev2` | ADBINTERNAL:Lifecycle | + | `mid` | 30250035503789876473484580554595324209 | + + * **Media Analytics Start call** + + | Parameter | Value (sample) | + |---|---| + | `s:event:type` | start | + + > On Media Analytics Start calls (`s:event:type=start`) the `mid` values may not be present. This is OK. They may not appear until the Media Analytics Play calls (`s:event:type=play`). + + * **Media Analytics Play call** + + | Parameter | Value (sample) | + |---|---| + | `s:event:type` | play | + | `s:user:mid` | 30250035503789876473484580554595324209 | + +1. **Start the media player** + + When the media player starts, the Media SDK sends the key calls to the two servers in the following order: + + 1. Adobe Analytics server — Start call + 1. Media Analytics server — Start call + 1. Media Analytics server — "Adobe Analytics Start call requested" + + The first two calls above contain additional metadata and variables. For call parameters and metadata, see [Test call details.](./test-call-details.md#start-the-media-player) + + The third call above tells the Media Analytics server that the Media SDK requested that the Adobe Analytics Start call (`pev2=ms_s`) be sent to the Adobe Analytics server. + +1. **View ad break if available** + + * **Ad Start** + + When the ad starts, the following key calls are sent in the following order: + + 1. Adobe Analytics server — Ad Start call + 1. Media Analytics server — Ad Start call + 1. Media Analytics server — "Adobe Analytics Ad Start call requested" + + The first two calls contain additional metadata and variables. For call parameters and metadata, see [Test call details.](./test-call-details.md#view-ad-playback) + + The third call tells the Media Analytics server that the Media SDK requested that the Adobe Analytics Ad Start call (`pev2=msa_s`) be sent to the Adobe Analytics server. + + * **Ad Play** + + During ad playback, the Media Analytics SDK sends play events of type "ad" to the Media Analytics server every second. + + * **Ad Complete** + + At the 100% point of an ad, a Media Analytics Complete call should be sent. + +1. **Pause ad playback for 30 seconds, if available.** **Ad Pause** + + During Ad Pause, Media Analytics heartbeat or "ping" calls are sent by the SDK to the Media Analytics server every second. + + > The playhead value should remain constant during the pause. + + For call parameters and metadata, see [Test call details.](./test-call-details.md#view-ad-playback) + +1. **Play main content for 10 seconds uninterrupted.** **Content Play** + + During main content playback, the Media SDK sends heartbeats (Play calls) to the Media Analytics server every 10 seconds. + + Notes: + + * The playhead position should increment by 10 with every Play call. + * The `l:event:duration` value represents the number of milliseconds since the last tracking call and should be roughly the same value on each 10 second call. + + For call parameters and metadata, see [Test call details.](./test-call-details.md#play-main-content) + +1. **Pause during playback for at least 30 seconds.** On pause of the media player, pause event calls will be sent by the SDK to the Media Analytics server every 10 seconds. After pause ends, the play events should resume. + + For call parameters and metadata, see [Test call details.](./test-call-details.md#pause-main-content) + +1. **Seek/scrub media.** On scrubbing of media playhead, no special tracking calls are sent, however, when media playback resumes after scrubbing, the playhead value should reflect the new position within the main content. + +1. **Replay media (VOD only).** When media is replayed, a new set of Media Start calls should be sent (as if it were a fresh start). + +1. **View next media in playlist.** On Media Start of the next media in a playlist, a new set of Media Start calls should be sent. + +1. **Switch media or stream.** When switching live streams, a Media Analytics complete call for the first stream should not be sent. The Media Start calls and Play calls should begin with the new show and stream name, and with the correct playhead and duration values for the new show. diff --git a/docs/2.x/validation/test2-media-interrupt.md b/docs/2.x/validation/test2-media-interrupt.md new file mode 100644 index 0000000..7a88070 --- /dev/null +++ b/docs/2.x/validation/test2-media-interrupt.md @@ -0,0 +1,45 @@ +# Test 2: Media Interruption + +This test case validates mobile interruption behavior. + +## Test procedure + +You must complete and record these tasks in following order: + +1. **Start the media player** + + When the media player starts, the following calls are sent in the following order: + + 1. Adobe Analytics (AppMeasurement) Start + 1. Media Analytics (heartbeats) Start + 1. Media Analytics (heartbeats) Adobe Analytics Start call requested + + The first two calls above contain additional metadata and variables. For call parameters and metadata, see [Test call details.](./test-call-details.md#start-the-media-player) + + The third call above tells the Media Analytics server that the Media SDK requested that the Adobe Analytics Start call (`pev2=ms_s`) be sent to the Adobe Analytics server. + +1. **Play main content for at least 5 minutes uninterrupted** + + **Content Play** + + During content playback, the Media SDK sends play calls (heartbeats) to the Media Analytics server every ten seconds. + + For call parameters and metadata, see [Test call details](./test-call-details.md#play-main-content). + + Also see your platform's [Track Ads](https://experienceleague.adobe.com/docs/media-analytics/using/use-cases/track-ads/track-ads-overview.html) instructions for additional information about these Ad calls. + +1. **Move app or browser to the background** + + While the app runs in the background, only `main:pause` calls should be sent to the Media Analytics server, starting with VHL version 1.6.6 and later. + +1. **Bring app or browser back to foreground** + + On returning from background, content playback should resume. + +1. **Play main content media for at least 5 minutes uninterrupted** + + For call parameters and metadata, see [Test Call Details](./test-call-details.md#play-main-content). + +1. **Close media player** + + No additional tracking calls should fire after the media player is closed. diff --git a/sdks/android/README.md b/sdks/android/README.md index d571787..9329cdc 100644 --- a/sdks/android/README.md +++ b/sdks/android/README.md @@ -3,4 +3,6 @@ MediaSDK-android Media SDK for Android -Starting with v2.2.0 release, the Video Heartbeat Library (VHL) SDKs are renamed to Media SDKs. The Media 2.2.0 SDK is fully backwards compatible with the VHL 2.x SDK series. The name change does not represent a functional break, simply a change in naming convention. All the existing public APIs with v2.x series has no impact due to SDK name change. +Starting with v2.2.0 release, the Video Heartbeat Library (VHL) SDKs are renamed to Media SDKs. The Media 2.2.0 SDK is fully backwards compatible with the VHL 2.x SDK series. The name change does not represent a functional break, simply a change in naming convention. All the existing public APIs with v2.x series has no impact due to SDK name change. + +> **End of Support:** The Media SDK 2.x for Android reached end of support on August 31, 2021. See the [setup guide](../../docs/2.x/android-setup.md) for archived documentation, or migrate to the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/home/). diff --git a/sdks/android/ReleaseNotes.md b/sdks/android/ReleaseNotes.md index 09672db..c185d3b 100644 --- a/sdks/android/ReleaseNotes.md +++ b/sdks/android/ReleaseNotes.md @@ -11,12 +11,6 @@ Lighter, Simpler implementation. - Error state recovery. Media SDK 2.x keeps track of the current state of the playback. By having internal state logic, Media SDK 2.x can ignore wrong API calls. - Clear difference between optional and required media tracking APIs. Optional media tracking features such as chapter tracking, ad tracking, bitrate change, etc. are now tracked through a single media tracking API: trackEvent. -For full documentation, please visit: -https://docs.adobe.com/content/help/en/media-analytics/using/sdk-implement/setup/set-up-android.html - -For full API documentation, please visit: -https://adobe-marketing-cloud.github.io/media-sdks/reference/android/index.html - ## 2.2.4 (Oct 11, 2019) - Bug fixes to improve stability and performance. diff --git a/sdks/chromecast/ReleaseNotes.md b/sdks/chromecast/ReleaseNotes.md index 83db405..67a21ca 100644 --- a/sdks/chromecast/ReleaseNotes.md +++ b/sdks/chromecast/ReleaseNotes.md @@ -3,7 +3,7 @@ Included are notes from the latest major revision to current. For full documentation please visit: -https://docs.adobe.com/content/help/en/media-analytics/using/sdk-implement/setup/set-up-chromecast.html +https://experienceleague.adobe.com/docs/media-analytics/using/implementation/media-sdk/setup/set-up-chromecast.html ## 3.0.3 (June 1, 2021) What's new : diff --git a/sdks/iOS/README.md b/sdks/iOS/README.md index 48f7f36..ef83470 100644 --- a/sdks/iOS/README.md +++ b/sdks/iOS/README.md @@ -1,4 +1,6 @@ MediaSDK-iOS Media SDK for iOS -Starting with v2.2.0 release, the Video Heartbeat Library (VHL) SDKs are renamed to Media SDKs. The Media 2.2.0 SDK is fully backwards compatible with the VHL 2.x SDK series. The name change does not represent a functional break, simply a change in naming convention. All the existing public APIs with v2.x series has no impact due to SDK name change. \ No newline at end of file +Starting with v2.2.0 release, the Video Heartbeat Library (VHL) SDKs are renamed to Media SDKs. The Media 2.2.0 SDK is fully backwards compatible with the VHL 2.x SDK series. The name change does not represent a functional break, simply a change in naming convention. All the existing public APIs with v2.x series has no impact due to SDK name change. + +> **End of Support:** The Media SDK 2.x for iOS reached end of support on August 31, 2021. See the [setup guide](../../docs/2.x/ios-setup.md) for archived documentation, or migrate to the [Adobe Experience Platform Mobile SDK](https://developer.adobe.com/client-sdks/home/). \ No newline at end of file diff --git a/sdks/iOS/ReleaseNotes.md b/sdks/iOS/ReleaseNotes.md index b40e14f..78722e8 100644 --- a/sdks/iOS/ReleaseNotes.md +++ b/sdks/iOS/ReleaseNotes.md @@ -9,9 +9,6 @@ Lighter, Simpler implementation. - Error state recovery. Media SDK 2.x keeps track of the current state of the playback. By having internal state logic, Media SDK 2.x can ignore wrong API calls. - Clear difference between optional and required media tracking APIs. Optional media tracking features such as chapter tracking, ad tracking, bitrate change, etc. are now tracked through a single media tracking API: trackEvent:. -For full documentation please visit: -https://marketing.adobe.com/resources/help/en_US/sc/appmeasurement/hbvideo/sdk-implement.html - ## 2.3.0 (December 18, 2020) - General - The SDK is now distributed using XCFrameworks in order to support hardware with the new Apple M1 architecture while maintaining support for existing Intel architecture. - **IMPORTANT**: Upgrading to MediaSDK XCFrameworks requires Xcode 12.0 or newer @@ -55,7 +52,7 @@ https://marketing.adobe.com/resources/help/en_US/sc/appmeasurement/hbvideo/sdk-i - Bug fixes to improve stability and SDK performance. ## 2.0.1 (11 Oct, 2016) -What’s new : +What's new : - Bug fixing to improve stability and performance. ## 2.0.0 (July 15, 2016) diff --git a/sdks/js/2.x/ReleaseNotes.md b/sdks/js/2.x/ReleaseNotes.md index a32f453..81ab386 100644 --- a/sdks/js/2.x/ReleaseNotes.md +++ b/sdks/js/2.x/ReleaseNotes.md @@ -6,18 +6,15 @@ What's new in 2.x: Lighter, Simpler implementation. - - Streamlined implementation and configuration. With VHL 2.x, all the configuration and video tracking API calls are centralized through a single class: MediaHeartbeat. - - Error state recovery. VHL 2.x keeps track of the current state of the playback. By having internal state logic, VHL 2.x can ignore wrong API calls. - - Clear difference between optional and required video tracking APIs. Optional video tracking features such as chapter tracking, ad tracking, bitrate change, etc. are now tracked through a single video tracking API: trackEvent. - -For full documentation please visit: -https://docs.adobe.com/content/help/en/media-analytics/using/sdk-implement/setup/set-up-js.html + - Streamlined implementation and configuration. With VHL 2.x, all the configuration and video tracking API calls are centralized through a single class: MediaHeartbeat. + - Error state recovery. VHL 2.x keeps track of the current state of the playback. By having internal state logic, VHL 2.x can ignore wrong API calls. + - Clear difference between optional and required video tracking APIs. Optional video tracking features such as chapter tracking, ad tracking, bitrate change, etc. are now tracked through a single video tracking API: trackEvent. ## 2.2.2 (June 24, 2020) - Bug fixes to improve stability and SDK performance. ## 2.2.1 (October 11, 2019) -- Added support for [Adobe Opt In service](https://docs.adobe.com/content/help/en/id-service/using/implementation-guides/opt-in-service/getting-started.html). +- Added support for [Adobe Opt In service](https://experienceleague.adobe.com/docs/id-service/using/implementation/opt-in-service/getting-started.html). - Bug fixes to improve stability and SDK performance. ## 2.2.0 (February 12, 2019) diff --git a/sdks/js/3.x/docs/MigrationGuide.md b/sdks/js/3.x/docs/MigrationGuide.md index 469ac44..3951241 100644 --- a/sdks/js/3.x/docs/MigrationGuide.md +++ b/sdks/js/3.x/docs/MigrationGuide.md @@ -250,4 +250,4 @@ metadata["customKey2"] = "custom value"; mediaTracker.trackEvent(Media.Event.AdStart, adObject, metadata); -``` \ No newline at end of file +``` diff --git a/sdks/roku/ReleaseNotes.md b/sdks/roku/ReleaseNotes.md index 65b4612..c5c5058 100644 --- a/sdks/roku/ReleaseNotes.md +++ b/sdks/roku/ReleaseNotes.md @@ -3,7 +3,7 @@ Included are notes from the latest major revision to current. For full documentation please visit: -https://docs.adobe.com/content/help/en/media-analytics/using/sdk-implement/download-sdks.html +https://experienceleague.adobe.com/docs/media-analytics/using/getting-started/download-sdks.html ## 2.2.7 (12 August, 2024) What's new: @@ -69,7 +69,7 @@ What’s new : What’s new : - Added SceneGraph compatibility to AdobeMobileLibrary - Misc. bug fixes -- API changes: AdobeMobile APIs and Constants have been rewritten into SceneGraph compatible node. For details, refer to the SceneGraph section of the Roku documentation: https://marketing.adobe.com/resources/help/en_US/sc/appmeasurement/hbvideo/roku/c_vhl_sg_titlepage.html +- API changes: AdobeMobile APIs and Constants have been rewritten into SceneGraph compatible node. For details, refer to the SceneGraph section of the Roku documentation: https://experienceleague.adobe.com/docs/media-analytics/using/implementation/media-sdk/setup/set-up-roku.html ## 2.0.1 (10 April, 2017) What’s new : diff --git a/sdks/roku/docs/README.md b/sdks/roku/docs/README.md index fad8d5b..dc26a49 100644 --- a/sdks/roku/docs/README.md +++ b/sdks/roku/docs/README.md @@ -12,4 +12,4 @@ Download AdobeMobileLibrary with SceneGraph support 4. Import adbmobile.brs into your Scene - refer documentation for more details 5. Create instance of adbmobileTask node into your Scene - refer documentation for more details 6. Get an instance of adbmobile connector for SceneGraph using the adbmobileTask instance - refer documentation for more details -7. Start using the adbmobile APIs available on connector instance - refer documentation for more details \ No newline at end of file +7. Start using the adbmobile APIs available on connector instance - refer documentation for more details