prebid-universal-creative 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +3 -3
- package/.github/workflows/issue_tracker.yml +89 -0
- package/README.md +1 -1
- package/browsers.json +17 -33
- package/dist/creative.js +3 -3
- package/dist/creative.max.js +516 -420
- package/dist/native-render.js +3 -3
- package/dist/native-trk.js +3 -3
- package/dist/prebid-mobile-rewarded-vast.xml +22 -0
- package/dist/uid.js +2 -2
- package/gulpfile.js +9 -4
- package/package.json +12 -7
- package/src/messaging.js +43 -0
- package/src/nativeAssetManager.js +185 -77
- package/src/nativeORTBTrackerManager.js +32 -0
- package/src/nativeRenderManager.js +10 -12
- package/src/nativeTrackerManager.js +18 -7
- package/src/renderingManager.js +58 -38
- package/src/utils.js +3 -0
- package/static/prebid-mobile-rewarded-vast.xml +22 -0
- package/test/helpers/mocks.js +7 -3
- package/test/spec/messaging_spec.js +64 -0
- package/test/spec/nativeAssetManager_spec.js +493 -347
- package/test/spec/nativeORTBTrackerManager_spec.js +76 -0
- package/test/spec/nativeRenderManager_spec.js +18 -1
- package/test/spec/renderingManager_spec.js +163 -73
package/src/renderingManager.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import * as utils from './utils';
|
2
2
|
import * as domHelper from './domHelper';
|
3
3
|
import {triggerPixel} from './utils';
|
4
|
+
import {prebidMessenger} from './messaging.js';
|
4
5
|
|
5
6
|
const DEFAULT_CACHE_HOST = 'prebid.adnxs.com';
|
6
7
|
const DEFAULT_CACHE_PATH = '/pbc/v1/cache';
|
@@ -70,10 +71,9 @@ export function newRenderingManager(win, environment) {
|
|
70
71
|
*/
|
71
72
|
function renderCrossDomain(adId, pubAdServerDomain = '', pubUrl) {
|
72
73
|
let windowLocation = win.location;
|
73
|
-
let parsedUrl = utils.parseUrl(pubUrl);
|
74
|
-
let publisherDomain = parsedUrl.protocol + '://' + parsedUrl.host;
|
75
74
|
let adServerDomain = pubAdServerDomain || win.location.hostname;
|
76
75
|
let fullAdServerDomain = windowLocation.protocol + '//' + adServerDomain;
|
76
|
+
const sendMessage = prebidMessenger(pubUrl, win);
|
77
77
|
|
78
78
|
function renderAd(ev) {
|
79
79
|
let key = ev.message ? 'message' : 'data';
|
@@ -84,52 +84,72 @@ export function newRenderingManager(win, environment) {
|
|
84
84
|
return;
|
85
85
|
}
|
86
86
|
|
87
|
-
let origin = ev.origin || ev.originalEvent.origin;
|
88
87
|
if (adObject.message && adObject.message === 'Prebid Response' &&
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
88
|
+
adObject.adId === adId) {
|
89
|
+
try {
|
90
|
+
let body = win.document.body;
|
91
|
+
let ad = adObject.ad;
|
92
|
+
let url = adObject.adUrl;
|
93
|
+
let width = adObject.width;
|
94
|
+
let height = adObject.height;
|
95
|
+
|
96
|
+
if (adObject.mediaType === 'video') {
|
97
|
+
signalRenderResult(false, {
|
98
|
+
reason: 'preventWritingOnMainDocument',
|
99
|
+
message: `Cannot render video ad ${adId}`
|
100
|
+
});
|
101
|
+
console.log('Error trying to write ad.');
|
102
|
+
} else if (ad) {
|
103
|
+
const iframe = domHelper.getEmptyIframe(adObject.height, adObject.width);
|
104
|
+
body.appendChild(iframe);
|
105
|
+
iframe.contentDocument.open();
|
106
|
+
iframe.contentDocument.write(ad);
|
107
|
+
iframe.contentDocument.close();
|
108
|
+
signalRenderResult(true);
|
109
|
+
} else if (url) {
|
110
|
+
const iframe = domHelper.getEmptyIframe(height, width);
|
111
|
+
iframe.style.display = 'inline';
|
112
|
+
iframe.style.overflow = 'hidden';
|
113
|
+
iframe.src = url;
|
114
|
+
|
115
|
+
domHelper.insertElement(iframe, document, 'body');
|
116
|
+
signalRenderResult(true);
|
117
|
+
} else {
|
118
|
+
signalRenderResult(false, {
|
119
|
+
reason: 'noAd',
|
120
|
+
message: `No ad for ${adId}`
|
121
|
+
});
|
122
|
+
console.log(`Error trying to write ad. No ad markup or adUrl for ${adId}`);
|
123
|
+
}
|
124
|
+
} catch (e) {
|
125
|
+
signalRenderResult(false, {reason: "exception", message: e.message});
|
126
|
+
console.log(`Error in rendering ad`, e);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
function signalRenderResult(success, {reason, message} = {}) {
|
131
|
+
const payload = {
|
132
|
+
message: 'Prebid Event',
|
133
|
+
adId,
|
134
|
+
event: success ? 'adRenderSucceeded' : 'adRenderFailed',
|
135
|
+
}
|
136
|
+
if (!success) {
|
137
|
+
payload.info = {reason, message};
|
115
138
|
}
|
139
|
+
sendMessage(payload);
|
116
140
|
}
|
117
141
|
}
|
118
142
|
|
143
|
+
|
119
144
|
function requestAdFromPrebid() {
|
120
|
-
let message =
|
145
|
+
let message = {
|
121
146
|
message: 'Prebid Request',
|
122
147
|
adId: adId,
|
123
148
|
adServerDomain: fullAdServerDomain
|
124
|
-
}
|
125
|
-
|
126
|
-
}
|
127
|
-
|
128
|
-
function listenAdFromPrebid() {
|
129
|
-
win.addEventListener('message', renderAd, false);
|
149
|
+
}
|
150
|
+
sendMessage(message, renderAd);
|
130
151
|
}
|
131
152
|
|
132
|
-
listenAdFromPrebid();
|
133
153
|
requestAdFromPrebid();
|
134
154
|
}
|
135
155
|
|
@@ -144,7 +164,7 @@ export function newRenderingManager(win, environment) {
|
|
144
164
|
|
145
165
|
return `https://${host}${path}`;
|
146
166
|
}
|
147
|
-
|
167
|
+
|
148
168
|
/**
|
149
169
|
* update iframe by using size string to resize
|
150
170
|
* @param {string} size
|
package/src/utils.js
CHANGED
@@ -32,6 +32,9 @@ export function writeAdUrl(adUrl, width, height) {
|
|
32
32
|
}
|
33
33
|
|
34
34
|
export function writeAdHtml(markup) {
|
35
|
+
// remove <?xml> and <!doctype> tags
|
36
|
+
// https://github.com/prebid/prebid-universal-creative/issues/134
|
37
|
+
markup = markup.replace(/\<(\?xml|(\!DOCTYPE[^\>\[]+(\[[^\]]+)?))+[^>]+\>/g, '');
|
35
38
|
postscribe(document.body, markup, {
|
36
39
|
error: console.error
|
37
40
|
});
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<VAST version="2.0">
|
3
|
+
<Ad id="PrebidMobileAppEvent">
|
4
|
+
<InLine>
|
5
|
+
<AdSystem version="1.0">Prebid org</AdSystem>
|
6
|
+
<AdTitle>PrebidAppEvent</AdTitle>
|
7
|
+
<Impression><![CDATA[https://test.url.com]]></Impression>
|
8
|
+
<Creatives>
|
9
|
+
<Creative>
|
10
|
+
<Linear>
|
11
|
+
<Duration>00:00:02</Duration>
|
12
|
+
<MediaFiles>
|
13
|
+
<MediaFile delivery="progressive" height="540" id="539733616" type="video/mp4" width="960">
|
14
|
+
<![CDATA[https://test.url.com/gam_rewarded.mp4]]>
|
15
|
+
</MediaFile>
|
16
|
+
</MediaFiles>
|
17
|
+
</Linear>
|
18
|
+
</Creative>
|
19
|
+
</Creatives>
|
20
|
+
</InLine>
|
21
|
+
</Ad>
|
22
|
+
</VAST>
|
package/test/helpers/mocks.js
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
export const mocks = {
|
2
2
|
createFakeWindow: function (href) {
|
3
3
|
return {
|
4
|
+
addEventListener: function () {},
|
5
|
+
removeEventListener: function () {},
|
4
6
|
document: {
|
5
7
|
head: {},
|
6
|
-
body: {
|
8
|
+
body: {
|
9
|
+
style: {}
|
10
|
+
}
|
7
11
|
},
|
8
12
|
location: {
|
9
13
|
href: href,
|
10
14
|
},
|
11
15
|
parent: {},
|
12
|
-
top: {}
|
16
|
+
top: {},
|
13
17
|
};
|
14
18
|
}
|
15
|
-
}
|
19
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import {mocks} from '../helpers/mocks.js';
|
2
|
+
import {prebidMessenger} from '../../src/messaging.js';
|
3
|
+
|
4
|
+
describe('prebidMessenger',() => {
|
5
|
+
let win;
|
6
|
+
beforeEach(() => {
|
7
|
+
win = Object.assign(mocks.createFakeWindow(), {
|
8
|
+
parent: {
|
9
|
+
postMessage: sinon.spy()
|
10
|
+
}
|
11
|
+
});
|
12
|
+
})
|
13
|
+
describe('when publisher URL is unavailable', () => {
|
14
|
+
let sendMessage;
|
15
|
+
|
16
|
+
beforeEach(() => {
|
17
|
+
sendMessage = prebidMessenger(null, win);
|
18
|
+
});
|
19
|
+
|
20
|
+
it('should throw', () => {
|
21
|
+
expect(() => sendMessage('test')).to.throw();
|
22
|
+
})
|
23
|
+
});
|
24
|
+
|
25
|
+
describe('when publisher URL is available', () => {
|
26
|
+
const URL = 'https://www.publisher.com/page.html';
|
27
|
+
const ORIGIN = 'https://www.publisher.com'
|
28
|
+
let sendMessage;
|
29
|
+
let callback, handler;
|
30
|
+
|
31
|
+
beforeEach(() => {
|
32
|
+
win.addEventListener = function (_, h) {
|
33
|
+
handler = h;
|
34
|
+
}
|
35
|
+
win.removeEventListener = sinon.spy();
|
36
|
+
sendMessage = prebidMessenger(URL, win);
|
37
|
+
callback = sinon.spy();
|
38
|
+
})
|
39
|
+
|
40
|
+
it('should use origin for postMessage', () => {
|
41
|
+
sendMessage('test');
|
42
|
+
sinon.assert.calledWith(win.parent.postMessage, JSON.stringify('test'), ORIGIN);
|
43
|
+
});
|
44
|
+
|
45
|
+
it('should not run callback on response if origin does not mach', ()=> {
|
46
|
+
sendMessage('test', callback);
|
47
|
+
handler({origin: 'different'});
|
48
|
+
expect(callback.called).to.be.false;
|
49
|
+
});
|
50
|
+
|
51
|
+
it('should run callback on response if origin does match', () => {
|
52
|
+
sendMessage('test', callback);
|
53
|
+
const ev = {origin: ORIGIN, data: 'stuff'};
|
54
|
+
handler(ev);
|
55
|
+
sinon.assert.calledWith(callback, ev);
|
56
|
+
});
|
57
|
+
|
58
|
+
it('should remove window listener when canceled', () => {
|
59
|
+
sendMessage('test', callback)();
|
60
|
+
expect(win.removeEventListener.called).to.be.true;
|
61
|
+
})
|
62
|
+
|
63
|
+
});
|
64
|
+
})
|