Skip to content
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

Implementing prebid-cache to support Video ads #1277

Merged
merged 27 commits into from
Jul 11, 2017
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e5c7920
Added code to cache video content, and made the cache key accessible …
dbemiller Jun 7, 2017
5985f39
Renamed the method we add to the bid.
dbemiller Jun 7, 2017
65863a6
Removed an extraneous function.
dbemiller Jun 7, 2017
219df5d
Removed some accidental console.log messages
dbemiller Jun 7, 2017
73b0d26
Added unit tests for the video cache, and fixed a bug or two.
dbemiller Jun 8, 2017
57139cc
Refactored the bidmanager a bit to help wrap my head around it, and c…
dbemiller Jun 19, 2017
77831e1
Implemented video end-to-end. Waiting on the modules PR so that it ca…
dbemiller Jun 21, 2017
da3459d
Better fix to the utils bug. Modernized the imports.
dbemiller Jun 21, 2017
3f94cfc
Updated documentation.
dbemiller Jun 22, 2017
008eda0
Added a few unit tests, and added fixtures for shared data structures.
dbemiller Jun 22, 2017
74ebd03
Added more thorough tests, and refactored a bit for better code reuse.
dbemiller Jun 23, 2017
c20c6b1
Renamed a function.
dbemiller Jun 23, 2017
ab4745d
Added tests for adding video bids when the cache fails.
dbemiller Jun 23, 2017
e3673aa
Removed an unused import.
dbemiller Jun 23, 2017
17e77dc
Added tests for the adServerManager, and renamed some files for consi…
dbemiller Jun 23, 2017
0fc1bd1
Renamed the dfpVideo module, and added unit tests for it.
dbemiller Jun 23, 2017
285e0ca
Moved dfpAdServerVideo into the modules directory.
dbemiller Jun 27, 2017
bfb1cc6
Fixed a bug, and added a regression test to catch it in the future.
dbemiller Jun 27, 2017
fcf673a
Added a bare-bones example page.
dbemiller Jun 27, 2017
09807f3
Made some cosmetic changes to names and documentation.
dbemiller Jun 27, 2017
0ebe649
Removed the shifty API. Updated unit tests. Renamed a property becaus…
dbemiller Jun 27, 2017
7df1e7e
Most code review comments. Still need to look into the details of VAST.
dbemiller Jun 30, 2017
4b9624b
Deleted some unused code, and upped the vast version to use 3.0 every…
dbemiller Jul 5, 2017
863bfb4
Made the cache use the new endpoints
dbemiller Jul 7, 2017
72fd424
Fixed style.
dbemiller Jul 10, 2017
fb4045b
Moved the test page into the tests directory.
dbemiller Jul 10, 2017
da637df
include the bid that ended the auction
mkendall07 Jul 11, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions integrationExamples/gpt/video_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be moved to ./test as it isn't really an integration example.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Prebid.js video adUnit example</title>

<!-- videojs -->
<link rel="stylesheet" href="http://vjs.zencdn.net/5.9.2/video-js.css">
<script type="text/javascript" src="http://vjs.zencdn.net/5.9.2/video.js"></script>

<!-- videojs-vast-vpaid -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs.vast.vpaid.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs_5.vast.vpaid.min.js"></script>

<!-- prebid.js -->
<script src="../../build/dev/prebid.js" async=true></script>


<script>

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

/*
Prebid Video adUnit
*/

var videoAdUnit = {
code: 'video1',
sizes: [640,480],
mediaType: 'video',
bids: [
{
bidder: 'appnexusAst',
params: {
placementId: '9333431',
video: {
skipppable: false,
playback_methods: ['auto_play_sound_off']
}
}
}
]
};

pbjs.que.push(function(){
pbjs.addAdUnits(videoAdUnit);
pbjs.requestBids({
timeout : 700,
bidsBackHandler : function(bids) {
var videoUrl = pbjs.adServers.dfp.buildVideoUrl({
adUnit: videoAdUnit,
params: {
iu: '/19968336/prebid_cache_video_adunit'
}
});

invokeVideoPlayer(videoUrl);
}
});
});

pbjs.bidderSettings =
{
standard: {
adserverTargeting: [
{
key: "hb_bidder",
val: function (bidResponse) {
return bidResponse.bidderCode;
}
}, {
key: "hb_adid",
val: function (bidResponse) {
return bidResponse.adId;
}
}, {
key: "hb_pb",
val: function (bidResponse) {
return "10.00";
}
}, {
key: "hb_size",
val: function (bidResponse) {
return bidResponse.size;

}
}
]
}
};
</script>
</head>

<body>

<h2>Prebid Video -- video.js</h2>

<div class="example-video-container">

<video id="vid1" class="video-js vjs-default-skin vjs-big-play-centered" controls
data-setup='{}'
width='640'
height='480'
>
<source src="http://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'/>
<source src="http://vjs.zencdn.net/v/oceans.webm" type='video/webm'/>
<source src="http://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'/>

</video>
</div>

