Appending Ad Query Params with the Native SDKs

Product(s)
Video Cloud
Brightcove Player
Role(s)
Device SDK Developer
Task(s)
Develop with the Native SDKs
Topic(s)
Advertising
SDK
Android
iOS
tvOS

In this topic, you will learn how to append advertising query parameters to your VMAP URLs with the Brightcove Native Player SDKs.

Overview

Even though the Native player SDKs do not perform client-side macro replacement, you can manually append query string parameters for ad targeting. This can be done for either client-side or server-side ads.

To learn more about URL parameters, see the Ad Variables section of the Video Cloud SSAI Ad Config API document.

Client-side ads

To provide custom values through URL parameters appended to the VMAP URL, follow these steps:

  1. Start with one of the client-side code samples for IMA advertising with the Brightcove Native SDKs:

  2. Append the URL query parameters to the VMAP URL before calling the IMA plugin. This can be done before the following methods:

    Android

    adsRequest.setAdTagUrl(adRulesURL);

     

    iOS
    updatedVideos.append(_video.updateVideo(withVMAPTag: IMAConfig.VMAPResponseAdTag))

Server-side ads

To provide custom values through URL parameters appended to the VMAP URL, follow these steps:

  1. With an SSAI ad configuration id, retrieve a video object from the Brightcove catalog (Playback API). Learn how to create an SSAI ad configuration with the Video Cloud SSAI Ad Config API. A sample ad configuration looks like this:

    {
      "name": "SSAI VMAP Ad Server",
      "vmap_response_namespace": "bc",
      "config_id": "your ad config Id",
      "account_id": "1752604059001",
      "created_timestamp": "2017-10-24T20:21:55.106488973Z",
      "updated_timestamp": "2017-10-26T14:26:22.161791419Z",
      "ad_config": {
      	"enable_ads": true,
      	"expected_ad_response": "dfp_vmap",
      	"proxy_beacons_enabled": false,
      	"template_url": {
      		"template": "https://solutions.brightcove.com/bcls/brightcove-player/vmap/simple-vmap.xml"
      	}
      }
    }
  2. In the jsonResponse from the call to the Playback API, examine the sources for the video object. Each source object will contain a VMAP property and a VMAP URL. Select and extract the VMAP URL.

    http://ssaiplayback.prod.boltdns.net/playback/once/v1/vmap/hls/v3/clear/3981276734001/
      b871a6b8-4b3e-4787-b176-aed923287d5a/477b1308-fc18-47a6-bb99-6cb9e2ff2040/
      content.vmap?bc_token=XXX
  3. Let’s say your ad URL looks like this:

    https://myad.com/ads?rule={{url.rule}}&id={{url.video.id}}

    If your ad URL has the above ad macros, then you will add these query parameters to the VMAP URLs with the appropriate values.

  4. Append query parameters to the VMAP URL. In this example, the {{url.rule}} macro in the ad url is replaced with the value discos-enabled, and the {{url.video_id}} macro is replaced with the video id value.

    http://ssaiplayback.prod.boltdns.net/playback/once/v1/vmap/hls/v3/clear/3981276734001/
    b871a6b8-4b3e-4787-b176-aed923287d5a/477b1308-fc18-47a6-bb99-6cb9e2ff2040/
    content.vmap?bc_token=XXX&rule=discos-enabled&video_id=5625751316001
  5. Process the video with the Once UX plugin.
  6. For development details, see the following:

Android implementation

From the Playback API response, you can extract the appropriate VMAP source URL and append your query parameters. To do this, follow these steps:

  1. With an SSAI ad configuration id, retrieve a video object from the Brightcove catalog (Playback API). For details, see the SSAI with the SDKs: Android implementation document.
  2. From the video object, select and extract the appropriate VMAP URL. Retrieve the default source using the OnceUxSourceSelectionController object. The source object returned will have these properties:

    source.getProperties().get(Source.Fields.VMAP);
  3. Append query parameters to the VMAP URL.
  4. Process the modified URL with the Once UX plugin as follows:

    plugin.processVideo(videoUrlString);

iOS implementation

From the Playback API response, you can extract the appropriate VMAP source URL and append your query parameters. To do this, follow these steps:

  1. With an SSAI ad configuration id, retrieve a video object from the Brightcove catalog (Playback API). For details, see the SSAI with the SDKs: iOS implementation document.
  2. From the video object, select and extract the appropriate manifest or VMAP URL. From the playback service response, the jsonResponse (NSDictionary) contains the BCOVVideo object, which includes the sources which hold the URL to the VMAP document. Your code may look similar to this:

    // Create a mutable version of the jsonResponse NSDictionary object
    NSURLComponents *components = [[NSURLComponents alloc] init];
    NSMutableDictionary *videoPropertiesDictionary = [[NSMutableDictionary alloc] init];
    NSMutableArray *updatedSources = [[NSMutableArray alloc] init];
    
    // Define the URL parameters that will be added to the VMAP URL
    NSURLQueryItem *queryItemEntrypointUrlParameter = [NSURLQueryItem queryItemWithName:@"rule" value:@"discos-enabled"];
    NSURLQueryItem *queryItemVideoId = [NSURLQueryItem queryItemWithName:@"video_id" value:jsonResponse[@"id"]];
    
    //deserialize the video and store in dictionary
    [videoPropertiesDictionary addEntriesFromDictionary:jsonResponse];
  3. Append query parameters to the VMAP URL.

    // For each source, update each VMAP URL stored in the jsonResponse NSDictionary object and assemble the NSURLQueryItem. Store it in the mutable version of the jsonResponse NSDictionary object.
    for (NSDictionary *source in videoPropertiesDictionary[@"sources"])
    {
        NSMutableDictionary *mutableSource = [[NSMutableDictionary alloc] init];
        [mutableSource addEntriesFromDictionary:source];
    
        NSString *vmapURL = mutableSource[@"vmap"];
        components = [NSURLComponents componentsWithString:vmapURL];
    
        NSArray *queryItemsArray = components.queryItems;
        NSURLQueryItem *bctoken = [queryItemsArray firstObject];
        components.queryItems = @[bctoken, queryItemEntrypointUrlParameter, queryItemVideoId ];
        mutableSource[@"vmap"] = components.URL.absoluteString;
    
        [updatedSources addObject:mutableSource];
    }
  4. Process the modified URL with the Once UX plugin as follows:

    videoPropertiesDictionary[@"sources"] = updatedSources;
    // Create a new video object with the updated jsonResponse NSDictionary object
    BCOVVideo *video = [BCOVPlaybackService videoFromJSONDictionary:videoPropertiesDictionary];
    // Setting this video object to the BCOVPlaybackController will call the new vmap URL (with the URL parameters appended) when playback starts.
    [self.controller setVideos:@[video]];

    For a complete code example, expand the iOS ViewController using Objective-C section below.

iOS ViewController using Objective-C

Your ViewController.m file should look similar to this:

//
//  ViewController.m
//  SSAI Params
//
//  Copyright © 2018 Brightcove. All rights reserved.
//

#import "ViewController.h"

@import BrightcovePlayerSDK;
@import BrightcoveOUX;

// ** Customize these values with your own account information **
NSString *accountId = @"your account Id";
NSString *policyKey = @"your policy key";
NSString *videoId = @"your video Id";
NSString *adConfigId = @"your ad configuration Id";

@interface ViewController () <BCOVPlaybackControllerDelegate>

