Client-side Implementation

How to configure a player application to support non-linear ad insertion

Client-side Components

The following functional client-side components are involved in the flow sequence:

  • App: The application / page that controls user interactions and the interactions between the main other client-side components
  • Video Player: the component in the app that streams and renders the video
  • Smartlib: the client-side Broadpeak SDK that manages interaction with the BkYou/broadpeak.io platform to receive metadata on inserted linear ads and non-linear ads to to be inserted
  • Smartlib Session: the object that manages individual playback sessions (specific to the stream and user)
  • SIMID Creative: the SIMID non-linear ad. It's an HTML document that contains the visual part of the ad and implements part of the SIMID protocol.
  • SIMID Controller: the component or object in the app that manages the display of SIMID creatives, typically through the management of a WebController object. The SIMID controller implements part of the SIMID protocol.
    For clarity about client-side responsibilities in this document, we introduce this component separate from the App itself. Naturally, application developers have the choice of how they model this distinction within the app.
  • Web Controller: the element in charge of loading and displaying the SIMID creative (HTML). This object depends on the device type: WebView (Android), WKWebView (iOS) or iframe (Web)

SIMID Controller

πŸ‘

Broadpeak provides an open-source reference implementation of a SIMID controller that can be integrated in a web or Android app and be bootstrapped from.

https://github.com/Broadpeak-tv/simid-controller

Role

The role of the SIMID controller is best understood from its relationship to the other component:

  • The app receives programmatic events from the SmartLib. The events carry information that indicates whether non-linear ads were returned by the ad server.
  • The app instructs the SIMID controller on how to display the non-linear ad.

πŸ’‘

These instructions are represented in the diagram below with the terms "init", "load url", "show" and "destroy". These names are purely informative, and the choice of implementation of these interactions between the App and the SIMID controller are in the hands of the application developer

  • The SIMID controller listens to the events that the Creative (loaded in the Web Controller) sends - see β€œSIMID Implementation” below
  • The SIMID controller propagates the information captured from those to the SmartLib, enabling it to react accordingly. - see β€œEvent listener” below

πŸ’‘

This functionality is necessary to ensure that the Smartlib can have access to certain information that passes between the SIMID Controller and the SIMID Creative, on all devices, particularly those on which events cannot be listened to by all components (e.g. Android and iOS). This is critical in particular for the purpose of ensuring that insertions are tracked correctly. see β€œEvent listener” below

SIMID Implementation

The controller implements the SIMID specification, and must at minimum support the following methods and messages:

  1. Section 8 - Protocol
    1. 8.4.1 - createSession
    2. 8.2.1 - resolve
    3. 8.2.2 - reject
  2. Section 4.3 - "Messages from the player" - sent by the SIMID controller to the Creative
    1. 4.3.7 - SIMID:Player:init
    2. 4.3.10 - SIMID:Player:startCreative
    3. 4.3.6 - SIMID:Player:fatalError
    4. 4.3.9 - SIMID:Player:resize
  3. Section 4.4 - "Messages from the Creative to the Player" - sent by the SIMID Creative to the SIMID controller
    1. 4.4.15 - SIMID:Creative:requestResize - necessary to enable ads that don’t overlay over the video, such as in L-Shape scenarios - see β€œPlayer Resizing” below for more information
    2. 4.4.4 - SIMID:Creative:fatalError - error reported by the SIMID creative

🚧

Other SIMID messages

The SIMID spec contains other messages. Those are not currently deemed to be necessary for non-linear ads (whether static of interactive).

Event listener

The SIMID controller propagates SIMID messages in such a way that the SmartLib can listen to them. This is critical in particular for the purpose of ensuring that insertions are tracked correctly in the Broadpeak analytics system which provides a combined view of linear and non-linear ad insertions.

To do so, the controller extends a GenericSimidControllerApi(abstract class bundled with SmartLib). The app must then pass an instance of the controller to SmartLib with session.attachSimidController().

Whenever the SIMID controller receives a SIMID message from the creative, it fires the method onMessageReceived() from your instance of GenericSimidControllerApi with the associated SIMID message payload encoded as a JSON string, which contains the following:

