New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Outstream Video Support #1082

Merged
merged 31 commits into from Apr 19, 2017

Conversation

Projects
None yet
5 participants
@protonate
Collaborator

protonate commented Mar 27, 2017

Type of change

  • Feature

Description of change

As media formats proliferate a Renderer type is proposed. This provides a set of functions to specify, load, configure and utilize a custom 3rd party renderer for a given bid's media format.

An initial use case for Renderer is support for outstream video as shown in this change. Here we are assuming the renderer_url is a value returned on a Bid response object, and if present the Bid response is assumed to be an outstream video ad in need of a custom renderer.

A renderer source could also be specified at the adapter or publisher level, which can be done by setting the rendererInstance.url value appropriately.

To implement in a bidder adapter, import Renderer module:

import { Renderer } from 'src/renderer';

A renderer can be installed on a bid response in a bidder adapter by using the static Renderer.install method. This takes an object with the following properties:

  {
    url: 'path/to/renderer.js'
    config: { example: 'an object to configure renderer options' },
    id: 1, // an id may be present in the renderer info returned on a bid
    callback: () => return 'function to call once renderer has loaded'
  }

An example looks like:

bid.renderer = Renderer.install({
  id: ad.renderer_id,
  url: ad.renderer_url,
  config: { adText: `AppNexus Outstream Video Ad via Prebid.js` },
  callback: () => onOutstreamRendererLoaded.call(null, bid)
});

Once a renderer is installed on a bid, the renderer can set it's render function using setRender():

  function onOutstreamRendererLoaded(bid) {
    bid.renderer.setRender(outstreamRender);
  }

The render function will receive the bid response object and the renderer can be called with it:

  function outstreamRender(bid) {
    window.ANOutstreamVideo.renderAd({
      tagId: bid.adResponse.tag_id,
      sizes: [bid.getSize().split('x')],
      targetId: bid.adUnitCode, // target div id to render video
      uuid: bid.adResponse.uuid,
      adResponse: bid.adResponse,
      rendererOptions: bid.renderer.getConfig()
    }, handleOutstreamRendererEvents.bind(bid));
  }

For the AppNexus Outstream Video renderer, the second argument takes a function that is invoked on events. We use this to call the Renderer's handleVideoEvent method:

  function handleOutstreamRendererEvents(id, eventName) {
    const bid = this;
    bid.renderer.handleVideoEvent({ id, eventName });
  }

A renderer can register event handlers using a hash with keys mapped to the renderers event names:

bid.renderer.setEventHandlers({
  impression: () => utils.logMessage('AppNexus outstream video impression event'),
  loaded: () => utils.logMessage('AppNexus outstream video loaded event'),
  ended: () => {
    utils.logMessage('AppNexus outstream renderer video event');
    document.querySelector(`#${bid.adUnitCode}`).style.display = 'none';
  }
});

@protonate protonate requested a review from mkendall07 Apr 6, 2017

@protonate

This comment has been minimized.

Show comment
Hide comment
@protonate

protonate Apr 6, 2017

Collaborator

@mkendall07 steel thread version for review

Collaborator

protonate commented Apr 6, 2017

@mkendall07 steel thread version for review

@protonate protonate self-assigned this Apr 11, 2017

