Appending Ad Query Params with the Native SDKs

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

Overview

You can append query string parameters for ad targeting with either client-side or server-side ads. The IMA plugins also support SpringServe macro replacement; arbitrary ad-server macros are not automatically expanded.

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

Client-side ads

You can provide custom values through URL parameters appended to the VMAP URL.

Android implementation

Ad targeting key/value pairs can be added to your ad tag URL in two ways:

  • Add your key/value pairs directly to the ad tag URL. Google IMA allows the addition of ad targeting key/value pairs using the cust_params parameter. For details, see Google's Add key-values to a master video ad tag document.
  • Apply a Map of values to the ad tag URL using the updateAdTargetingValues method for the GoogleIMAComponent.

For either approach, the key/value pairs are added to the ad tag URL in the ADS_REQUEST_FOR_VIDEO event listener. The code sample below adds the key/value pairs using the updateAdTargetingValues method for the GoogleIMAComponent.

Here is the code to create a Map of key/value pairs, using the CUSTOM_FIELDS property of the Video object property of the ADS_REQUEST_FOR_VIDEO event:

Video video = (Video) event.getProperties().get(Event.VIDEO);
if (video != null) {
    Map<String, String> customFieldsMap = (HashMap<String, String>) video.getProperties().get(Video.Fields.CUSTOM_FIELDS);
}

Here is a complete code sample for the ADS_REQUEST_FOR_VIDEO event listener, which is added to the setup method for the Google IMA plugin:

eventEmitter.on(GoogleIMAEventType.ADS_REQUEST_FOR_VIDEO, event -> {
    // The GoogleIMAComponent owns the ad display container.
    AdsRequest adsRequest = sdkFactory.createAdsRequest();

    // Set Ad Targeting values, using the Video object's Custom Fields
    // (if they are present; if they are not present, use default values instead) 
    Video video = (Video) event.getProperties().get(Event.VIDEO);
    if (video != null) {
        Map<String, String> customFieldsMap = (HashMap<String, String>) video.getProperties().get(Video.Fields.CUSTOM_FIELDS);
        if (customFieldsMap != null) { 
            googleIMAComponent.updateAdTargetingValues(customFieldsMap);
        }
    }

    adsRequest.setAdTagUrl(adRulesURL);
    ArrayList<AdsRequest> adsRequests = new ArrayList<AdsRequest>(1);
    adsRequests.add(adsRequest);
    // Respond to the event with the new ad requests.
    event.properties.put(GoogleIMAComponent.ADS_REQUESTS, adsRequests);
    eventEmitter.respond(event);
});

iOS implementation

To append ad query parameters with the Native SDK for iOS, follow these steps:

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

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

    let updatedVideo = video.update { mutableVideo in
        var properties = mutableVideo.properties
        // Use your VMAP URL with its query parameters already URL-encoded.
        properties[kBCOVIMAAdTag] = vmapURLWithQueryParameters
        mutableVideo.properties = properties
    }
    playbackController.setVideos([updatedVideo])

    Use BCOVIMAAdsRequestPolicy.videoPropertiesVMAPAdTagUrl() so that the plugin reads this per-video ad tag. A policy created with a fixed VMAP URL uses that URL instead.

Server-side ads

The VMAP workflow below applies to VOD and legacy live SSAI sources. NextGen Live uses session initialization rather than VMAP. On Android 10.4.21 or later, call SSAIComponent.updateLive2AdsParams(Map<String, String>) before processVideo. On iOS/tvOS 7.2.18 or later, set BCOVOUXSessionProviderOptions.live2AdsParams before creating the SSAI session provider with options. Those values are sent in the session initialization request's adsParams field for server-side macro replacement.

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 ad configuration with the Implementing Server-Side Ads with the Native Player SDKs document.

    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 SSAI 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 Android implementation section of the Implementing Server-Side Ads with the Native Player SDKs document.
  2. In the Catalog's onVideo callback method, select and extract the appropriate VMAP URL from the Video object's default source, using the SSAISourceSelector. The source object returned should have a VMAP URL property.

    SSAISourceSelector sourceSelector = new SSAISourceSelector();
    Source source = sourceSelector.selectSource(video);            
    String vmapUrl = source.getStringProperty(Source.Fields.VMAP);
    source.getProperties().put(Source.Fields.VMAP, configureVmapUrlWithCustomParams(vmapUrl, vmapUrlParams));
  3. Append your query parameters to the VMAP URL:

    private String configureVmapUrlWithCustomParams(String vmapUrl, Map<String, String> vmapUrlParams) {
        Uri.Builder vmapBuilder = Uri.parse(vmapUrl).buildUpon();
        for (Map.Entry<String, String> entry : vmapUrlParams.entrySet()) {
            vmapBuilder.appendQueryParameter(entry.getKey(), entry.getValue());
        }
        return vmapBuilder.toString();
    }
  4. Process the updated Video object with the SSAI plugin as follows:

    plugin.processVideo(video);

Here is a complete code sample:

HttpRequestConfig httpRequestConfig = new HttpRequestConfig.Builder()
        .addQueryParameter(AD_CONFIG_ID_QUERY_PARAM_KEY, AD_CONFIG_ID_QUERY_PARAM_VALUE)
        .build();
Map<String, String> vmapUrlParams = new HashMap<>();
vmapUrlParams.put("section", "sports");
vmapUrlParams.put("multi", "baseball,tennis");

catalog.findVideoByID(getString(R.string.video_id), httpRequestConfig, new VideoListener() {
    @Override public void onVideo(Video video) {
        // The Video Sources will have a VMAP url which will be processed by the SSAI plugin,
        // If there is not a VMAP url, or if there are any requesting or parsing error,
        // an EventType.ERROR event will be emitted.
        try{
            SSAISourceSelector sourceSelector = new SSAISourceSelector();
            Source source = sourceSelector.selectSource(video);
            String vmapUrl = source.getStringProperty(Source.Fields.VMAP);
            source.getProperties().put(Source.Fields.VMAP, configureVmapUrlWithCustomParams(vmapUrl, vmapUrlParams));
            plugin.processVideo(video);
        }
        catch (NoSourceFoundException ns) {
            Log.e(TAG, "No usable source was found - " + ns.getMessage());
        }
    }
});

private String configureVmapUrlWithCustomParams(String vmapUrl, Map<String, String> vmapUrlParams) {
    Uri.Builder vmapBuilder = Uri.parse(vmapUrl).buildUpon();
    for (Map.Entry<String, String> entry : vmapUrlParams.entrySet()) {
        vmapBuilder.appendQueryParameter(entry.getKey(), entry.getValue());
    }
    return vmapBuilder.toString();
}

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 iOS implementation section of the Implementing Server-Side Ads with the Native Player SDKs 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];
    
        if (vmapURL.length > 0 && components != nil) {
            NSMutableArray *queryItems = [NSMutableArray arrayWithArray:components.queryItems ?: @[]];
            [queryItems addObjectsFromArray:@[queryItemEntrypointUrlParameter, queryItemVideoId]];
            components.queryItems = queryItems;
            mutableSource[@"vmap"] = components.URL.absoluteString;
        }
    
        [updatedSources addObject:mutableSource];
    }
  4. Process the modified URL with the SSAI 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]];