From dea9a66ec8b509184c72fc994ead4d9129df3ae4 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Fri, 23 Jun 2017 15:00:29 +0100 Subject: [PATCH] fix: render ad inside storybook Storybook relies on iframes to render stories, gpt map sizes, used to build responsive ads don't seem to work with it. This hack solves it for now until further developments on https://github.com/storybooks/storybook/issues/862 --- packages/gpt/ad-manager.js | 81 ++++++++++-------- packages/gpt/config.js | 145 +++++++++++++------------------- packages/gpt/generate-config.js | 36 ++++---- packages/gpt/gpt-manager.js | 19 ++--- packages/gpt/gpt.stories.js | 24 +++--- packages/gpt/gpt.test.js | 11 ++- packages/gpt/gpt.web.js | 21 ++--- packages/gpt/pbjs-manager.js | 74 ++++++++-------- 8 files changed, 205 insertions(+), 206 deletions(-) diff --git a/packages/gpt/ad-manager.js b/packages/gpt/ad-manager.js index f0c9cc5363c..d397f284946 100644 --- a/packages/gpt/ad-manager.js +++ b/packages/gpt/ad-manager.js @@ -1,11 +1,11 @@ -import series from 'run-series'; -import parallel from 'run-parallel'; +import series from "run-series"; +import parallel from "run-parallel"; -import { getSlotConfig } from './generate-config'; -import gptManager from './gpt-manager'; -import pbjsManager from './pbjs-manager'; +import { getSlotConfig } from "./generate-config"; +import gptManager from "./gpt-manager"; +import pbjsManager from "./pbjs-manager"; -function AdManager (options = {}) { +function AdManager(options = {}) { if (!(this instanceof AdManager)) { return new AdManager(); } @@ -17,31 +17,33 @@ function AdManager (options = {}) { this.initialised = false; } -AdManager.prototype.isReady = function isReady () { +AdManager.prototype.isReady = function isReady() { return this.initialised; }; -AdManager.prototype.init = function init (callback) { +AdManager.prototype.init = function init(callback) { // Load scripts if needed be gptManager.loadScript(); pbjsManager.loadScript(); - series([ - // Set services config - parallel.bind(parallel, [ - gptManager.setConfig.bind(gptManager), - pbjsManager.setConfig.bind(pbjsManager) - ]), - // Init services - parallel.bind(parallel, [ - gptManager.init.bind(gptManager), - pbjsManager.init.bind(pbjsManager, this.adQueue) - ])], - (err) => { + series( + [ + // Set services config + parallel.bind(parallel, [ + gptManager.setConfig.bind(gptManager), + pbjsManager.setConfig.bind(pbjsManager) + ]), + // Init services + parallel.bind(parallel, [ + gptManager.init.bind(gptManager), + pbjsManager.init.bind(pbjsManager, this.adQueue) + ]) + ], + err => { if (err) throw new Error(err); this.initialised = true; // Actually push the ads to GPT - this.adQueue.forEach((ad) => { + this.adQueue.forEach(ad => { this._pushAdToGPT(ad.code, ad.mappings, ad.options); }); if (callback) callback(); @@ -49,32 +51,39 @@ AdManager.prototype.init = function init (callback) { ); }; -AdManager.prototype.registerAd = function registerAd (code, { width = 1024 } = {}) { +AdManager.prototype.registerAd = function registerAd( + code, + { width = 1024 } = {} +) { this.adQueue.push(getSlotConfig(this.section, code, width)); }; -AdManager.prototype.unregisterAd = function registerAd (code) { - const queueIds = this.adQueue.map((item) => item.id); +AdManager.prototype.unregisterAd = function registerAd(code) { + const queueIds = this.adQueue.map(item => item.id); const idx = queueIds.indexOf(code); if (idx > -1) { this.adQueue.splice(idx, 1); } }; -AdManager.prototype.display = function display (callback) { +AdManager.prototype.display = function display(callback) { gptManager.googletag.cmd.push(() => { pbjsManager.pbjs.que.push(() => { - console.log('refresh') + console.log("refresh"); pbjsManager.pbjs.setTargetingForGPTAsync(); gptManager.googletag.pubads().refresh(); - if(callback) callback(); + if (callback) callback(); }); }); }; -AdManager.prototype._pushAdToGPT = function pushAdToGPT (adSlotId, sizingMap, options = {}) { +AdManager.prototype._pushAdToGPT = function pushAdToGPT( + adSlotId, + sizingMap, + options = {} +) { if (!this.initialised) { - throw new Error('Ad manager needs to be initialised first'); + throw new Error("Ad manager needs to be initialised first"); } gptManager.googletag.cmd.push(() => { @@ -89,12 +98,12 @@ AdManager.prototype._pushAdToGPT = function pushAdToGPT (adSlotId, sizingMap, op // Display the ad gptManager.googletag.display(adSlotId); -console.log('Display slot', slot) -console.log('Sizing map', sizingMap) + console.log("Display slot", slot); + console.log("Sizing map", sizingMap); }); }; -AdManager.prototype._generateSizings = function generateSizings (sizingMap) { +AdManager.prototype._generateSizings = function generateSizings(sizingMap) { const mapping = gptManager.googletag.sizeMapping(); for (let i = 0; i < sizingMap.length; i++) { @@ -105,8 +114,12 @@ AdManager.prototype._generateSizings = function generateSizings (sizingMap) { return mapping.build(); }; -AdManager.prototype._createSlot = function createSlot (adSlotId, section) { - return gptManager.googletag.defineSlot(`/${this.networkId}/${this.adUnit}/${section}`, [], adSlotId); +AdManager.prototype._createSlot = function createSlot(adSlotId, section) { + return gptManager.googletag.defineSlot( + `/${this.networkId}/${this.adUnit}/${section}`, + [], + adSlotId + ); }; export default AdManager; diff --git a/packages/gpt/config.js b/packages/gpt/config.js index 7ed08219cf1..21734745871 100644 --- a/packages/gpt/config.js +++ b/packages/gpt/config.js @@ -14,27 +14,17 @@ const sizes = { { width: 300, height: 100, - sizes: [ - [320, 50], - [320, 48], - mobileStandard - ] + sizes: [[320, 50], [320, 48], mobileStandard] }, { width: 768, height: 90, - sizes: [ - leaderboard - ] + sizes: [leaderboard] }, { width: 1024, height: 250, - sizes: [ - billboard, - wideLeaderboard, - leaderboard - ] + sizes: [billboard, wideLeaderboard, leaderboard] } ], intervention: [ @@ -46,28 +36,17 @@ const sizes = { { width: 300, height: 100, - sizes: [ - [300, 250], - [320, 50], - [320, 48], - mobileStandard - ] + sizes: [[300, 250], [320, 50], [320, 48], mobileStandard] }, { width: 768, height: 90, - sizes: [ - leaderboard - ] + sizes: [leaderboard] }, { width: 1024, height: 250, - sizes: [ - billboard, - wideLeaderboard, - leaderboard - ] + sizes: [billboard, wideLeaderboard, leaderboard] } ], pixel: [ @@ -80,82 +59,78 @@ const sizes = { }; const bidders = { - 'appnexus': { - 'placementId': '5823281' + appnexus: { + placementId: "5823281" }, - 'rubicon': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918' + rubicon: { + accountId: "14062", + siteId: "70608", + zoneId: "335918" }, - 'amazon': { - 'accountId': '3360' + amazon: { + accountId: "3360" }, - 'criteo': { - 'zoneMap': { - '120x600': '764877', - '160x600': '764878', - '300x100': '764885', - '300x250': '764879', - '300x600': '764880', - '320x50': '764882', - '728x90': '764881', - '970x250': '764883', - '970x90': '764884' + criteo: { + zoneMap: { + "120x600": "764877", + "160x600": "764878", + "300x100": "764885", + "300x250": "764879", + "300x600": "764880", + "320x50": "764882", + "728x90": "764881", + "970x250": "764883", + "970x90": "764884" } }, - 'pubmatic': { - 'accountId': '01234', - 'adSlotPrefix': 'TheTimes' + pubmatic: { + accountId: "01234", + adSlotPrefix: "TheTimes" }, - 'indexExchange': { - 'siteId': '1234' + indexExchange: { + siteId: "1234" } }; // Prebid JS config const pbjs = { - 'timeout': 1000, - 'minPrice': 0.01, - 'maxBid': 15, - 'bucketSize': 0.25, - 'bidders': { - 'appnexus': { - 'placementId': '5823281' + timeout: 1000, + minPrice: 0.01, + maxBid: 15, + bucketSize: 0.25, + bidders: { + appnexus: { + placementId: "5823281" }, - 'rubicon': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918' + rubicon: { + accountId: "14062", + siteId: "70608", + zoneId: "335918" }, - 'amazon': { - 'accountId': '3360' + amazon: { + accountId: "3360" }, - 'criteo': { - 'zoneMap': { - '120x600': '764877', - '160x600': '764878', - '300x100': '764885', - '300x250': '764879', - '300x600': '764880', - '320x50': '764882', - '728x90': '764881', - '970x250': '764883', - '970x90': '764884' + criteo: { + zoneMap: { + "120x600": "764877", + "160x600": "764878", + "300x100": "764885", + "300x250": "764879", + "300x600": "764880", + "320x50": "764882", + "728x90": "764881", + "970x250": "764883", + "970x90": "764884" } }, - 'pubmatic': { - 'accountId': '01234', - 'adSlotPrefix': 'TheTimes' + pubmatic: { + accountId: "01234", + adSlotPrefix: "TheTimes" }, - 'indexExchange': { - 'siteId': '1234' + indexExchange: { + siteId: "1234" } } }; -export { - pbjs, - sizes, - bidders -}; +export { pbjs, sizes, bidders }; diff --git a/packages/gpt/generate-config.js b/packages/gpt/generate-config.js index cab26ef4d89..b3c837417e8 100644 --- a/packages/gpt/generate-config.js +++ b/packages/gpt/generate-config.js @@ -1,15 +1,15 @@ -import { bidders, sizes } from './config'; +import { bidders, sizes } from "./config"; -const getSizeMaps = (code) => { +const getSizeMaps = code => { switch (code) { - case 'ad-header': + case "ad-header": return sizes.header; - case 'ad-pixel': - case 'ad-pixelskin': - case 'ad-pixelteads': - case 'ad-article-sponsored': + case "ad-pixel": + case "ad-pixelskin": + case "ad-pixelteads": + case "ad-article-sponsored": return sizes.pixel; - default : + default: return sizes.intervention; } }; @@ -28,14 +28,14 @@ const getSlotConfig = (section, code, width) => { const mappings = getSizeMaps(code); const bids = [ { - bidder: 'appnexus', + bidder: "appnexus", params: { placementId: bidders.appnexus.placementId, section } }, { - bidder: 'rubicon', + bidder: "rubicon", params: { accountId: bidders.rubicon.accountId, siteId: bidders.rubicon.siteId, @@ -44,7 +44,7 @@ const getSlotConfig = (section, code, width) => { } }, { - bidder: 'indexExchange', + bidder: "indexExchange", params: { id: code, siteID: bidders.indexExchange.siteId @@ -54,19 +54,19 @@ const getSlotConfig = (section, code, width) => { adSizes.forEach(size => { bids.push({ - bidder: 'pubmatic', + bidder: "pubmatic", params: { publisherId: bidders.pubmatic.accountId, - adSlot: bidders.pubmatic.adSlotPrefix + '@' + size.join('x'), + adSlot: bidders.pubmatic.adSlotPrefix + "@" + size.join("x"), section } }); // Criteo - const zoneId = bidders.criteo.zoneMap[size.join('x')] || ''; + const zoneId = bidders.criteo.zoneMap[size.join("x")] || ""; if (zoneId) { bids.push({ - bidder: 'criteo', + bidder: "criteo", params: { zoneId: zoneId } @@ -82,8 +82,4 @@ const getSlotConfig = (section, code, width) => { }; }; -export { - getAdSizes, - getSizeMaps, - getSlotConfig -}; +export { getAdSizes, getSizeMaps, getSlotConfig }; diff --git a/packages/gpt/gpt-manager.js b/packages/gpt/gpt-manager.js index 5b2ea4b1016..8da1c001468 100644 --- a/packages/gpt/gpt-manager.js +++ b/packages/gpt/gpt-manager.js @@ -1,5 +1,4 @@ - -function GptManager () { +function GptManager() { if (!(this instanceof GptManager)) { return new GptManager(); } @@ -9,11 +8,11 @@ function GptManager () { this.googletag = null; } -GptManager.prototype.isReady = function isReady () { +GptManager.prototype.isReady = function isReady() { return this.scriptSet && this.initialised; }; -GptManager.prototype.loadScript = function loadScript () { +GptManager.prototype.loadScript = function loadScript() { // Check if script tag is already set if (this.scriptSet) return; @@ -22,18 +21,18 @@ GptManager.prototype.loadScript = function loadScript () { window.googletag.cmd = window.googletag.cmd || []; this.googletag = window.googletag; - const gads = document.createElement('script'); + const gads = document.createElement("script"); gads.async = true; - gads.type = 'text/javascript'; - gads.src = '//www.googletagservices.com/tag/js/gpt.js'; + gads.type = "text/javascript"; + gads.src = "//www.googletagservices.com/tag/js/gpt.js"; - const head = document.getElementsByTagName('head')[0]; + const head = document.getElementsByTagName("head")[0]; head.appendChild(gads); this.scriptSet = true; }; -GptManager.prototype.setConfig = function setConfig (callback) { +GptManager.prototype.setConfig = function setConfig(callback) { if (this.isReady()) return callback(); const googletag = this.googletag; @@ -56,7 +55,7 @@ GptManager.prototype.setConfig = function setConfig (callback) { }); }; -GptManager.prototype.init = function init (callback) { +GptManager.prototype.init = function init(callback) { if (this.isReady()) return callback(); this.googletag.cmd.push(() => { diff --git a/packages/gpt/gpt.stories.js b/packages/gpt/gpt.stories.js index 8b244f57b98..301cf439940 100644 --- a/packages/gpt/gpt.stories.js +++ b/packages/gpt/gpt.stories.js @@ -1,22 +1,20 @@ -import "react-native"; import React, { Component } from "react"; import { storiesOf } from "@storybook/react-native"; -import AdManager from './ad-manager'; +import AdManager from "./ad-manager"; import GPT from "./gpt.web"; class Wrapper extends Component { - - constructor (props) { + constructor(props) { super(props); this.adManager = new AdManager({ - networkId: '25436805', - adUnit: 'd.thetimes.co.uk', - section: 'home' + networkId: "25436805", + adUnit: "d.thetimes.co.uk", + section: "article" }); } - componentDidMount () { + componentDidMount() { this.adManager.init(() => { this.adManager.display(); }); @@ -25,12 +23,18 @@ class Wrapper extends Component { render() { return (
- + + Render ad + +
); } } storiesOf("GPT", module).add("GPT", () => { - return (); + return ; }); diff --git a/packages/gpt/gpt.test.js b/packages/gpt/gpt.test.js index f76ecbba18d..246630c6ad0 100644 --- a/packages/gpt/gpt.test.js +++ b/packages/gpt/gpt.test.js @@ -1,10 +1,19 @@ import "react-native"; import React from "react"; import GPT from "./gpt.web"; +import AdManager from "./ad-manager"; import renderer from "react-test-renderer"; it("renders correctly", () => { - const tree = renderer.create().toJSON(); + const adManager = new AdManager({ + networkId: "25436805", + adUnit: "d.thetimes.co.uk", + section: "article" + }); + + const tree = renderer + .create() + .toJSON(); expect(tree).toBeTruthy(); }); diff --git a/packages/gpt/gpt.web.js b/packages/gpt/gpt.web.js index 15fa4283467..ece7322c5fe 100644 --- a/packages/gpt/gpt.web.js +++ b/packages/gpt/gpt.web.js @@ -1,27 +1,24 @@ // TODO: this component should be moved to component library -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; -import AdManager from './ad-manager'; +import AdManager from "./ad-manager"; class GPT extends Component { - - componentDidMount () { - console.log('Component did mount', this.props) + componentDidMount() { + console.log("Component did mount", this.props); this.props.adManager.registerAd(this.props.code); } - componentWillUnmount () { - console.log('Component unmount') + componentWillUnmount() { + console.log("Component unmount"); this.props.adManager.unregisterAd(this.props.code); } - render () { + render() { const props = this.props; - return ( -
- ); + return
; } } diff --git a/packages/gpt/pbjs-manager.js b/packages/gpt/pbjs-manager.js index 130aade0b9d..744322915fc 100644 --- a/packages/gpt/pbjs-manager.js +++ b/packages/gpt/pbjs-manager.js @@ -1,17 +1,17 @@ -import { pbjs as config } from './config'; +import { pbjs as config } from "./config"; -function PbjsManager (options) { +function PbjsManager(options) { this._options = options; this.scriptSet = false; this.initialised = false; this.pbjs = null; } -PbjsManager.prototype.isReady = function isReady () { +PbjsManager.prototype.isReady = function isReady() { return this.initialised && this.scriptSet; }; -PbjsManager.prototype.loadScript = function loadScript () { +PbjsManager.prototype.loadScript = function loadScript() { // Check if script tag is already set if (this.scriptSet) return; @@ -21,19 +21,19 @@ PbjsManager.prototype.loadScript = function loadScript () { this.pbjs = window.pbjs; const d = document; - const pbs = d.createElement('script'); + const pbs = d.createElement("script"); pbs.async = true; // const pro = d.location.protocol; - pbs.type = 'text/javascript'; + pbs.type = "text/javascript"; // pbs.src = ((pro === 'https:') ? 'https' : 'http') + '://acdn.adnxs.com/prebid/not-for-prod/prebid.js'; - pbs.src = 'https://www.thetimes.co.uk/d/js/vendor/prebid.min-4812861170.js'; - const head = document.getElementsByTagName('head')[0]; + pbs.src = "https://www.thetimes.co.uk/d/js/vendor/prebid.min-4812861170.js"; + const head = document.getElementsByTagName("head")[0]; head.appendChild(pbs); this.scriptSet = true; }; -PbjsManager.prototype.setConfig = function setConfig (callback) { +PbjsManager.prototype.setConfig = function setConfig(callback) { if (this.initialised) return callback(); const pbjs = this.pbjs; @@ -43,40 +43,46 @@ PbjsManager.prototype.setConfig = function setConfig (callback) { pbjs.bidderSettings = { standard: { - adserverTargeting: [{ - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidder; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - if (bidResponse.cpm > options.maxBid) { - return options.maxBid.toFixed(2); + adserverTargeting: [ + { + key: "hb_bidder", + val: function(bidResponse) { + return bidResponse.bidder; } - if (bidResponse.cpm < options.bucketSize) { - return options.minPrice.toFixed(2); + }, + { + key: "hb_adid", + val: function(bidResponse) { + return bidResponse.adId; + } + }, + { + key: "hb_pb", + val: function(bidResponse) { + if (bidResponse.cpm > options.maxBid) { + return options.maxBid.toFixed(2); + } + if (bidResponse.cpm < options.bucketSize) { + return options.minPrice.toFixed(2); + } + return (bidResponse.cpm - + bidResponse.cpm % options.bucketSize).toFixed(2); + } + }, + { + key: "hb_size", + val: function(bidResponse) { + return bidResponse.size; } - return (bidResponse.cpm - (bidResponse.cpm % options.bucketSize)).toFixed(2); - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; } - }] + ] } }; callback(); }; -PbjsManager.prototype.init = function init (adUnits, callback) { +PbjsManager.prototype.init = function init(adUnits, callback) { this.pbjs.que.push(() => { console.log(adUnits); this.pbjs.addAdUnits(adUnits);