propertytypeexample
sessionIdstringβ€œ173378a4-b2e1-11e9-a2a3-2a2ae2dbcce4”
messageIdint0
timestamplong1564501643047
typestringβ€œcreateSession”
argsmap<string, any>(object created from the JSON payload)

Conversely, when the SIMID controller sends a SIMID message to the creative, it fires the method onMessageSent() from your instance of GenericSimidControllerApi, with the message sent encoded as a JSON string.

Not all messages need to be propagated to SmartLib. In the current version, only createSession and SIMID:Player:startCreative are necessary.

Ad Tracking

The SIMID controller, since it is in charge of the display of the web controller, also needs to inform the SmartLib when it is time to send ad trackers, in particular the creativeView tracking URL. SmartLib offers a sendTracker() method for that purpose - See β€œTracking” section below for details

Overall flow

πŸ“˜

The solution has been architected to ensure minimal changes in the Smartlib compared to standard SSAI linear ads flows (documented at https://delivery-platform.broadpeak.tv/smartlib/public/ad-insertion/integration). Familiarity with those flows is assumed in the remainder of this document.
A β€œnew” icon 🌟 is used below to highlight areas specific to flows with non-linear ads which require specific and additional handling by the app or player developer.

❗️

This section focuses on an Android integration. There are likely to be small differences in implementation between different platforms (web, Android, iOS). Where relevant they are highlighted below.

  1. When the app launches, SmartLib is initialised

  2. For each video load (i.e., each channel change), a SmartLib session is created

    1. The app calls SmartLib.getInstance().createStreamingSession() and stores the session object.
    2. The app attaches the video player instance to Smartlib with session.attachPlayer(playerInstance).
    3. 🌟 The app extends a GenericSimidControllerApi and create an instance of bpkSimidController. Some of the SIMID messages received from that point on must be forwarded using bpkSimidController.onMessageReceived(messageStr) for received messages and bpkSimidController.onMessageSent(messageStr) for sent messages. Your SIMID controller might need to keep track of this instance.
    4. 🌟 The app attaches the SIMID controller instance with session.attachSimidController(bpkSimidController). This allows the SIMID controller to pass events to SmartLib.
    5. The app calls session.setAdEventsListener(…) so that the app can receive ad events.
    6. The app calls session.getURL(contentURL) to start the streaming session.
  3. When SmartLib detects an ad break

    1. 🌟 onPrepareAdBreak(adBreakData) is triggered a few seconds before the start of the ad break, in all cases (whether the ad break contains linear non-linear ads)

      1. adBreakData contains information about the ad break.
      2. This event can be used by the app to (re-)initialize the SIMID controller
    2. 🌟 onPrepareAd(adBreakData, adData) is triggered a few seconds before the start of an ad

      1. 🌟 The app determines if the ad has non-linear ads attached

        1. on Web, this is done by looking up the field adData.adType, which will contain one of the following values:

          linearThe ad only contains a linear creative
          nonlinearThe ad only contains a non-linear creative
          linear_and_nonlinearThe ad contains both linear and non-linear creatives
        2. on Android, this is done by calling adData.getType(), which returns an enum value

          AD_LINEARThe ad only contains a linear creative
          AD_NON_LINEARThe ad only contains a non-linear creative
          AD_LINEAR_AND_NON_LINEARThe ad contains both linear and non-linear creatives
      2. 🌟 If a non-linear creative is present, the app retrieves the metadata for the SIMID resource:

        1. On Web, by looking up adData.nonLinearIframeResources
        2. On Android, by calling adData.getNonLinearIframeResources()

        Both return an array of objects with the following properties:

        propertytypedescription
        urlstringURL of the SIMID resource
        parametersstringContains information that needs to be passed to the SIMID Creative through the Player:init. It contains a JSON string but it is the creative’s responsibility to parse and interpret it.
      3. 🌟 The app instructs the SIMID controller to load the SIMID creative from that URL. The SIMID controller creates a WebController in the way appropriate to each device.

      4. The SIMID Creative exchanges a few messages with the SIMID controller to ensure everything is working properly: createSession, Player:init, resolve - see section 6.2 β€œWorkflow Initialization” of the SIMID specification.

      5. The SIMID Controller propagates those messages to SmartLib with bpkSimidController.onMessageReceived(messageStr) and bpkSimidController.onMessageSent(messageStr).

    3. onAdBreakBegin(adBreakData) is triggered when the ad break starts.

    4. onAdBegin(adBreakData, adData) is triggered when an ad starts.

      1. 🌟 The app instructs the SIMID controller to display the SIMID Creative (if one was successfully prepared in onPrepareAd())
      2. 🌟 The SIMID Creative exchanges a few messages with the controller: Player:startCreative, resolve- see section 6.3 β€œTypical Start Creative Workflow” of the SIMID specification:
      3. 🌟 The SIMID Controller ensures that the WebController is displayed to the end-user.
      4. 🌟 The SIMID Controller instructs SmartLib to trigger the creativeView tracking URL, with session.sendTracker(AdTracking.CREATIVE_VIEW). This triggers the impression call to the ad server.
      5. 🌟 The SIMID Creative sends a Creative:requestResize message to instruct the app to resize the player. The app resizes the video player component accordingly - see β€œPlayer Resizing” below for more information.
      6. The SIMID Controller propagates those messages to SmartLib with bpkSimidController.onMessageReceived(messageStr) and bpkSimidController.onMessageSent(messageStr).
    5. onAdEnd(adBreakData, adData) is triggered when the ad ends

      1. 🌟 The app instructs the SIMID Controller to hide the SIMID Creative
      2. 🌟 The app resets the size of the video player
    6. onAdBreakEnd(adBreakData) is triggered when the ad break ends

      1. 🌟 The app can use this event to free the memory of the SIMID controller (if appropriate)

Sample Code

Please refer to SIMID controller repository for reference implementation:

Player resizing

To enable the display of non-linear ads around the video content and avoid obscuring part of the content, the SIMID creative will send a SIMID:Creative:requestResize command to the SIMID controller, with the calculated coordinates and dimensions (in pixels) of the area of the creative within which the video needs to be displayed.

The dimensions returned take into account the dimensions of the player component and of the creative.

The SIMID controller passes those dimensions to the app, which must resize the video component accordingly. If transitions are warranted for a better user experience (such as a gradual squeeze back), it is the responsibility of the application to apply them.

⚠️

Deviation from SIMID spec

The SIMID spec (latest v1.2) indicates that:

SIMID does not support L-shaped ads that resize the video player without an overlay covering the video

and that, instead

The video asset will need to be cropped or resized to allow the interactive creative to be put into the correct place

This constraint is not workable, in particular in a SSAI solution supporting non-linear ads (such as L-Banners), especially when they don’t accompany a corresponding linear creative and are therefore to be displayed alongside the main content.

Our solution therefore requires a small β€œdeviation” from the standard specification, to allow a creative to inform a player/app of the need to resize the video component and make it smaller than the (full-frame) creative. This is possible without any change to the SIMID message syntax.

Example

πŸ’‘

For simplicity, we use a 4-tuple to represent a Dimensions object: (x, y, width, height)

This example assumes that

  • the display has a natural 4K (3840x2160) resolution
    • This is sent by the SIMID controller to the creative in the SIMID:Player:init message
  • the source image (returned by the ad server) has a resolution of 1920x1080, with a media area declared as (200, 0, 1720, 968)
    • This information is passed by the Smartlib to the Creative through the SIMID:Player:init message, in particular the CreativeData.adParameters
non-linear ad creative, with dimensions

non-linear ad creative, with dimensions

On that basis, the creative will calculate and send a SIMID:Creative:requestResize message with the following payload

  • creativeDimensions: (0, 0, 3840, 2160)
  • mediaDimensions: (400, 0, 3440, 1935)

The application performs the resize of the video player accordingly:

Application, with resized video player (hashed area)

Application, with resized video player (hashed area)

❗️

It is critical that the player not send a SIMID:Player:resize after receiving and resolving a SIMID:Creative:requestResize

Ad Tracking

Impressions

The impression (or impressions) are valid for the whole ad, whether or not they contain linear and/or non-linear components. They are automatically being fired by the SmartLib

Tracking beacons

The only tracker used for non-interactive non-linear ads is creativeView.

It is the responsibility of the SIMID Controller to instruct SmartLib to send the tracker, after it has ensured that the ad is successfully displayed. This is described in the flow above