Skip to content

Commit

Permalink
Prebid 9: Deprecate native sendTargetingKeys/types, validate asset IDs (
Browse files Browse the repository at this point in the history
#11481)

* Validate native ortb.asset.id

* deprecate native sendTargetingKeys / types

* undo package-lock changes
  • Loading branch information
dgirardi authored May 15, 2024
1 parent 183515d commit a749d55
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 11 deletions.
21 changes: 21 additions & 0 deletions src/prebid.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,38 @@ function validateVideoMediaType(adUnit) {
}

function validateNativeMediaType(adUnit) {
function err(msg) {
logError(`Error in adUnit "${adUnit.code}": ${msg}. Removing native request from ad unit`, adUnit);
delete validatedAdUnit.mediaTypes.native;
return validatedAdUnit;
}
function checkDeprecated(onDeprecated) {
for (const key of ['sendTargetingKeys', 'types']) {
if (native.hasOwnProperty(key)) {
const res = onDeprecated(key);
if (res) return res;
}
}
}
const validatedAdUnit = deepClone(adUnit);
const native = validatedAdUnit.mediaTypes.native;
// if native assets are specified in OpenRTB format, remove legacy assets and print a warn.
if (native.ortb) {
if (native.ortb.assets?.some(asset => !isNumber(asset.id) || asset.id < 0 || asset.id % 1 !== 0)) {
return err('native asset ID must be a nonnegative integer');
}
if (checkDeprecated(key => err(`ORTB native requests cannot specify "${key}"`))) {
return validatedAdUnit;
}
const legacyNativeKeys = Object.keys(NATIVE_KEYS).filter(key => NATIVE_KEYS[key].includes('hb_native_'));
const nativeKeys = Object.keys(native);
const intersection = nativeKeys.filter(nativeKey => legacyNativeKeys.includes(nativeKey));
if (intersection.length > 0) {
logError(`when using native OpenRTB format, you cannot use legacy native properties. Deleting ${intersection} keys from request.`);
intersection.forEach(legacyKey => delete validatedAdUnit.mediaTypes.native[legacyKey]);
}
} else {
checkDeprecated(key => `mediaTypes.native.${key} is deprecated, consider using native ORTB instead`, adUnit);
}
if (native.image && native.image.sizes && !Array.isArray(native.image.sizes)) {
logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.');
Expand Down
67 changes: 56 additions & 11 deletions test/spec/unit/pbjs_api_spec.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import {
createBidReceived,
getAdServerTargeting,
getAdUnits,
getBidRequests,
getBidResponses,
getBidResponsesFromAPI,
getTargetingKeys,
getTargetingKeysBidLandscape,
getAdUnits,
createBidReceived
getTargetingKeysBidLandscape
} from 'test/fixtures/fixtures.js';
import { auctionManager, newAuctionManager } from 'src/auctionManager.js';
import { targeting, newTargeting, filters } from 'src/targeting.js';
import { config as configObj } from 'src/config.js';
import {auctionManager, newAuctionManager} from 'src/auctionManager.js';
import {filters, newTargeting, targeting} from 'src/targeting.js';
import {config as configObj} from 'src/config.js';
import * as ajaxLib from 'src/ajax.js';
import * as auctionModule from 'src/auction.js';
import { registerBidder } from 'src/adapters/bidderFactory.js';
import {resizeRemoteCreative} from 'src/secureCreatives.js';
import {resetAuctionState} from 'src/auction.js';
import {registerBidder} from 'src/adapters/bidderFactory.js';
import {find} from 'src/polyfill.js';
import * as pbjsModule from 'src/prebid.js';
import $$PREBID_GLOBAL$$ from 'src/prebid.js';
import {hook} from '../../../src/hook.js';
import {reset as resetDebugging} from '../../../src/debugging.js';
import $$PREBID_GLOBAL$$ from 'src/prebid.js';
import {resetAuctionState} from 'src/auction.js';
import {stubAuctionIndex} from '../../helpers/indexStub.js';
import {createBid} from '../../../src/bidfactory.js';
import {enrichFPD} from '../../../src/fpd/enrichment.js';
import {mockFpdEnrichments} from '../../helpers/fpd.js';
import {generateUUID} from '../../../src/utils.js';
import {getCreativeRenderer} from '../../../src/creativeRenderers.js';
import { BID_STATUS, EVENTS, GRANULARITY_OPTIONS, TARGETING_KEYS } from 'src/constants.js';
import {BID_STATUS, EVENTS, GRANULARITY_OPTIONS, TARGETING_KEYS} from 'src/constants.js';

var assert = require('chai').assert;
var expect = require('chai').expect;
Expand Down Expand Up @@ -2475,6 +2474,52 @@ describe('Unit: Prebid Module', function () {
}
});

if (FEATURES.NATIVE) {
Object.entries({
missing: {},
negative: {id: -1},
'not an integer': {id: 1.23},
NaN: {id: 'garbage'}
}).forEach(([t, props]) => {
it(`should reject native ortb when asset ID is ${t}`, () => {
const adUnit = {
code: 'au',
mediaTypes: {
native: {
ortb: {
assets: [props]
}
}
},
bids: [{bidder: 'appnexus'}]
};
$$PREBID_GLOBAL$$.requestBids({
adUnits: [adUnit]
});
expect(auctionArgs.adUnits[0].bids.length).to.equal(0);
});
});

['sendTargetingKeys', 'types'].forEach(key => {
it(`should reject native that includes both ortb and ${key}`, () => {
const adUnit = {
code: 'au',
mediaTypes: {
native: {
ortb: {},
[key]: {}
}
},
bids: [{bidder: 'appnexus'}]
};
$$PREBID_GLOBAL$$.requestBids({
adUnits: [adUnit]
});
expect(auctionArgs.adUnits[0].bids.length).to.equal(0);
})
});
}

it('should throw error message and remove adUnit if adUnit.bids is not defined correctly', function () {
const adUnits = [{
code: 'ad-unit-1',
Expand Down

0 comments on commit a749d55

Please sign in to comment.