Skip to content

Commit

Permalink
Native: add custom data assets capability (#6220)
Browse files Browse the repository at this point in the history
Use `mediaTypes.native.ext: {}` special object to add/allow custom data. assets.
  • Loading branch information
osazos committed Feb 25, 2021
1 parent c2865ba commit 52f4813
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 35 deletions.
78 changes: 54 additions & 24 deletions src/native.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,30 +165,38 @@ export function getNativeTargeting(bid, bidReq) {
`nativeParams.sendTargetingKeys`
) !== false;

Object.keys(bid['native']).forEach(asset => {
if (asset !== 'adTemplate') {
const key = CONSTANTS.NATIVE_KEYS[asset];
let value = getAssetValue(bid['native'][asset]);

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

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

const assetSendTargetingKeys = deepAccess(
bidReq,
`nativeParams.${asset}.sendTargetingKeys`);

const sendTargeting = typeof assetSendTargetingKeys === 'boolean' ? assetSendTargetingKeys : globalSendTargetingKeys;

if (key && value && sendTargeting) {
keyValues[key] = value;
}
const nativeKeys = getNativeKeys(bidReq);

const flatBidNativeKeys = { ...bid.native, ...bid.native.ext };
delete flatBidNativeKeys.ext;

Object.keys(flatBidNativeKeys).forEach(asset => {
const key = nativeKeys[asset];
let value = getAssetValue(bid.native[asset]) || getAssetValue(deepAccess(bid, `native.ext.${asset}`));

if (asset === 'adTemplate' || !key || !value) {
return;
}

let sendPlaceholder = deepAccess(bidReq, `nativeParams.${asset}.sendId`);
if (typeof sendPlaceholder !== 'boolean') {
sendPlaceholder = deepAccess(bidReq, `nativeParams.ext.${asset}.sendId`);
}

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

let assetSendTargetingKeys = deepAccess(bidReq, `nativeParams.${asset}.sendTargetingKeys`)
if (typeof assetSendTargetingKeys !== 'boolean') {
assetSendTargetingKeys = deepAccess(bidReq, `nativeParams.ext.${asset}.sendTargetingKeys`);
}

const sendTargeting = typeof assetSendTargetingKeys === 'boolean' ? assetSendTargetingKeys : globalSendTargetingKeys;

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

Expand Down Expand Up @@ -234,6 +242,13 @@ export function getAllAssetsMessage(data, adObject) {
message.adTemplate = getAssetValue(adObject.native[key]);
} else if (key === 'rendererUrl' && adObject.native[key]) {
message.rendererUrl = getAssetValue(adObject.native[key]);
} else if (key === 'ext') {
Object.keys(adObject.native[key]).forEach(extKey => {
if (adObject.native[key][extKey]) {
const value = getAssetValue(adObject.native[key][extKey]);
message.assets.push({ key: extKey, value });
}
})
} else if (adObject.native[key] && CONSTANTS.NATIVE_KEYS.hasOwnProperty(key)) {
const value = getAssetValue(adObject.native[key]);

Expand All @@ -255,3 +270,18 @@ function getAssetValue(value) {

return value;
}

function getNativeKeys(bidReq) {
const extraNativeKeys = {}

if (deepAccess(bidReq, 'nativeParams.ext')) {
Object.keys(bidReq.nativeParams.ext).forEach(extKey => {
extraNativeKeys[extKey] = `hb_native_${extKey}`;
})
}

return {
...CONSTANTS.NATIVE_KEYS,
...extraNativeKeys
}
}
74 changes: 63 additions & 11 deletions test/spec/native_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const bid = {
clickUrl: 'https://www.link.example',
clickTrackers: ['https://tracker.example'],
impressionTrackers: ['https://impression.example'],
javascriptTrackers: '<script src=\"http://www.foobar.js\"></script>'
javascriptTrackers: '<script src=\"http://www.foobar.js\"></script>',
ext: {
foo: 'foo-value',
baz: 'baz-value'
}
}
};

Expand All @@ -36,7 +40,11 @@ const bidWithUndefinedFields = {
clickUrl: 'https://www.link.example',
clickTrackers: ['https://tracker.example'],
impressionTrackers: ['https://impression.example'],
javascriptTrackers: '<script src=\"http://www.foobar.js\"></script>'
javascriptTrackers: '<script src=\"http://www.foobar.js\"></script>',
ext: {
foo: 'foo-value',
baz: undefined
}
}
};

Expand All @@ -59,14 +67,21 @@ describe('native.js', function () {
expect(targeting[CONSTANTS.NATIVE_KEYS.title]).to.equal(bid.native.title);
expect(targeting[CONSTANTS.NATIVE_KEYS.body]).to.equal(bid.native.body);
expect(targeting[CONSTANTS.NATIVE_KEYS.clickUrl]).to.equal(bid.native.clickUrl);
expect(targeting.hb_native_foo).to.equal(bid.native.foo);
});

it('sends placeholders for configured assets', function () {
const bidRequest = {
mediaTypes: {
native: {
body: { sendId: true },
clickUrl: { sendId: true },
nativeParams: {
body: { sendId: true },
clickUrl: { sendId: true },
ext: {
foo: {
sendId: false
},
baz: {
sendId: true
}
}
}
};
Expand All @@ -75,15 +90,33 @@ describe('native.js', function () {
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');
expect(targeting.hb_native_foo).to.equal(bid.native.ext.foo);
expect(targeting.hb_native_baz).to.equal('hb_native_baz:123');
});

it('should only include native targeting keys with values', function () {
const targeting = getNativeTargeting(bidWithUndefinedFields);
const bidRequest = {
nativeParams: {
body: { sendId: true },
clickUrl: { sendId: true },
ext: {
foo: {
required: false
},
baz: {
required: false
}
}
}
};

const targeting = getNativeTargeting(bidWithUndefinedFields, bidRequest);

expect(Object.keys(targeting)).to.deep.equal([
CONSTANTS.NATIVE_KEYS.title,
CONSTANTS.NATIVE_KEYS.sponsoredBy,
CONSTANTS.NATIVE_KEYS.clickUrl
CONSTANTS.NATIVE_KEYS.clickUrl,
'hb_native_foo'
]);
});

Expand Down Expand Up @@ -138,6 +171,12 @@ describe('native.js', function () {
sponsoredBy: {
required: false,
sendTargetingKeys: false
},
ext: {
foo: {
required: false,
sendTargetingKeys: true
}
}
}

Expand All @@ -148,7 +187,8 @@ describe('native.js', function () {
CONSTANTS.NATIVE_KEYS.title,
CONSTANTS.NATIVE_KEYS.body,
CONSTANTS.NATIVE_KEYS.image,
CONSTANTS.NATIVE_KEYS.clickUrl
CONSTANTS.NATIVE_KEYS.clickUrl,
'hb_native_foo'
]);
});

Expand Down Expand Up @@ -265,7 +305,7 @@ describe('native.js', function () {

const message = getAllAssetsMessage(messageRequest, bid);

expect(message.assets.length).to.equal(7);
expect(message.assets.length).to.equal(9);
expect(message.assets).to.deep.include({
key: 'body',
value: bid.native.body
Expand Down Expand Up @@ -294,6 +334,14 @@ describe('native.js', function () {
key: 'sponsoredBy',
value: bid.native.sponsoredBy
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo
});
expect(message.assets).to.deep.include({
key: 'baz',
value: bid.native.ext.baz
});
});

it('creates native all asset message with only defined fields', function() {
Expand All @@ -305,7 +353,7 @@ describe('native.js', function () {

const message = getAllAssetsMessage(messageRequest, bidWithUndefinedFields);

expect(message.assets.length).to.equal(3);
expect(message.assets.length).to.equal(4);
expect(message.assets).to.deep.include({
key: 'clickUrl',
value: bid.native.clickUrl
Expand All @@ -318,6 +366,10 @@ describe('native.js', function () {
key: 'sponsoredBy',
value: bid.native.sponsoredBy
});
expect(message.assets).to.deep.include({
key: 'foo',
value: bid.native.ext.foo
});
});
});

Expand Down

0 comments on commit 52f4813

Please sign in to comment.