Skip to content

Commit 99977a9

Browse files
matthewlanejsnellbaker
authored andcommitted
Send placeholders for configured native assets (prebid#3573)
* Send placeholders for configured native assets * Post native assets on replacement request * Update names * Change config name
1 parent fcbaa4c commit 99977a9

File tree

5 files changed

+95
-7
lines changed

5 files changed

+95
-7
lines changed

src/auction.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) {
488488
// if there is any key value pairs to map do here
489489
var keyValues;
490490
if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) {
491-
keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject);
491+
keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq);
492492
}
493493

494494
// use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs
@@ -563,7 +563,7 @@ export function getStandardBidderSettings(mediaType) {
563563
return bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD];
564564
}
565565

566-
export function getKeyValueTargetingPairs(bidderCode, custBidObj) {
566+
export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
567567
if (!custBidObj) {
568568
return {};
569569
}
@@ -586,7 +586,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) {
586586

587587
// set native key value targeting
588588
if (custBidObj['native']) {
589-
keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj));
589+
keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj, bidReq));
590590
}
591591

592592
return keyValues;

src/native.js

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deepAccess, getBidRequest, logError, triggerPixel, insertHtmlIntoIframe } from './utils';
1+
import { deepAccess, getBidRequest, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils';
22
import includes from 'core-js/library/fn/array/includes';
33

44
const CONSTANTS = require('./constants.json');
@@ -151,7 +151,7 @@ export function fireNativeTrackers(message, adObject) {
151151
* @param {Object} bid
152152
* @return {Object} targeting
153153
*/
154-
export function getNativeTargeting(bid) {
154+
export function getNativeTargeting(bid, bidReq) {
155155
let keyValues = {};
156156

157157
Object.keys(bid['native']).forEach(asset => {
@@ -163,10 +163,41 @@ export function getNativeTargeting(bid) {
163163
value = value.url;
164164
}
165165

166+
const sendPlaceholder = deepAccess(
167+
bidReq,
168+
`mediaTypes.native.${asset}.sendId`
169+
);
170+
171+
if (sendPlaceholder) {
172+
const placeholder = `${key}:${bid.adId}`;
173+
value = placeholder;
174+
}
175+
166176
if (key && value) {
167177
keyValues[key] = value;
168178
}
169179
});
170180

171181
return keyValues;
172182
}
183+
184+
/**
185+
* Constructs a message object containing asset values for each of the
186+
* requested data keys.
187+
*/
188+
export function getAssetMessage(data, adObject) {
189+
const message = {
190+
message: 'assetResponse',
191+
adId: data.adId,
192+
assets: [],
193+
};
194+
195+
data.assets.forEach(asset => {
196+
const key = getKeyByValue(CONSTANTS.NATIVE_KEYS, asset);
197+
const value = adObject.native[key];
198+
199+
message.assets.push({ key, value });
200+
});
201+
202+
return message;
203+
}

src/secureCreatives.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import events from './events';
7-
import { fireNativeTrackers } from './native';
7+
import { fireNativeTrackers, getAssetMessage } from './native';
88
import { EVENTS } from './constants';
99
import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils';
1010
import { auctionManager } from './auctionManager';
@@ -46,6 +46,12 @@ function receiveMessage(ev) {
4646
// adId: '%%PATTERN:hb_adid%%'
4747
// }), '*');
4848
if (data.message === 'Prebid Native') {
49+
if (data.action === 'assetRequest') {
50+
const message = getAssetMessage(data, adObject);
51+
ev.source.postMessage(JSON.stringify(message), ev.origin);
52+
return;
53+
}
54+
4955
fireNativeTrackers(data, adObject);
5056
auctionManager.addWinningBid(adObject);
5157
events.emit(BID_WON, adObject);

src/utils.js

+13
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,19 @@ export function getValue(obj, key) {
783783
return obj[key];
784784
}
785785

786+
/**
787+
* Get the key of an object for a given value
788+
*/
789+
export function getKeyByValue(obj, value) {
790+
for (let prop in obj) {
791+
if (obj.hasOwnProperty(prop)) {
792+
if (obj[prop] === value) {
793+
return prop;
794+
}
795+
}
796+
}
797+
}
798+
786799
export function getBidderCodes(adUnits = $$PREBID_GLOBAL$$.adUnits) {
787800
// this could memoize adUnits
788801
return adUnits.map(unit => unit.bids.map(bid => bid.bidder)

test/spec/native_spec.js

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { expect } from 'chai';
2-
import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native';
2+
import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid, getAssetMessage } from 'src/native';
33
import CONSTANTS from 'src/constants.json';
44
const utils = require('src/utils');
55

66
const bid = {
7+
adId: '123',
78
native: {
89
title: 'Native Creative',
910
body: 'Cool description great stuff',
@@ -50,6 +51,22 @@ describe('native.js', function () {
5051
expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl);
5152
});
5253

54+
it('sends placeholders for configured assets', function () {
55+
const bidRequest = {
56+
mediaTypes: {
57+
native: {
58+
body: { sendId: true },
59+
clickUrl: { sendId: true },
60+
}
61+
}
62+
};
63+
const targeting = getNativeTargeting(bid, bidRequest);
64+
65+
expect(targeting[CONSTANTS.NATIVE_KEYS.title]).to.equal(bid.native.title);
66+
expect(targeting[CONSTANTS.NATIVE_KEYS.body]).to.equal('hb_native_body:123');
67+
expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal('hb_native_linkurl:123');
68+
});
69+
5370
it('should only include native targeting keys with values', function () {
5471
const targeting = getNativeTargeting(bidWithUndefinedFields);
5572

@@ -72,6 +89,27 @@ describe('native.js', function () {
7289
sinon.assert.calledOnce(triggerPixelStub);
7390
sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]);
7491
});
92+
93+
it('creates native asset message', function() {
94+
const messageRequest = {
95+
message: 'Prebid Native',
96+
action: 'assetRequest',
97+
adId: '123',
98+
assets: ['hb_native_body', 'hb_native_linkurl'],
99+
};
100+
101+
const message = getAssetMessage(messageRequest, bid);
102+
103+
expect(message.assets.length).to.equal(2);
104+
expect(message.assets).to.deep.include({
105+
key: 'body',
106+
value: bid.native.body
107+
});
108+
expect(message.assets).to.deep.include({
109+
key: 'clickUrl',
110+
value: bid.native.clickUrl
111+
});
112+
});
75113
});
76114

77115
describe('validate native', function () {

0 commit comments

Comments
 (0)