@property (nonatomic, strong) id<BCOVPlaybackController> playbackController;
@property (nonatomic, strong) BCOVPlaybackService *playbackService;
@property (nonatomic) BCOVPUIPlayerView *playerView;
@property (weak, nonatomic) IBOutlet UIView *videoContainerView;
@property (weak, nonatomic) IBOutlet UIView *companionSlotContainerView;
@property(copy) NSArray<NSURLQueryItem *> *queryItems;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    BCOVPlayerSDKManager *manager = [BCOVPlayerSDKManager sharedManager];

    // Create a companion slot.
    BCOVOUXCompanionSlot *companionSlot = [[BCOVOUXCompanionSlot alloc] initWithView:self.companionSlotContainerView width:500 height:61];

    // In order to display an ad progress banner on the top of the view, we create this display container.  This object is also responsible for populating the companion slots.
    BCOVOUXAdComponentDisplayContainer *adComponentDisplayContainer = [[BCOVOUXAdComponentDisplayContainer alloc] initWithCompanionSlots:@[companionSlot]];

    self.controller = [manager createOUXPlaybackControllerWithViewStrategy:nil];

    // In order for the ad display container to receive ad information, we add it as a session consumer.
    [self.controller addSessionConsumer:adComponentDisplayContainer];

    self.controller.delegate = self;
    self.controller.autoPlay = YES;
    self.controller.autoAdvance = YES;

    BCOVPUIBasicControlView *controlView = [BCOVPUIBasicControlView basicControlViewWithVODLayout];
    // Set playback controller later.
    self.playerView = [[BCOVPUIPlayerView alloc] initWithPlaybackController:nil options:nil controlsView:controlView];

    [self.videoContainerView addSubview:self.playerView];
    self.playerView.translatesAutoresizingMaskIntoConstraints = NO;
    [NSLayoutConstraint activateConstraints:@[
        [self.playerView.topAnchor constraintEqualToAnchor:self.videoContainerView.topAnchor],
        [self.playerView.rightAnchor constraintEqualToAnchor:self.videoContainerView.rightAnchor],
        [self.playerView.leftAnchor constraintEqualToAnchor:self.videoContainerView.leftAnchor],
        [self.playerView.bottomAnchor constraintEqualToAnchor:self.videoContainerView.bottomAnchor],
    ]];

    self.playerView.playbackController = self.controller;

    _playbackService = [[BCOVPlaybackService alloc]
                        initWithAccountId:accountId
                        policyKey:policyKey];

    [self requestContentFromPlaybackService];
}

- (void)requestContentFromPlaybackService
{
	// Set your SSAI ad configuration id as a query parameter
  NSDictionary *queryParameters = @{
                                    @"ad_config_id" : kViewControllerAdConfigID
                                    };
  // Retrieve a video from the Playback API using a video Id and your ad config Id
  [self.playbackService findVideoWithVideoID:videoId parameters:queryParameters completion:^(BCOVVideo *video, NSDictionary *jsonResponse, NSError *error) {

    if (video)
    {
      // Create a mutable version of the jsonResponse NSDictionary object
      NSURLComponents *components = [[NSURLComponents alloc] init];
      NSMutableDictionary *videoPropertiesDictionary = [[NSMutableDictionary alloc] init];
      NSMutableArray *updatedSources = [[NSMutableArray alloc] init];

			// Define the URL parameters that will be added to the VMAP URL
      NSURLQueryItem *queryItemEntrypointUrlParameter = [NSURLQueryItem queryItemWithName:@"rule" value:@"discos-enabled"];
      NSURLQueryItem *queryItemVideoId = [NSURLQueryItem queryItemWithName:@"video_id" value:jsonResponse[@"id"]];

      //deserialize the video and store in dictionary
      [videoPropertiesDictionary addEntriesFromDictionary:jsonResponse];

      // For each source, update each VMAP URL stored in the jsonResponse NSDictionary object
      // and assemble the NSURLQueryItem. Store it in the mutable version of the jsonResponse NSDictionary object.
      for (NSDictionary *source in videoPropertiesDictionary[@"sources"])
      {
        NSMutableDictionary *mutableSource = [[NSMutableDictionary alloc] init];
        [mutableSource addEntriesFromDictionary:source];

        NSString *vmapURL = mutableSource[@"vmap"];
        components = [NSURLComponents componentsWithString:vmapURL];

        NSArray *queryItemsArray = components.queryItems;
        NSURLQueryItem *bctoken = [queryItemsArray firstObject];
        components.queryItems = @[bctoken, queryItemEntrypointUrlParameter, queryItemVideoId ];
        mutableSource[@"vmap"] = components.URL.absoluteString;

        [updatedSources addObject:mutableSource];
      }
      videoPropertiesDictionary[@"sources"] = updatedSources;
      // Create a new video object with the updated jsonResponse NSDictionary object
      BCOVVideo *video = [BCOVPlaybackService videoFromJSONDictionary:videoPropertiesDictionary];
      // Setting this video object to the BCOVPlaybackController will call the new vmap URL
      // (with the URL parameters appended) when playback starts.
      [self.controller setVideos:@[video]];
    }
    else
    {
      NSLog(@"ViewController Debug - Error retrieving video playlist: `%@`", error);
    }

  }];
}

@end