From 50e70f57c2eb94ed82d67fa84049cef7d9ca434d Mon Sep 17 00:00:00 2001 From: nkloeber Date: Tue, 23 May 2023 15:25:24 +0200 Subject: [PATCH 1/2] YieldlabBidAdapter updated native asset mapping for adserver responses for icons --- modules/yieldlabBidAdapter.js | 20 ++++++--- test/spec/modules/yieldlabBidAdapter_spec.js | 44 +++++++++++++++++++- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 31e9b35f178..68147ed6683 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -186,13 +186,21 @@ export const spec = { // there may be publishers still rely on it bidResponse.adUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}`; bidResponse.mediaType = NATIVE; - const nativeImageAssetObj = find(matchedBid.native.assets, asset => isMainImage(asset)); + const nativeIconAssetObj = find(matchedBid.native.assets, asset => isImageAssetOfType(asset, 1)); + const nativeImageAssetObj = find(matchedBid.native.assets, asset => isImageAssetOfType(asset, 3)); const nativeImageAsset = nativeImageAssetObj ? nativeImageAssetObj.img : { url: '', w: 0, h: 0 }; const nativeTitleAsset = find(matchedBid.native.assets, asset => hasValidProperty(asset, 'title')); const nativeBodyAsset = find(matchedBid.native.assets, asset => hasValidProperty(asset, 'data')); bidResponse.native = { title: nativeTitleAsset ? nativeTitleAsset.title.text : '', body: nativeBodyAsset ? nativeBodyAsset.data.value : '', + ...nativeIconAssetObj?.img && { + icon: { + url: nativeIconAssetObj.img.url, + width: nativeIconAssetObj.img.w, + height: nativeIconAssetObj.img.h, + }, + }, image: { url: nativeImageAsset.url, width: nativeImageAsset.w, @@ -517,14 +525,14 @@ function hasValidProperty(obj, propName) { } /** - * Checks if an asset object is a main image. - * A main image is defined as an image asset whose type value is 3. + * Checks if an asset object is of the given type. * * @param {Object} asset - The asset object to check. - * @returns {boolean} Returns true if the object has a property img.type with a value of 3, otherwise false. + * @param {number} type - The type number to compare. + * @returns {boolean} Returns true if the object has a property img.type with a value of the given type, otherwise false. */ -function isMainImage(asset) { - return asset?.img?.type === 3 +function isImageAssetOfType(asset, type) { + return asset?.img?.type === type } registerBidder(spec); diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 80537facd41..93c231c816b 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -200,6 +200,15 @@ const NATIVE_RESPONSE = Object.assign({}, RESPONSE, { value: 'Native body value', }, }, + { + id: 4, + img: { + url: 'https://localhost:8080/assets/favicon/favicon-16x16.png', + w: 16, + h: 16, + type: 1, + }, + }, ], imptrackers: [ 'http://localhost:8080/ve?d=ODE9ZSY2MTI1MjAzNjMzMzYxPXN0JjA0NWUwZDk0NTY5Yi05M2FiLWUwZTQtOWFjNy1hYWY0MzFiZj1kaXQmMj12', @@ -567,15 +576,24 @@ describe('yieldlabBidAdapter', () => { expect(result[0].native.image.url).to.equal('https://localhost:8080/yl-logo100x100.jpg'); expect(result[0].native.image.width).to.equal(100); expect(result[0].native.image.height).to.equal(100); + expect(result[0].native.icon.url).to.equal('https://localhost:8080/assets/favicon/favicon-16x16.png'); + expect(result[0].native.icon.width).to.equal(16); + expect(result[0].native.icon.height).to.equal(16); expect(result[0].native.clickUrl).to.equal('https://www.yieldlab.de'); expect(result[0].native.impressionTrackers.length).to.equal(3); - expect(result[0].native.assets.length).to.equal(3); + expect(result[0].native.assets.length).to.equal(4); const titleAsset = result[0].native.assets.find(asset => 'title' in asset); - const imageAsset = result[0].native.assets.find(asset => 'img' in asset); + const imageAsset = result[0].native.assets.find((asset) => { + return asset?.img?.type === 3; + }); + const iconAsset = result[0].native.assets.find((asset) => { + return asset?.img?.type === 1; + }); const bodyAsset = result[0].native.assets.find(asset => 'data' in asset); expect(titleAsset).to.exist.and.to.have.nested.property('id', 1) expect(imageAsset).to.exist.and.to.have.nested.property('id', 2) expect(bodyAsset).to.exist.and.to.have.nested.property('id', 3) + expect(iconAsset).to.exist.and.to.have.nested.property('id', 4) }); it('should add adUrl and default native assets when type is Native', () => { @@ -601,6 +619,28 @@ describe('yieldlabBidAdapter', () => { expect(result[0].native.image.height).to.equal(0); }); + it('should not add icon if not present in the native response', () => { + const NATIVE_RESPONSE_WITHOUT_ICON = Object.assign({}, NATIVE_RESPONSE, { + native: { + link: { + url: 'https://www.yieldlab.de', + }, + assets: [ + { + id: 1, + title: { + text: 'This is a great headline', + } + } + ], + imptrackers: [], + }, + }); + const result = spec.interpretResponse({body: [NATIVE_RESPONSE_WITHOUT_ICON]}, {validBidRequests: [NATIVE_REQUEST()], queryParams: REQPARAMS}); + expect(result[0].native.hasOwnProperty('icon')).to.be.false; + expect(result[0].native.title).to.equal('This is a great headline'); + }); + it('should append gdpr parameters to vastUrl', () => { const result = spec.interpretResponse({body: [VIDEO_RESPONSE]}, {validBidRequests: [VIDEO_REQUEST()], queryParams: REQPARAMS_GDPR}); From 4c9e9101501e797d114d1b22bd9746f4a3ee139c Mon Sep 17 00:00:00 2001 From: nkloeber Date: Wed, 24 May 2023 12:26:13 +0200 Subject: [PATCH 2/2] YieldlabBidAdapter removed magic numbers and improved image asset filtering --- modules/yieldlabBidAdapter.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 68147ed6683..b0136cd21ea 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -12,6 +12,8 @@ const CURRENCY_CODE = 'EUR'; const OUTSTREAMPLAYER_URL = 'https://ad.adition.com/dynamic.ad?a=o193092&ma_loadEvent=ma-start-event'; const GVLID = 70; const DIMENSION_SIGN = 'x'; +const IMG_TYPE_ICON = 1; +const IMG_TYPE_MAIN = 3; export const spec = { code: BIDDER_CODE, @@ -183,14 +185,15 @@ export const spec = { } if (isNative(bidRequest, adType)) { - // there may be publishers still rely on it + const { native } = matchedBid; + const { assets } = native; bidResponse.adUrl = `${ENDPOINT}/d/${matchedBid.id}/${bidRequest.params.supplyId}/?ts=${timestamp}${extId}${gdprApplies}${gdprConsent}${pvId}`; bidResponse.mediaType = NATIVE; - const nativeIconAssetObj = find(matchedBid.native.assets, asset => isImageAssetOfType(asset, 1)); - const nativeImageAssetObj = find(matchedBid.native.assets, asset => isImageAssetOfType(asset, 3)); + const nativeIconAssetObj = find(assets, isImageAssetOfType(IMG_TYPE_ICON)); + const nativeImageAssetObj = find(assets, isImageAssetOfType(IMG_TYPE_MAIN)); const nativeImageAsset = nativeImageAssetObj ? nativeImageAssetObj.img : { url: '', w: 0, h: 0 }; - const nativeTitleAsset = find(matchedBid.native.assets, asset => hasValidProperty(asset, 'title')); - const nativeBodyAsset = find(matchedBid.native.assets, asset => hasValidProperty(asset, 'data')); + const nativeTitleAsset = find(assets, asset => hasValidProperty(asset, 'title')); + const nativeBodyAsset = find(assets, asset => hasValidProperty(asset, 'data')); bidResponse.native = { title: nativeTitleAsset ? nativeTitleAsset.title.text : '', body: nativeBodyAsset ? nativeBodyAsset.data.value : '', @@ -206,9 +209,9 @@ export const spec = { width: nativeImageAsset.w, height: nativeImageAsset.h, }, - clickUrl: matchedBid.native.link.url, - impressionTrackers: matchedBid.native.imptrackers, - assets: matchedBid.native.assets, + clickUrl: native.link.url, + impressionTrackers: native.imptrackers, + assets: assets, }; } @@ -525,14 +528,12 @@ function hasValidProperty(obj, propName) { } /** - * Checks if an asset object is of the given type. - * - * @param {Object} asset - The asset object to check. - * @param {number} type - The type number to compare. - * @returns {boolean} Returns true if the object has a property img.type with a value of the given type, otherwise false. + * Returns a filtering function for image assets based on type. + * @param {number} type - The desired asset type to filter for i.e. IMG_TYPE_ICON = 1, IMG_TYPE_MAIN = 3 + * @returns {function} - A filtering function that accepts an asset and checks if its img.type matches the desired type. */ -function isImageAssetOfType(asset, type) { - return asset?.img?.type === type +function isImageAssetOfType(type) { + return asset => asset?.img?.type === type; } registerBidder(spec);