<script>
function invokeVideoPlayer(url) {
videojs("vid1").ready(function() {
this.vastClient({
adTagUrl: url,
playAdAlways: true,
verbosity: 4,
vpaidFlashLoaderPath: "https://github.com/MailOnline/videojs-vast-vpaid/blob/RELEASE/bin/VPAIDFlash.swf?raw=true",
autoplay: true
});

this.muted(true);
this.play();
});
}

</script>
</body>
</html>
88 changes: 88 additions & 0 deletions modules/dfpAdServerVideo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* This module adds [DFP support]{@link https://www.doubleclickbygoogle.com/} for Video to Prebid.
*/

import { registerVideoSupport } from '../src/adServerManager';
import { getWinningBids } from '../src/targeting';
import { formatQS, format as buildUrl } from '../src/url';
import { parseSizesInput } from '../src/utils';

/**
* @typedef {Object} DfpVideoParams
*
* This object contains the params needed to form a URL which hits the
* [DFP API]{@link https://support.google.com/dfp_premium/answer/1068325?hl=en}.
*
* All params (except iu, mentioned below) should be considered optional. This module will choose reasonable
* defaults for all of the other required params.
*
* The cust_params property, if present, must be an object. It will be merged with the rest of the
* standard Prebid targeting params (hb_adid, hb_bidder, etc).
*
* @param {string} iu This param *must* be included, in order for us to create a valid request.
* @param [string] description_url This field is required if you want Ad Exchange to bid on our ad unit...
* but otherwise optional
*/

/**
* @typedef {Object} DfpVideoOptions
*
* @param {Object} adUnit The adUnit which this bid is supposed to help fill.
* @param [Object] bid The bid which should be considered alongside the rest of the adserver's demand.
* If this isn't defined, then we'll use the winning bid for the adUnit.
*
* @param {DfpVideoParams} params Query params which should be set on the DFP request.
* These will override this module's defaults whenever they conflict.
*/

/** Safe defaults which work on pretty much all video calls. */
const defaultParamConstants = {
env: 'vp',
gdfp_req: 1,
output: 'xml_vast3',
unviewed_position_start: 1,
};

/**
* Merge all the bid data and publisher-supplied options into a single URL, and then return it.
*
* @see [The DFP API]{@link https://support.google.com/dfp_premium/answer/1068325?hl=en#env} for details.
*
* @param {DfpVideoOptions} options Options which should be used to construct the URL.
*
* @return {string} A URL which calls DFP, letting options.bid
* (or the auction's winning bid for this adUnit, if undefined) compete alongside the rest of the
* demand in DFP.
*/
export default function buildDfpVideoUrl(options) {
const adUnit = options.adUnit;
const bid = options.bid || getWinningBids(adUnit.code)[0];

const derivedParams = {
correlator: Date.now(),
sz: parseSizesInput(adUnit.sizes).join('|'),
url: location.href,
};

const customParams = Object.assign({},
bid.adserverTargeting,
{ hb_uuid: bid.videoCacheKey },
options.params.cust_params);

const queryParams = Object.assign({},
defaultParamConstants,
derivedParams,
options.params,
{ cust_params: encodeURIComponent(formatQS(customParams))});

return buildUrl({
protocol: 'https',
host: 'pubads.g.doubleclick.net',
pathname: '/gampad/ads',
search: queryParams
});
}

registerVideoSupport('dfp', {
buildVideoUrl: buildDfpVideoUrl
});
54 changes: 54 additions & 0 deletions src/adServerManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { getGlobal } from 'src/prebidGlobal';
import { logWarn } from 'src/utils';

const prebid = getGlobal();

/**
* This file defines the plugin points in prebid-core for AdServer-specific functionality.
*
* Its main job is to expose functions for AdServer modules to append functionality to the Prebid public API.
* For a given Ad Server with name "adServerName", these functions will only change the API in the
* $$PREBID_GLOBAL$$.adServers[adServerName] namespace.
*/

/**
* @typedef {Object} CachedVideoBid
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types-ish! 👍

*
* @property {string} videoCacheId The ID which can be used to retrieve this video from prebid-server.
* This is the same ID given to the callback in the videoCache's store function.
*/

/**
* @function VideoAdUrlBuilder
*
* @param {CachedVideoBid} bid The winning Bid which the ad server should show, assuming it beats out
* the competition.
*
* @param {Object} options Options required by the Ad Server to make a valid AdServer URL.
* This object will have different properties depending on the specific ad server supported.
* For more information, see the docs inside the ad server module you're supporting.
*
* @return {string} A URL which can be passed into the Video player to play an ad.
*/

/**
* @typedef {Object} VideoSupport
*
* @function {VideoAdUrlBuilder} buildVideoAdUrl
*/

/**
* Enable video support for the Ad Server.
*
* @property {string} name The identifying name for this adserver.
* @property {VideoSupport} videoSupport An object with the functions needed to support video in Prebid.
*/
export function registerVideoSupport(name, videoSupport) {
prebid.adServers = prebid.adServers || { };
prebid.adServers[name] = prebid.adServers[name] || { };
if (prebid.adServers[name].buildVideoUrl) {
logWarn(`Multiple calls to registerVideoSupport for AdServer ${name}. Expect surprising behavior.`);
return;
}
prebid.adServers[name].buildVideoUrl = videoSupport.buildVideoUrl;
}
Loading