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

Send placeholders for configured native assets #3573

Merged
merged 4 commits into from
Feb 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/auction.js
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) {
// if there is any key value pairs to map do here
var keyValues;
if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) {
keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject);
keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq);
}

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

export function getKeyValueTargetingPairs(bidderCode, custBidObj) {
export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
if (!custBidObj) {
return {};
}
Expand All @@ -586,7 +586,7 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj) {

// set native key value targeting
if (custBidObj['native']) {
keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj));
keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj, bidReq));
}

return keyValues;
Expand Down
35 changes: 33 additions & 2 deletions src/native.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deepAccess, getBidRequest, logError, triggerPixel, insertHtmlIntoIframe } from './utils';
import { deepAccess, getBidRequest, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils';
import includes from 'core-js/library/fn/array/includes';

const CONSTANTS = require('./constants.json');
Expand Down Expand Up @@ -151,7 +151,7 @@ export function fireNativeTrackers(message, adObject) {
* @param {Object} bid
* @return {Object} targeting
*/
export function getNativeTargeting(bid) {
export function getNativeTargeting(bid, bidReq) {
let keyValues = {};

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

const sendPlaceholder = deepAccess(
bidReq,
`mediaTypes.native.${asset}.sendId`
);

if (sendPlaceholder) {
const placeholder = `${key}:${bid.adId}`;
value = placeholder;
}

if (key && value) {
keyValues[key] = value;
}
});

return keyValues;
}

/**
* Constructs a message object containing asset values for each of the
* requested data keys.
*/
export function getAssetMessage(data, adObject) {
const message = {
message: 'assetResponse',
adId: data.adId,
assets: [],
};

data.assets.forEach(asset => {
const key = getKeyByValue(CONSTANTS.NATIVE_KEYS, asset);
const value = adObject.native[key];

message.assets.push({ key, value });
});

return message;
}
8 changes: 7 additions & 1 deletion src/secureCreatives.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import events from './events';
import { fireNativeTrackers } from './native';
import { fireNativeTrackers, getAssetMessage } from './native';
import { EVENTS } from './constants';
import { isSlotMatchingAdUnitCode, logWarn, replaceAuctionPrice } from './utils';
import { auctionManager } from './auctionManager';
Expand Down Expand Up @@ -46,6 +46,12 @@ function receiveMessage(ev) {
// adId: '%%PATTERN:hb_adid%%'
// }), '*');
if (data.message === 'Prebid Native') {
if (data.action === 'assetRequest') {
const message = getAssetMessage(data, adObject);
ev.source.postMessage(JSON.stringify(message), ev.origin);
return;
}

fireNativeTrackers(data, adObject);
auctionManager.addWinningBid(adObject);
events.emit(BID_WON, adObject);
Expand Down
13 changes: 13 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,19 @@ export function getValue(obj, key) {
return obj[key];
}

/**
* Get the key of an object for a given value
*/
export function getKeyByValue(obj, value) {
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (obj[prop] === value) {
return prop;
}
}
}
}

export function getBidderCodes(adUnits = $$PREBID_GLOBAL$$.adUnits) {
// this could memoize adUnits
return adUnits.map(unit => unit.bids.map(bid => bid.bidder)
Expand Down
40 changes: 39 additions & 1 deletion test/spec/native_spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { expect } from 'chai';
import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native';
import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid, getAssetMessage } from 'src/native';
import CONSTANTS from 'src/constants.json';
const utils = require('src/utils');

const bid = {
adId: '123',
native: {
title: 'Native Creative',
body: 'Cool description great stuff',
Expand Down Expand Up @@ -50,6 +51,22 @@ describe('native.js', function () {
expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl);
});

it('sends placeholders for configured assets', function () {
const bidRequest = {
mediaTypes: {
native: {
body: { sendId: true },
clickUrl: { sendId: true },
}
}
};
const targeting = getNativeTargeting(bid, bidRequest);

expect(targeting[CONSTANTS.NATIVE_KEYS.title]).to.equal(bid.native.title);
expect(targeting[CONSTANTS.NATIVE_KEYS.body]).to.equal('hb_native_body:123');
expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal('hb_native_linkurl:123');
});

it('should only include native targeting keys with values', function () {
const targeting = getNativeTargeting(bidWithUndefinedFields);

Expand All @@ -72,6 +89,27 @@ describe('native.js', function () {
sinon.assert.calledOnce(triggerPixelStub);
sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]);
});

it('creates native asset message', function() {
const messageRequest = {
message: 'Prebid Native',
action: 'assetRequest',
adId: '123',
assets: ['hb_native_body', 'hb_native_linkurl'],
};

const message = getAssetMessage(messageRequest, bid);

expect(message.assets.length).to.equal(2);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body
});
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl
});
});
});

describe('validate native', function () {
Expand Down