Show outdated Hide outdated src/prebid.js
};
function performRenderViaRenderer(doc, adObject) {
window.apntag = { debug: true };

This comment has been minimized.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

this logic is specific to appnexus, we should move it into the adapter or into a renderer interface type.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

this logic is specific to appnexus, we should move it into the adapter or into a renderer interface type.

Show outdated Hide outdated src/prebid.js
// use renderer defined by creative or default to ANOutstreamVideo.js
loadScript(
adObject.rendererUrl ||
'http://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js'

This comment has been minimized.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

make protocoless to support https

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

make protocoless to support https

Show outdated Hide outdated test/spec/e2e/gpt-examples/gpt_outstream.html
bidder: 'appnexusAst',
params: {
placementId: '5768085',
video: {

This comment has been minimized.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

I wonder if we could move these params up to the adunit level?

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

I wonder if we could move these params up to the adunit level?

Show outdated Hide outdated src/prebid.js
var url = adObject.adUrl;
var ad = adObject.ad;
const { height, width, ad, mediaType } = adObject;
const url = adObject.adUrl;

This comment has been minimized.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

This can be included in the destructuring above

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

This can be included in the destructuring above

Show outdated Hide outdated src/prebid.js
utils.logError(`Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`);
} else if (mediaType === 'video' || mediaType === 'video-outstream') {

This comment has been minimized.

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

I don't think we want to render a pure video response yet, since that requires a video player

@mkendall07

mkendall07 Apr 12, 2017

Collaborator

I don't think we want to render a pure video response yet, since that requires a video player

@mjacobsonny mjacobsonny added the video label Apr 14, 2017

Show outdated Hide outdated integrationExamples/gpt/amp/amp_page_with_taboola_html.html
@@ -0,0 +1,180 @@
<!doctype html>

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

drop this file.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

drop this file.

Show outdated Hide outdated src/Renderer.js
@@ -0,0 +1,37 @@
import { loadScript } from 'src/adloader';
const utils = require('src/utils');

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

nit: why not import?

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

nit: why not import?

Show outdated Hide outdated src/adapters/appnexusAst.js
tagId: bid.adResponse.tag_id,
sizes: [bid.getSize().split('x')],
targetId: bid.adUnitCode, // target div id to render video
uuid: bid.adResponse.uuid, // is this the correct UUID ?

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

should work fine.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

should work fine.

Show outdated Hide outdated src/adapters/appnexusAst.js
uuid: bid.adResponse.uuid, // is this the correct UUID ?
adResponse: bid.adResponse,
rendererOptions: {
adText: 'Prebid Outstream Video Ad'

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

I think we might want to default this to empty text.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

I think we might want to default this to empty text.

Show outdated Hide outdated src/adapters/appnexusAst.js
rendererOptions: {
adText: 'Prebid Outstream Video Ad'
}
}, (id, eventName) => {

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

Is id here uuid? If so, maybe we should make this adUnit.code instead.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

Is id here uuid? If so, maybe we should make this adUnit.code instead.

Show outdated Hide outdated src/adapters/appnexusAst.js
});
});
bid.renderer.setEventHandlers({
impression: () => utils.logMessage('AppNexus outstream video impression event'),

This comment has been minimized.

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

who's firing these events?

@mkendall07

mkendall07 Apr 18, 2017

Collaborator

who's firing these events?

@mkendall07

This comment has been minimized.

Show comment
Hide comment
@mkendall07

mkendall07 Apr 18, 2017

Collaborator

Looks great! Just a few minor changes/suggestions

Collaborator

mkendall07 commented Apr 18, 2017

Looks great! Just a few minor changes/suggestions

@protonate protonate requested a review from matthewlane Apr 18, 2017

@mkendall07

This comment has been minimized.

Show comment
Hide comment
@mkendall07

mkendall07 Apr 18, 2017

Collaborator

@protonate looks like there is a conflict.

Collaborator

mkendall07 commented Apr 18, 2017

@protonate looks like there is a conflict.

protonate

@jaiminpanchal27 jaiminpanchal27 self-requested a review Apr 19, 2017

@jaiminpanchal27

This comment has been minimized.

Show comment
Hide comment
@jaiminpanchal27

jaiminpanchal27 Apr 19, 2017

Collaborator

LGTM.

Collaborator

jaiminpanchal27 commented Apr 19, 2017

LGTM.

@@ -225,6 +227,26 @@ function AppnexusAstAdapter() {
return tag && tag.ads && tag.ads.length && tag.ads.find(ad => ad.rtb);
}
function outstreamRender(bid) {
window.ANOutstreamVideo.renderAd({

This comment has been minimized.

@mkendall07

mkendall07 Apr 19, 2017

Collaborator

Exception would be thrown here if window.ANOutstreamVideo isn't defined but should be caught in renderAd so I guess it's alright for now.

@mkendall07

mkendall07 Apr 19, 2017

Collaborator

Exception would be thrown here if window.ANOutstreamVideo isn't defined but should be caught in renderAd so I guess it's alright for now.

@mkendall07

This comment has been minimized.

Show comment
Hide comment
@mkendall07

mkendall07 Apr 19, 2017

Collaborator

LGTM

Collaborator

mkendall07 commented Apr 19, 2017

LGTM

@mkendall07 mkendall07 merged commit 2198683 into master Apr 19, 2017

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

@mkendall07 mkendall07 removed the in progress label Apr 19, 2017

@mkendall07 mkendall07 deleted the feature/outstream-video branch Apr 19, 2017

@richardhector

This comment has been minimized.

Show comment
Hide comment
@richardhector

richardhector May 10, 2017

Hey @mkendall07    quick question: If you want to render outstream without DFP just straight by calling and rendering on the page, I took the example from postbid, modifying it to video, then getting bids returned, but don't get the ad to render. Not sure if this works for outstream in the same fashion as for display using the iFrame. Appreciate a short note.

              // If any bidders return any creatives
          if (params && params['hb_adid']) {
                    console.log("creatives returned");
            pbjs.renderAd(iframeDoc, params['hb_adid']);
          }
        }
      });
    });

  </script>

  <iframe id='dynamic_ad' FRAMEBORDER="0" SCROLLING="no" MARGINHEIGHT="0" MARGINWIDTH="0" TOPMARGIN="0" LEFTMARGIN="0" ALLOWTRANSPARENCY="true" WIDTH="0" HEIGHT="0"></iframe>

Hey @mkendall07    quick question: If you want to render outstream without DFP just straight by calling and rendering on the page, I took the example from postbid, modifying it to video, then getting bids returned, but don't get the ad to render. Not sure if this works for outstream in the same fashion as for display using the iFrame. Appreciate a short note.

              // If any bidders return any creatives
          if (params && params['hb_adid']) {
                    console.log("creatives returned");
            pbjs.renderAd(iframeDoc, params['hb_adid']);
          }
        }
      });
    });

  </script>

  <iframe id='dynamic_ad' FRAMEBORDER="0" SCROLLING="no" MARGINHEIGHT="0" MARGINWIDTH="0" TOPMARGIN="0" LEFTMARGIN="0" ALLOWTRANSPARENCY="true" WIDTH="0" HEIGHT="0"></iframe>

dluxemburg added a commit to Genius/Prebid.js that referenced this pull request Jul 17, 2018

Outstream Video Support (#1082)
* add renderer adapter type

initial appnexus outstream renderer adapter

* render outstream response from appnexus

* trim back to steel thread

* turn off istanbul

* fix adUrl, move mediaType logical test

* clean up

* load renderer in renderAd

* clean up

* fix loadScript in render

RAD-1439

* collapse divs on render

* add Renderer class, remove render functions from prebid.js file

* wip

* add API to Renderer to set render function and event handlers

cache loadScript for renderer
Renderer.install returns existing instance of renderer, if available

* add support for multiple video units, renderer options can be set from bid level data

* example page edits

* decruftification

* import utils with es syntax

* add tests

* add tests

* use .call instead of .bind, reduce auction time limit on example

* use mock server for tests on Renderer.install

* fix test

* appease Travis

* appease Travis some more

* appease Travis some more again

* outstream example create utility functions for readability

* test link to use public endpoint

* remove prebid key from example ad server targeting

* reorder code in bidder

* review notes

* fix test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment