From 478dc6bff9096f813838002ff4bb1b7b85113aa9 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 7 Feb 2022 12:18:28 +0200 Subject: [PATCH 01/30] create taboola adapter --- modules/taboolaBidAdapter.js | 153 +++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 modules/taboolaBidAdapter.js diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js new file mode 100644 index 00000000000..c9019a8e1e4 --- /dev/null +++ b/modules/taboolaBidAdapter.js @@ -0,0 +1,153 @@ +// jshint esversion: 6, es3: false, node: true +'use strict'; + +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER} from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'taboola'; +const GVLID = 42; +const CURRENCY = 'USD'; +const END_POINT_URL = 'http://taboolahb.bidder.taboolasyndication.com' + +export const spec = { + supportedMediaTypes: [BANNER], + gvlid: GVLID, + code: BIDDER_CODE, + isBidRequestValid: (bidRequest) => { + return !!(bidRequest.sizes && + bidRequest.params && + bidRequest.params.publisherId && + bidRequest.params.tagId); + }, + getUserSyncs: (syncOptions, responses, gdprConsent, uspConsent) => { + return []; + }, + buildRequests: (validBidRequests, bidderRequest) => { + const [bidRequest] = validBidRequests; + const {bcat = [], badv = [], publisherId} = bidRequest.params; + const site = getSiteProperties(bidRequest.params, bidderRequest.refererInfo.referer); + const device = {ua: navigator.userAgent}; + const timeout = bidderRequest.timeout; + const imps = getImps(validBidRequests); + + const request = { + id: bidderRequest.auctionId, + imp: imps, + site, + device, + source: {fd: 1}, + tmax: timeout, + bcat: bcat, + badv: badv + }; + const url = [END_POINT_URL, publisherId].join('?p='); + + return { + url, + method: 'POST', + data: JSON.stringify(request), + bids: validBidRequests + }; + }, + interpretResponse: (serverResponse, {bids}) => { + if (!bids) { + return []; + } + + const {bidResponses, cur: currency} = getBidResponses(serverResponse); + + if (!bidResponses) { + return []; + } + + return bids.map((bid, id) => { + const bidResponse = bidResponses[id]; + if (!bidResponse) { + return; + } + + const {price: cpm, crid: creativeId, adm: ad, w: width, h: height, adomain: advertiserDomains, meta = {} + } = bidResponse; + + if (advertiserDomains && advertiserDomains.length > 0) { + meta.advertiserDomains = advertiserDomains + } + + return { + requestId: bid.bidId, + ttl: 360, + mediaType: BANNER, + cpm, + creativeId, + currency, + ad, + width, + height, + meta, + netRevenue: false + }; + }).filter(Boolean); + }, +}; + +registerBidder(spec); + +function getSiteProperties({publisherId, bcat = []}, page) { + return { + id: publisherId, + name: publisherId, + domain: window.location.host, + page, + cat: bcat, + publisher: { + id: publisherId + }, + content: { + language: navigator.language + } + } +} + +function getImps(validBidRequests) { + return validBidRequests.map((bid, id) => { + const {tagId, bidfloor = null, bidfloorcur = CURRENCY} = bid.params; + + return { + id: id + 1, + banner: getBanners(bid), + tagid: tagId, + bidfloor, + bidfloorcur, + }; + }); +} + +function getBanners(bid) { + return getSizes(bid.sizes); +} + +function getSizes(sizes) { + return sizes.map(size => { + return { + h: size[0], + w: size[1] + } + }) +} + +function getBidResponses({body}) { + if (!body || (body && !body.bidResponse)) { + return []; + } + + const {seatbid, cur} = body.bidResponse; + + if (!seatbid.length && !seatbid[0] && seatbid[0].bids) { + return []; + } + + return { + bidResponses: seatbid[0].bid, + cur + }; +} From bb759976595e42b33852fb772026483b0ec9d244 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 7 Feb 2022 12:35:51 +0200 Subject: [PATCH 02/30] create taboola adapter md --- modules/taboolaBidAdapter.md | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 modules/taboolaBidAdapter.md diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md new file mode 100644 index 00000000000..194f5bec7fe --- /dev/null +++ b/modules/taboolaBidAdapter.md @@ -0,0 +1,43 @@ +# Overview + +``` +Module Name: Taboola Adapter +Module Type: Bidder Adapter +Maintainer: someone@taboola.com //todo: need to fill this Maintainer email. +``` + +# Description + +Module that connects to Taboola bidder to fetch bids. +support display format. Using OpenRTB standard. + +# Configuration + +## Bidder and usersync URLs + +The Outbrain adapter does not work without setting the correct bidder and usersync URLs. +You will receive the URLs when contacting us. + +# Test Display Parameters +``` + var adUnits = [{ + code: 'your-unit-container-id', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]], + } + }, + bids: [{ + bidder: 'taboola', + params: { + tagId: 'test-1', + publisherId: 'test', + bidfloor: 0.25, // optional default is null + bidfloorcur: 'USD', // optional default is USD + bcat: ['IAB1-1'], // optional default is [] + badv: ['example.com'] // optional default is [] + } + }] + }]; + +``` From a8fe09790fac35bb8eb99d0659a367ca0c10dd69 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 7 Feb 2022 17:38:50 +0200 Subject: [PATCH 03/30] taboolaBidAdapter.js - small fixes taboolaBidAdapter_spec.js - new UT --- modules/taboolaBidAdapter.js | 2 +- test/spec/modules/taboolaBidAdapter_spec.js | 249 ++++++++++++++++++++ 2 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 test/spec/modules/taboolaBidAdapter_spec.js diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index c9019a8e1e4..3d57d8c9b82 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -142,7 +142,7 @@ function getBidResponses({body}) { const {seatbid, cur} = body.bidResponse; - if (!seatbid.length && !seatbid[0] && seatbid[0].bids) { + if (!seatbid.length || !seatbid[0].bid) { return []; } diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js new file mode 100644 index 00000000000..13572737211 --- /dev/null +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -0,0 +1,249 @@ +import {expect} from 'chai'; +import {spec} from 'modules/taboolaBidAdapter.js'; + +describe.only('Taboola Adapter', function () { + const commonBidRequest = { + bidder: 'taboola', + params: { + publisherId: 'publisherId', + tagId: 'placement name' + }, + bidId: 'aa43860a-4644-442a-b5e0-93f268cs4d19', + auctionId: '65746dca-26f3-4186-be13-dfa63469b1b7', + } + + const displayBidRequestParams = { + sizes: [ + [300, 250] + ] + } + + describe('isBidRequestValid', function () { + it('should fail when bid is invalid - tagId isn`t defined', function () { + const bid = { + bidder: 'taboola', + params: { + publisherId: 'publisherId' + }, + ...displayBidRequestParams + } + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + + it('should fail when bid is invalid - publisherId isn`t defined', function () { + const bid = { + bidder: 'taboola', + params: { + tagId: 'below the article' + }, + ...displayBidRequestParams + } + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + + it('should fail when bid is invalid - sizes isn`t defined', function () { + const bid = { + bidder: 'taboola', + params: { + publisherId: 'publisherId', + tagId: 'below the article' + }, + } + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + + it('should succeed when bid contains valid', function () { + const bid = { + bidder: 'taboola', + params: { + publisherId: 'publisherId', + tagId: 'below the article' + }, + ...displayBidRequestParams, + } + expect(spec.isBidRequestValid(bid)).to.equal(true) + }) + }) + + describe('buildRequests', function () { + const commonBidderRequest = { + refererInfo: { + referer: 'https://example.com/' + } + } + + it('should build display request', function () { + const bidRequest = { + ...commonBidRequest, + ...displayBidRequestParams, + } + const expectedData = { + 'imp': [{ + 'id': 1, + 'banner': [{'h': displayBidRequestParams.sizes[0][0], 'w': displayBidRequestParams.sizes[0][1]}], + 'tagid': 'placement name', + 'bidfloor': null, + 'bidfloorcur': 'USD' + }], + 'site': { + 'id': 'publisherId', + 'name': 'publisherId', + 'domain': window.location.host, + 'page': 'https://example.com/', + 'cat': [], + 'publisher': {'id': 'publisherId'}, + 'content': {'language': 'en-US'} + }, + 'device': {'ua': navigator.userAgent}, + 'source': {'fd': 1}, + 'bcat': [], + 'badv': [] + }; + + const res = spec.buildRequests([bidRequest], commonBidderRequest) + + expect(res.url).to.equal('http://taboolahb.bidder.taboolasyndication.com?p=publisherId') + expect(res.data).to.deep.equal(JSON.stringify(expectedData)) + }) + + it('should pass optional parameters in request', function () { + const optionalParams = { + badv: ['adadadbcd.com'], + bcat: ['IAB25', 'IAB7-39'], + bidfloor: 0.25, + bidfloorcur: 'EUR' + } + const bidRequest = { + ...commonBidRequest, + ...displayBidRequestParams, + params: {...commonBidRequest.params, ...optionalParams} + } + + const res = spec.buildRequests([bidRequest], commonBidderRequest) + const resData = JSON.parse(res.data) + expect(resData.bcat).to.deep.equal(['IAB25', 'IAB7-39']) + expect(resData.badv).to.deep.equal(['adadadbcd.com']) + expect(resData.imp[0].bidfloor).to.deep.equal(0.25) + expect(resData.imp[0].bidfloorcur).to.deep.equal('EUR') + }); + + it('should pass bidder timeout', function () { + const bidRequest = { + ...commonBidRequest, + ...displayBidRequestParams, + } + + const bidderRequest = { + ...commonBidderRequest, + timeout: 500 + } + const res = spec.buildRequests([bidRequest], bidderRequest) + const resData = JSON.parse(res.data) + expect(resData.tmax).to.equal(500) + }); + }) + + describe('interpretResponse', function () { + const serverResponse = { + body: { + 'bidResponse': { + 'id': '49ffg4d58ef9a163a69fhgfghd4fad03621b9e036f24f7_15', + 'seatbid': [ + { + 'bid': [ + { + 'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c', + 'impid': '1', + 'price': 0.342068, + 'adid': '2785119545551083381', + 'adm': '\u003chtml\u003e\n\u003chead\u003e\n\u003cmeta charset\u003d"UTF-8"\u003e\n\u003cmeta http-equiv\u003d"Content-Type" content\u003d"text/html; charset\u003dutf-8"/\u003e\u003c/head\u003e\n\u003cbody style\u003d"margin: 0px; overflow:hidden;"\u003e \n\u003cscript type\u003d"text/javascript"\u003e\nwindow.tbl_trc_domain \u003d \u0027us-trc.taboola.com\u0027;\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({article:\u0027auto\u0027});\n!function (e, f, u, i) {\nif (!document.getElementById(i)){\ne.async \u003d 1;\ne.src \u003d u;\ne.id \u003d i;\nf.parentNode.insertBefore(e, f);\n}\n}(document.createElement(\u0027script\u0027),\ndocument.getElementsByTagName(\u0027script\u0027)[0],\n\u0027//cdn.taboola.com/libtrc/wattpad-placement-255/loader.js\u0027,\n\u0027tb_loader_script\u0027);\nif(window.performance \u0026\u0026 typeof window.performance.mark \u003d\u003d \u0027function\u0027)\n{window.performance.mark(\u0027tbl_ic\u0027);}\n\u003c/script\u003e\n\n\u003cdiv id\u003d"taboola-below-article-thumbnails" style\u003d"height: 250px; width: 300px;"\u003e\u003c/div\u003e\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({\nmode: \u0027Rbox_300x250_1x1\u0027,\ncontainer: \u0027taboola-below-article-thumbnails\u0027,\nplacement: \u0027wattpad.com_P18694_S257846_W300_H250_N1_TB\u0027,\ntarget_type: \u0027mix\u0027,\n"rtb-win":{ \nbi:\u002749ff4d58ef9a163a696d4fad03621b9e036f24f7_15\u0027,\ncu:\u0027USD\u0027,\nwp:\u0027${AUCTION_PRICE:BF}\u0027,\nwcb:\u0027~!audex-display-impression!~\u0027,\nrt:\u00271643227025284\u0027,\nrdc:\u0027us.taboolasyndication.com\u0027,\nti:\u00274212\u0027,\nex:\u0027MagniteSCoD\u0027,\nbs:\u0027xapi:257846:lvvSm6Ak7_wE\u0027,\nbp:\u002718694\u0027,\nbd:\u0027wattpad.com\u0027,\nsi:\u00279964\u0027\n} \n,\nrec: {"trc":{"si":"a69c7df43b2334f0aa337c37e2d80c21","sd":"v2_a69c7df43b2334f0aa337c37e2d80c21_3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD_1643227025_1643227025_CJS1tQEQ5NdWGPLA0d76xo-9ngEgASgEMCY4iegHQIroB0iB09kDUKPPB1gAYABop-G2i_Hl-eVucAA","ui":"3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD","plc":"PHON","wi":"-643136642229425433","cc":"CA","route":"US:US:V","el2r":["bulk-metrics","debug","social","metrics","perf"],"uvpw":"1","pi":"1420260","cpb":"GNO629MGIJz__________wEqGXVzLnRhYm9vbGFzeW5kaWNhdGlvbi5jb20yC3RyYy1zY29kMTI5OIDwmrUMQInoB0iK6AdQgdPZA1ijzwdjCN3__________wEQ3f__________ARgjZGMI3AoQoBAYFmRjCNIDEOAGGAhkYwiWFBCcHBgYZGMI9AUQiwoYC2RjCNkUEPkcGB1kYwj0FBCeHRgfZGorNDlmZjRkNThlZjlhMTYzYTY5NmQ0ZmFkMDM2MjFiOWUwMzZmMjRmN18xNXgCgAHpbIgBrPvTxQE","dcga":{"pubConfigOverride":{"border-color":"black","font-weight":"bold","inherit-title-color":"true","module-name":"cta-lazy-module","enable-call-to-action-creative-component":"true","disable-cta-on-custom-module":"true"}},"tslt":{"p-video-overlay":{"cancel":"סגור","goto":"עבור לדף"},"read-more":{"DEFAULT_CAPTION":"%D7%A7%D7%A8%D7%90%20%D7%A2%D7%95%D7%93"},"next-up":{"BTN_TEXT":"לקריאת התוכן הבא"},"time-ago":{"now":"עכשיו","today":"היום","yesterday":"אתמול","minutes":"לפני {0} דקות","hour":"לפני שעה","hours":"לפני {0} שעות","days":"לפני {0} ימים"},"explore-more":{"TITLE_TEXT":"המשיכו לקרוא","POPUP_TEXT":"אל תפספסו הזדמנות לקרוא עוד תוכן מעולה, רגע לפני שתעזבו"}},"evh":"-1964913910","vl":[{"ri":"185db6d274ce94b27caaabd9eed7915b","uip":"wattpad.com_P18694_S257846_W300_H250_N1_TB","ppb":"COIF","estimation_method":"EcpmEstimationMethodType_ESTIMATION","baseline_variant":"false","original_ecpm":"0.4750949889421463","v":[{"thumbnail":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg","all-thumbnails":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg!-#@1600x1000","origin":"default","thumb-size":"1600x1000","title":"Get Roofing Services At Prices You Can Afford In Edmonton","type":"text","published-date":"1641997069","branding-text":"Roofing Services | Search Ads","url":"https://inneth-conded.xyz/9ad2e613-8777-4fe7-9a52-386c88879289?site\u003dwattpad-placement-255\u0026site_id\u003d1420260\u0026title\u003dGet+Roofing+Services+At+Prices+You+Can+Afford+In+Edmonton\u0026platform\u003dSmartphone\u0026campaign_id\u003d15573949\u0026campaign_item_id\u003d3108610633\u0026thumbnail\u003dhttp%3A%2F%2Fcdn.taboola.com%2Flibtrc%2Fstatic%2Fthumbnails%2Fa2b272be514ca3ebe3f97a4a32a41db5.jpg\u0026cpc\u003d{cpc}\u0026click_id\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1\u0026tblci\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1#tblciGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1","duration":"0","sig":"328243c4127ff16e3fdcd7270bab908f6f3fc5b4c98d","item-id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","uploader":"","is-syndicated":"true","publisher":"search","id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","category":"home","views":"0","itp":[{"u":"https://trc.taboola.com/1326786/log/3/unip?en\u003dclickersusa","t":"c"}],"description":""}]}],"cpcud":{"upc":"0.0","upr":"0.0"}}}\n});\n\u003c/script\u003e\n\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({flush: true});\n\u003c/script\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e', + 'adomain': [ + 'example.xyz' + ], + 'cid': '15744349', + 'crid': '278195503434041083381', + 'w': 300, + 'h': 250, + 'lurl': 'http://us-trc.taboola.com/sample' + } + ], + 'seat': '14204545260' + } + ], + 'bidid': 'da43860a-4644-442a-b5e0-93f268cf8d19', + 'cur': 'USD' + }, + 'debugResponse': {} + } + }; + + const request = { + bids: [ + { + ...commonBidRequest, + ...displayBidRequestParams + } + ] + } + + it('should return empty array if no valid bids', function () { + const res = spec.interpretResponse(serverResponse, []) + expect(res).to.be.an('array').that.is.empty + }); + + it('should return empty array if no server response', function () { + const res = spec.interpretResponse({}, request) + expect(res).to.be.an('array').that.is.empty + }); + + it('should return empty array if server response without seatbid', function () { + const overriddenServerResponse = {...serverResponse}; + const seatbid = {...serverResponse.body.bidResponse.seatbid[0]}; + overriddenServerResponse.body.bidResponse.seatbid[0] = {}; + + const res = spec.interpretResponse(overriddenServerResponse, request) + expect(res).to.be.an('array').that.is.empty + + overriddenServerResponse.body.bidResponse.seatbid[0] = seatbid; + }); + + it('should return empty array if server response without bids', function () { + const overriddenServerResponse = {...serverResponse}; + const bid = [...serverResponse.body.bidResponse.seatbid[0].bid]; + overriddenServerResponse.body.bidResponse.seatbid[0].bid = {}; + + const res = spec.interpretResponse(overriddenServerResponse, request) + expect(res).to.be.an('array').that.is.empty + + overriddenServerResponse.body.bidResponse.seatbid[0].bid = bid; + }); + + it('should interpret display response', function () { + const [bid] = serverResponse.body.bidResponse.seatbid[0].bid; + const expectedRes = [ + { + requestId: request.bids[0].bidId, + cpm: bid.price, + creativeId: bid.crid, + ttl: 360, + netRevenue: false, + currency: serverResponse.body.bidResponse.cur, + mediaType: 'banner', + ad: bid.adm, + width: bid.w, + height: bid.h, + meta: { + 'advertiserDomains': bid.adomain + }, + } + ] + + const res = spec.interpretResponse(serverResponse, request) + expect(res).to.deep.equal(expectedRes) + }); + }) + + describe('getUserSyncs', function () { + // todo: add UT for getUserSyncs + }) +}) From 63147501356a1731982a9a72c6236b67effdd2bb Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 7 Feb 2022 18:09:36 +0200 Subject: [PATCH 04/30] taboolaBidAdapter.js - small fixes taboolaBidAdapter_spec.js - new UT --- modules/taboolaBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index 194f5bec7fe..554eb4de442 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Taboola Adapter Module Type: Bidder Adapter -Maintainer: someone@taboola.com //todo: need to fill this Maintainer email. +Maintainer: headerbidding@taboola.com ``` # Description From 644ba0fdcb20195d60784e56a2684be730859a06 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 7 Feb 2022 18:15:58 +0200 Subject: [PATCH 05/30] update the md --- modules/taboolaBidAdapter.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index 554eb4de442..42871b20ed5 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -13,11 +13,6 @@ support display format. Using OpenRTB standard. # Configuration -## Bidder and usersync URLs - -The Outbrain adapter does not work without setting the correct bidder and usersync URLs. -You will receive the URLs when contacting us. - # Test Display Parameters ``` var adUnits = [{ From b09a481b76347d90540e19263c3296f40206b3b7 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 8 Feb 2022 09:12:02 +0200 Subject: [PATCH 06/30] update the Maintainer email --- modules/taboolaBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index 42871b20ed5..f809e66d9b8 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Taboola Adapter Module Type: Bidder Adapter -Maintainer: headerbidding@taboola.com +Maintainer: prebid@taboola.com ``` # Description From 0f11f67689cb78f60a9aae60ae4fd5eae8055bb1 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 8 Feb 2022 10:05:38 +0200 Subject: [PATCH 07/30] * update MD page * refactor code for better readability * small fix in UT --- modules/taboolaBidAdapter.js | 56 +++++++++++---------- modules/taboolaBidAdapter.md | 15 ++++-- test/spec/modules/taboolaBidAdapter_spec.js | 2 +- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 3d57d8c9b82..fda06eb09e3 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -60,33 +60,7 @@ export const spec = { return []; } - return bids.map((bid, id) => { - const bidResponse = bidResponses[id]; - if (!bidResponse) { - return; - } - - const {price: cpm, crid: creativeId, adm: ad, w: width, h: height, adomain: advertiserDomains, meta = {} - } = bidResponse; - - if (advertiserDomains && advertiserDomains.length > 0) { - meta.advertiserDomains = advertiserDomains - } - - return { - requestId: bid.bidId, - ttl: 360, - mediaType: BANNER, - cpm, - creativeId, - currency, - ad, - width, - height, - meta, - netRevenue: false - }; - }).filter(Boolean); + return bids.map((bid, id) => getBid(bid.bidId, currency, bidResponses[id])).filter(Boolean); }, }; @@ -151,3 +125,31 @@ function getBidResponses({body}) { cur }; } + +function getBid(requestId, currency, bidResponse) { + if (!bidResponse) { + return; + } + + const { + price: cpm, crid: creativeId, adm: ad, w: width, h: height, adomain: advertiserDomains, meta = {} + } = bidResponse; + + if (advertiserDomains && advertiserDomains.length > 0) { + meta.advertiserDomains = advertiserDomains + } + + return { + requestId, + ttl: 360, + mediaType: BANNER, + cpm, + creativeId, + currency, + ad, + width, + height, + meta, + netRevenue: false + }; +} diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index f809e66d9b8..31e77be2793 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -11,8 +11,6 @@ Maintainer: prebid@taboola.com Module that connects to Taboola bidder to fetch bids. support display format. Using OpenRTB standard. -# Configuration - # Test Display Parameters ``` var adUnits = [{ @@ -34,5 +32,16 @@ support display format. Using OpenRTB standard. } }] }]; - ``` + +# Parameters + +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------------------------------|--------------------------|--------------| +| `tagId` | required | Tag Id / Placement name | `below the article` | `String` | +| `publisherId` | required | Tag Id / Placement name | `below the article` | `String` | +| `bcat` | optional | list of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | +| `badv` | optional | Blocked Advertiser Domains | `example.com` | `String Url` | +| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | +| `bidfloorcur` | optional | CPM bid floor currency | `Euro` | `Integer` | + diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 13572737211..2e035f11d0f 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/taboolaBidAdapter.js'; -describe.only('Taboola Adapter', function () { +describe('Taboola Adapter', function () { const commonBidRequest = { bidder: 'taboola', params: { From 90b0258d775cfd8d848aae5369b404f457513e21 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 8 Feb 2022 11:14:31 +0200 Subject: [PATCH 08/30] * add privacy to the request builder * add relevant Ut * small fixes in UT --- modules/taboolaBidAdapter.js | 34 +++++++++-- test/spec/modules/taboolaBidAdapter_spec.js | 67 ++++++++++++++++----- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index fda06eb09e3..bf014c00479 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -3,6 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; +import {config} from '../src/config.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; @@ -24,11 +25,31 @@ export const spec = { }, buildRequests: (validBidRequests, bidderRequest) => { const [bidRequest] = validBidRequests; + const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; const {bcat = [], badv = [], publisherId} = bidRequest.params; - const site = getSiteProperties(bidRequest.params, bidderRequest.refererInfo.referer); + const site = getSiteProperties(bidRequest.params, refererInfo.referer); const device = {ua: navigator.userAgent}; - const timeout = bidderRequest.timeout; const imps = getImps(validBidRequests); + const user = { + ext: {} + }; + const regs = { + coppa: 0, + ext: {} + }; + + if (gdprConsent.gdprApplies) { + user.ext.consent = bidderRequest.gdprConsent.consentString; + regs.ext.gdpr = 1; + } + + if (uspConsent) { + regs.ext.us_privacy = uspConsent; + } + + if (config.getConfig('coppa')) { + regs.coppa = 1 + } const request = { id: bidderRequest.auctionId, @@ -36,10 +57,13 @@ export const spec = { site, device, source: {fd: 1}, - tmax: timeout, - bcat: bcat, - badv: badv + tmax: bidderRequest.timeout, + bcat, + badv, + user, + regs }; + const url = [END_POINT_URL, publisherId].join('?p='); return { diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 2e035f11d0f..0d441dcba2b 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -1,5 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/taboolaBidAdapter.js'; +import {config} from '../../../src/config' describe('Taboola Adapter', function () { const commonBidRequest = { @@ -66,6 +67,11 @@ describe('Taboola Adapter', function () { }) describe('buildRequests', function () { + const defaultBidRequest = { + ...commonBidRequest, + ...displayBidRequestParams, + } + const commonBidderRequest = { refererInfo: { referer: 'https://example.com/' @@ -73,10 +79,6 @@ describe('Taboola Adapter', function () { } it('should build display request', function () { - const bidRequest = { - ...commonBidRequest, - ...displayBidRequestParams, - } const expectedData = { 'imp': [{ 'id': 1, @@ -97,10 +99,12 @@ describe('Taboola Adapter', function () { 'device': {'ua': navigator.userAgent}, 'source': {'fd': 1}, 'bcat': [], - 'badv': [] + 'badv': [], + 'user': {'ext': {}}, + 'regs': {'coppa': 0, 'ext': {}} }; - const res = spec.buildRequests([bidRequest], commonBidderRequest) + const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) expect(res.url).to.equal('http://taboolahb.bidder.taboolasyndication.com?p=publisherId') expect(res.data).to.deep.equal(JSON.stringify(expectedData)) @@ -114,8 +118,7 @@ describe('Taboola Adapter', function () { bidfloorcur: 'EUR' } const bidRequest = { - ...commonBidRequest, - ...displayBidRequestParams, + ...defaultBidRequest, params: {...commonBidRequest.params, ...optionalParams} } @@ -128,19 +131,55 @@ describe('Taboola Adapter', function () { }); it('should pass bidder timeout', function () { - const bidRequest = { - ...commonBidRequest, - ...displayBidRequestParams, - } - const bidderRequest = { ...commonBidderRequest, timeout: 500 } - const res = spec.buildRequests([bidRequest], bidderRequest) + const res = spec.buildRequests([defaultBidRequest], bidderRequest) const resData = JSON.parse(res.data) expect(resData.tmax).to.equal(500) }); + + describe('handle privacy segments when building request', function () { + it('should pass GDPR consent', function () { + const bidderRequest = { + refererInfo: { + referer: 'https://example.com/' + }, + gdprConsent: { + gdprApplies: true, + consentString: 'consentString', + } + }; + + const res = spec.buildRequests([defaultBidRequest], bidderRequest) + const resData = JSON.parse(res.data) + expect(resData.user.ext.consent).to.equal('consentString') + expect(resData.regs.ext.gdpr).to.equal(1) + }); + + it('should pass us privacy consent', function () { + const bidderRequest = { + refererInfo: { + referer: 'https://example.com/' + }, + uspConsent: 'consentString' + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest) + const resData = JSON.parse(res.data) + expect(resData.regs.ext.us_privacy).to.equal('consentString') + }); + + it('should pass coppa consent', function () { + config.setConfig({coppa: true}) + + const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) + const resData = JSON.parse(res.data); + expect(resData.regs.coppa).to.equal(1) + + config.resetConfig() + }); + }) }) describe('interpretResponse', function () { From de8139638f6b38110fe1f06c104394a5b3d7aa93 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 9 Feb 2022 14:44:07 +0200 Subject: [PATCH 09/30] * code refactoring + add more accurate way to get page url and referer * add relevant Ut * small fixes in md --- modules/taboolaBidAdapter.js | 41 +++++++-- modules/taboolaBidAdapter.md | 16 ++-- test/spec/modules/taboolaBidAdapter_spec.js | 93 +++++++++++++++++++-- 3 files changed, 131 insertions(+), 19 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index bf014c00479..44863c81aef 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -4,6 +4,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; +import {getWindowSelf, getWindowTop} from '../src/utils.js' const BIDDER_CODE = 'taboola'; const GVLID = 42; @@ -27,10 +28,11 @@ export const spec = { const [bidRequest] = validBidRequests; const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; const {bcat = [], badv = [], publisherId} = bidRequest.params; - const site = getSiteProperties(bidRequest.params, refererInfo.referer); + const site = getSiteProperties(bidRequest.params, refererInfo); const device = {ua: navigator.userAgent}; const imps = getImps(validBidRequests); const user = { + buyerid: window.TRC ? window.TRC.user_id : 0, ext: {} }; const regs = { @@ -64,7 +66,7 @@ export const spec = { regs }; - const url = [END_POINT_URL, publisherId].join('?p='); + const url = [END_POINT_URL, publisherId].join('?pid='); return { url, @@ -87,16 +89,45 @@ export const spec = { return bids.map((bid, id) => getBid(bid.bidId, currency, bidResponses[id])).filter(Boolean); }, }; +export const internal = { + getPageUrl: (refererInfo = {}) => { + if (refererInfo.canonicalUrl) { + return refererInfo.canonicalUrl; + } + + if (config.getConfig('pageUrl')) { + return config.getConfig('pageUrl'); + } + + try { + return getWindowTop().location.href; + } catch (e) { + return getWindowSelf().location.href; + } + }, + getReferrer: (refererInfo = {}) => { + if (refererInfo.referer) { + return refererInfo.referer; + } + + try { + return getWindowTop().document.referrer; + } catch (e) { + return getWindowSelf().document.referrer; + } + } +} registerBidder(spec); -function getSiteProperties({publisherId, bcat = []}, page) { +function getSiteProperties({publisherId, bcat = []}, refererInfo) { + const {getPageUrl, getReferrer} = internal; return { id: publisherId, name: publisherId, domain: window.location.host, - page, - cat: bcat, + page: getPageUrl(refererInfo), + ref: getReferrer(refererInfo), publisher: { id: publisherId }, diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index 31e77be2793..5a84ab378be 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -36,12 +36,12 @@ support display format. Using OpenRTB standard. # Parameters -| Name | Scope | Description | Example | Type | -|---------------|----------|----------------------------------------------|--------------------------|--------------| -| `tagId` | required | Tag Id / Placement name | `below the article` | `String` | -| `publisherId` | required | Tag Id / Placement name | `below the article` | `String` | -| `bcat` | optional | list of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | -| `badv` | optional | Blocked Advertiser Domains | `example.com` | `String Url` | -| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | -| `bidfloorcur` | optional | CPM bid floor currency | `Euro` | `Integer` | +| Name | Scope | Description | Example | Type | +|----------------|----------|-----------------------------------------------------|--------------------------|--------------| +| `tagId` | required | Tag Id / Placement name | `below the article` | `String` | +| `publisherId` | required | Publisher id | `Publisher name` | `String` | +| `bcat` | optional | list of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | +| `badv` | optional | Blocked Advertiser Domains | `example.com` | `String Url` | +| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | +| `bidfloorcur` | optional | CPM bid floor currency | `Euro` | `Integer` | diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 0d441dcba2b..cb10875ff04 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; -import {spec} from 'modules/taboolaBidAdapter.js'; +import {spec, internal} from 'modules/taboolaBidAdapter.js'; import {config} from '../../../src/config' +import * as utils from '../../../src/utils' describe('Taboola Adapter', function () { const commonBidRequest = { @@ -74,7 +75,8 @@ describe('Taboola Adapter', function () { const commonBidderRequest = { refererInfo: { - referer: 'https://example.com/' + referer: 'https://example.com/ref', + canonicalUrl: 'https://example.com/' } } @@ -91,8 +93,8 @@ describe('Taboola Adapter', function () { 'id': 'publisherId', 'name': 'publisherId', 'domain': window.location.host, - 'page': 'https://example.com/', - 'cat': [], + 'page': commonBidderRequest.refererInfo.canonicalUrl, + 'ref': commonBidderRequest.refererInfo.referer, 'publisher': {'id': 'publisherId'}, 'content': {'language': 'en-US'} }, @@ -100,13 +102,16 @@ describe('Taboola Adapter', function () { 'source': {'fd': 1}, 'bcat': [], 'badv': [], - 'user': {'ext': {}}, + 'user': { + 'buyerid': 0, + 'ext': {}, + }, 'regs': {'coppa': 0, 'ext': {}} }; const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) - expect(res.url).to.equal('http://taboolahb.bidder.taboolasyndication.com?p=publisherId') + expect(res.url).to.equal('http://taboolahb.bidder.taboolasyndication.com?pid=publisherId') expect(res.data).to.deep.equal(JSON.stringify(expectedData)) }) @@ -140,6 +145,20 @@ describe('Taboola Adapter', function () { expect(resData.tmax).to.equal(500) }); + it('should use Taboola user id if exist', function () { + window.TRC = { + user_id: 51525152 + } + const bidderRequest = { + ...commonBidderRequest, + timeout: 500 + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest) + const resData = JSON.parse(res.data) + expect(resData.user.buyerid).to.equal(51525152) + delete window.TRC; + }); + describe('handle privacy segments when building request', function () { it('should pass GDPR consent', function () { const bidderRequest = { @@ -285,4 +304,66 @@ describe('Taboola Adapter', function () { describe('getUserSyncs', function () { // todo: add UT for getUserSyncs }) + + describe('internal functions', function () { + describe('getPageUrl', function() { + let origPageUrl; + const bidderRequest = { + refererInfo: { + canonicalUrl: 'http://canonical.url' + } + }; + + beforeEach(function() { + // remember original pageUrl in config + origPageUrl = config.getConfig('pageUrl'); + + // unset pageUrl in config + config.setConfig({ pageUrl: null }); + }); + + afterEach(function() { + // set original pageUrl to config + config.setConfig({ pageUrl: origPageUrl }); + }); + + it('should handle empty or missing data', function() { + expect(internal.getPageUrl(undefined)).to.equal(utils.getWindowTop().location.href); + expect(internal.getPageUrl('')).to.equal(utils.getWindowTop().location.href); + }); + + it('should use "pageUrl" from config', function() { + config.setConfig({ pageUrl: 'http://page.url' }); + + expect(internal.getPageUrl(undefined)).to.equal(config.getConfig('pageUrl')); + }); + + it('should use bidderRequest.refererInfo.canonicalUrl', function() { + expect(internal.getPageUrl(bidderRequest.refererInfo)).to.equal(bidderRequest.refererInfo.canonicalUrl); + }); + + it('should prefer bidderRequest.refererInfo.canonicalUrl over "pageUrl" from config', () => { + config.setConfig({ pageUrl: 'https://page.url' }); + + expect(internal.getPageUrl(bidderRequest.refererInfo)).to.equal(bidderRequest.refererInfo.canonicalUrl); + }); + }); + + describe('getReferrer', function() { + it('should handle empty or missing data', function() { + expect(internal.getReferrer(undefined)).to.equal(utils.getWindowTop().document.referrer); + expect(internal.getReferrer('')).to.equal(utils.getWindowTop().document.referrer); + }); + + it('should use bidderRequest.refererInfo.referer', () => { + const bidderRequest = { + refererInfo: { + referer: 'foobar' + } + }; + + expect(internal.getReferrer(bidderRequest.refererInfo)).to.equal(bidderRequest.refererInfo.referer); + }); + }); + }) }) From a1dfd88397b5af60b651f69e3fa3b7d22c99515f Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 10 Feb 2022 16:34:49 +0200 Subject: [PATCH 10/30] * code refactoring + gte user id * add relevant Ut * small fixes --- modules/taboolaBidAdapter.js | 117 +++++++++++----- test/spec/modules/taboolaBidAdapter_spec.js | 141 +++++++++++++++----- 2 files changed, 188 insertions(+), 70 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 44863c81aef..34b751c5dbc 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -1,15 +1,91 @@ -// jshint esversion: 6, es3: false, node: true 'use strict'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {getWindowSelf, getWindowTop} from '../src/utils.js' +import {getStorageManager} from '../src/storageManager.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; const CURRENCY = 'USD'; -const END_POINT_URL = 'http://taboolahb.bidder.taboolasyndication.com' +export const END_POINT_URL = 'https://taboolahb.bidder.taboolasyndication.com'; +const USER_ID = 'user-id'; +const STORAGE_KEY = `taboola global:${USER_ID}`; +const COOKIE_KEY = 'trc_cookie_storage'; + +/** + * try to extract User Id by that order: + * local storage + * first party cookie + * rendered trc + * new user set it to 0 + */ +export const userData = { + storageManager: getStorageManager(GVLID, BIDDER_CODE), + getUserId: () => { + const {getFromLocalStorage, getFromCookie, getFromTRC} = userData; + + try { + return getFromLocalStorage() || getFromCookie() || getFromTRC(); + } catch (ex) { + return 0; + } + }, + getFromCookie() { + const {cookiesAreEnabled, getCookie} = userData.storageManager; + if (cookiesAreEnabled()) { + const cookieData = getCookie(COOKIE_KEY); + const userId = userData.getCookieDataByKey(cookieData, USER_ID); + if (userId) { + return userId; + } + } + }, + getCookieDataByKey(cookieData, key) { + const [, value = ''] = cookieData.split(`${key}=`) + return value; + }, + getFromLocalStorage() { + const {hasLocalStorage, localStorageIsEnabled, getDataFromLocalStorage} = userData.storageManager; + + if (hasLocalStorage() && localStorageIsEnabled()) { + return getDataFromLocalStorage(STORAGE_KEY); + } + }, + getFromTRC() { + return window.TRC ? window.TRC.user_id : 0; + } +} + +export const internal = { + getPageUrl: (refererInfo = {}) => { + if (refererInfo.canonicalUrl) { + return refererInfo.canonicalUrl; + } + + if (config.getConfig('pageUrl')) { + return config.getConfig('pageUrl'); + } + + try { + return getWindowTop().location.href; + } catch (e) { + return getWindowSelf().location.href; + } + }, + getReferrer: (refererInfo = {}) => { + if (refererInfo.referer) { + return refererInfo.referer; + } + + try { + return getWindowTop().document.referrer; + } catch (e) { + return getWindowSelf().document.referrer; + } + } +} export const spec = { supportedMediaTypes: [BANNER], @@ -21,9 +97,6 @@ export const spec = { bidRequest.params.publisherId && bidRequest.params.tagId); }, - getUserSyncs: (syncOptions, responses, gdprConsent, uspConsent) => { - return []; - }, buildRequests: (validBidRequests, bidderRequest) => { const [bidRequest] = validBidRequests; const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; @@ -32,7 +105,7 @@ export const spec = { const device = {ua: navigator.userAgent}; const imps = getImps(validBidRequests); const user = { - buyerid: window.TRC ? window.TRC.user_id : 0, + buyeruid: userData.getUserId(gdprConsent, uspConsent), ext: {} }; const regs = { @@ -89,36 +162,6 @@ export const spec = { return bids.map((bid, id) => getBid(bid.bidId, currency, bidResponses[id])).filter(Boolean); }, }; -export const internal = { - getPageUrl: (refererInfo = {}) => { - if (refererInfo.canonicalUrl) { - return refererInfo.canonicalUrl; - } - - if (config.getConfig('pageUrl')) { - return config.getConfig('pageUrl'); - } - - try { - return getWindowTop().location.href; - } catch (e) { - return getWindowSelf().location.href; - } - }, - getReferrer: (refererInfo = {}) => { - if (refererInfo.referer) { - return refererInfo.referer; - } - - try { - return getWindowTop().document.referrer; - } catch (e) { - return getWindowSelf().document.referrer; - } - } -} - -registerBidder(spec); function getSiteProperties({publisherId, bcat = []}, refererInfo) { const {getPageUrl, getReferrer} = internal; @@ -208,3 +251,5 @@ function getBid(requestId, currency, bidResponse) { netRevenue: false }; } + +registerBidder(spec); diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index cb10875ff04..de1b4b30854 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec, internal} from 'modules/taboolaBidAdapter.js'; +import {spec, internal, END_POINT_URL, userData} from 'modules/taboolaBidAdapter.js'; import {config} from '../../../src/config' import * as utils from '../../../src/utils' @@ -85,17 +85,17 @@ describe('Taboola Adapter', function () { 'imp': [{ 'id': 1, 'banner': [{'h': displayBidRequestParams.sizes[0][0], 'w': displayBidRequestParams.sizes[0][1]}], - 'tagid': 'placement name', + 'tagid': commonBidRequest.params.tagId, 'bidfloor': null, 'bidfloorcur': 'USD' }], 'site': { - 'id': 'publisherId', - 'name': 'publisherId', + 'id': commonBidRequest.params.publisherId, + 'name': commonBidRequest.params.publisherId, 'domain': window.location.host, 'page': commonBidderRequest.refererInfo.canonicalUrl, 'ref': commonBidderRequest.refererInfo.referer, - 'publisher': {'id': 'publisherId'}, + 'publisher': {'id': commonBidRequest.params.publisherId}, 'content': {'language': 'en-US'} }, 'device': {'ua': navigator.userAgent}, @@ -103,7 +103,7 @@ describe('Taboola Adapter', function () { 'bcat': [], 'badv': [], 'user': { - 'buyerid': 0, + 'buyeruid': 0, 'ext': {}, }, 'regs': {'coppa': 0, 'ext': {}} @@ -111,7 +111,7 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) - expect(res.url).to.equal('http://taboolahb.bidder.taboolasyndication.com?pid=publisherId') + expect(res.url).to.equal(`${END_POINT_URL}?pid=${commonBidRequest.params.publisherId}`) expect(res.data).to.deep.equal(JSON.stringify(expectedData)) }) @@ -145,20 +145,6 @@ describe('Taboola Adapter', function () { expect(resData.tmax).to.equal(500) }); - it('should use Taboola user id if exist', function () { - window.TRC = { - user_id: 51525152 - } - const bidderRequest = { - ...commonBidderRequest, - timeout: 500 - } - const res = spec.buildRequests([defaultBidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.user.buyerid).to.equal(51525152) - delete window.TRC; - }); - describe('handle privacy segments when building request', function () { it('should pass GDPR consent', function () { const bidderRequest = { @@ -199,6 +185,93 @@ describe('Taboola Adapter', function () { config.resetConfig() }); }) + + describe('handle userid ', function () { + it('should get user id from local storage', function () { + const getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); + getDataFromLocalStorage.returns(51525152); + + const bidderRequest = { + ...commonBidderRequest, + timeout: 500 + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal(51525152); + getDataFromLocalStorage.restore(); + }); + + it('should get user id from cookie if local storage isn`t defined', function () { + const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); + const getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); + const getCookie = sinon.stub(userData.storageManager, 'getCookie'); + + getDataFromLocalStorage.returns(51525152); + hasLocalStorage.returns(false); + getCookie.returns('taboola%20global%3Auser-id=12121212'); + + const bidderRequest = { + ...commonBidderRequest + }; + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal('12121212'); + + getDataFromLocalStorage.restore(); + hasLocalStorage.restore(); + getCookie.restore(); + }); + + it('should get user id from TRC if local storage and cookie isn`t defined', function () { + const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); + const cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); + + hasLocalStorage.returns(false); + cookiesAreEnabled.returns(false); + + window.TRC = { + user_id: 31313131 + }; + + const bidderRequest = { + ...commonBidderRequest + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal(31313131); + + hasLocalStorage.restore(); + cookiesAreEnabled.restore(); + delete window.TRC; + }); + + it('should get user id to be 0 if cookie, local storage, TRC isn`t defined', function () { + const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); + const cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); + + hasLocalStorage.returns(false); + cookiesAreEnabled.returns(false); + + const bidderRequest = { + ...commonBidderRequest + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal(0); + + hasLocalStorage.restore(); + cookiesAreEnabled.restore(); + }); + + it('should set buyeruid to be 0 if it`s a new user', function () { + const bidderRequest = { + ...commonBidderRequest + } + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal(0); + }); + }); }) describe('interpretResponse', function () { @@ -301,12 +374,12 @@ describe('Taboola Adapter', function () { }); }) - describe('getUserSyncs', function () { + describe('userData', function () { // todo: add UT for getUserSyncs }) describe('internal functions', function () { - describe('getPageUrl', function() { + describe('getPageUrl', function () { let origPageUrl; const bidderRequest = { refererInfo: { @@ -314,43 +387,43 @@ describe('Taboola Adapter', function () { } }; - beforeEach(function() { + beforeEach(function () { // remember original pageUrl in config origPageUrl = config.getConfig('pageUrl'); // unset pageUrl in config - config.setConfig({ pageUrl: null }); + config.setConfig({pageUrl: null}); }); - afterEach(function() { + afterEach(function () { // set original pageUrl to config - config.setConfig({ pageUrl: origPageUrl }); + config.setConfig({pageUrl: origPageUrl}); }); - it('should handle empty or missing data', function() { + it('should handle empty or missing data', function () { expect(internal.getPageUrl(undefined)).to.equal(utils.getWindowTop().location.href); expect(internal.getPageUrl('')).to.equal(utils.getWindowTop().location.href); }); - it('should use "pageUrl" from config', function() { - config.setConfig({ pageUrl: 'http://page.url' }); + it('should use "pageUrl" from config', function () { + config.setConfig({pageUrl: 'http://page.url'}); expect(internal.getPageUrl(undefined)).to.equal(config.getConfig('pageUrl')); }); - it('should use bidderRequest.refererInfo.canonicalUrl', function() { + it('should use bidderRequest.refererInfo.canonicalUrl', function () { expect(internal.getPageUrl(bidderRequest.refererInfo)).to.equal(bidderRequest.refererInfo.canonicalUrl); }); it('should prefer bidderRequest.refererInfo.canonicalUrl over "pageUrl" from config', () => { - config.setConfig({ pageUrl: 'https://page.url' }); + config.setConfig({pageUrl: 'https://page.url'}); expect(internal.getPageUrl(bidderRequest.refererInfo)).to.equal(bidderRequest.refererInfo.canonicalUrl); }); }); - describe('getReferrer', function() { - it('should handle empty or missing data', function() { + describe('getReferrer', function () { + it('should handle empty or missing data', function () { expect(internal.getReferrer(undefined)).to.equal(utils.getWindowTop().document.referrer); expect(internal.getReferrer('')).to.equal(utils.getWindowTop().document.referrer); }); From 600a9d0c5c379ab0b140c7f3d4e6f92702065547 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 13 Feb 2022 16:16:27 +0200 Subject: [PATCH 11/30] * code refactoring + gte user id * add relevant Ut * small fixes --- modules/taboolaBidAdapter.js | 15 +++++---------- test/spec/modules/taboolaBidAdapter_spec.js | 5 ++++- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 34b751c5dbc..d1c5628184d 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -195,16 +195,11 @@ function getImps(validBidRequests) { } function getBanners(bid) { - return getSizes(bid.sizes); -} - -function getSizes(sizes) { - return sizes.map(size => { - return { - h: size[0], - w: size[1] - } - }) + const [size] = bid.sizes; + return { + h: size[0], + w: size[1] + } } function getBidResponses({body}) { diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index de1b4b30854..57d49cb9f1c 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -84,7 +84,10 @@ describe('Taboola Adapter', function () { const expectedData = { 'imp': [{ 'id': 1, - 'banner': [{'h': displayBidRequestParams.sizes[0][0], 'w': displayBidRequestParams.sizes[0][1]}], + 'banner': { + 'h': displayBidRequestParams.sizes[0][0], + 'w': displayBidRequestParams.sizes[0][1] + }, 'tagid': commonBidRequest.params.tagId, 'bidfloor': null, 'bidfloorcur': 'USD' From 7fb13799be3b16e8c4906456c8cc70ed1e6a6c06 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 15 Feb 2022 16:09:56 +0200 Subject: [PATCH 12/30] * update end point url * update UT * Update banner End point structure --- modules/taboolaBidAdapter.js | 23 +++++--- modules/taboolaBidAdapter.md | 60 +++++++++++---------- test/spec/modules/taboolaBidAdapter_spec.js | 15 +++--- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index d1c5628184d..d0d9db415f9 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -9,7 +9,7 @@ import {getStorageManager} from '../src/storageManager.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; const CURRENCY = 'USD'; -export const END_POINT_URL = 'https://taboolahb.bidder.taboolasyndication.com'; +export const END_POINT_URL = 'hb.bidder.taboola.com/TaboolaHBOpenRTBRequestHandlerServlet'; const USER_ID = 'user-id'; const STORAGE_KEY = `taboola global:${USER_ID}`; const COOKIE_KEY = 'trc_cookie_storage'; @@ -93,9 +93,9 @@ export const spec = { code: BIDDER_CODE, isBidRequestValid: (bidRequest) => { return !!(bidRequest.sizes && - bidRequest.params && - bidRequest.params.publisherId && - bidRequest.params.tagId); + bidRequest.params && + bidRequest.params.publisherId && + bidRequest.params.tagId); }, buildRequests: (validBidRequests, bidderRequest) => { const [bidRequest] = validBidRequests; @@ -139,7 +139,7 @@ export const spec = { regs }; - const url = [END_POINT_URL, publisherId].join('?pid='); + const url = [END_POINT_URL, publisherId].join(''); return { url, @@ -195,10 +195,17 @@ function getImps(validBidRequests) { } function getBanners(bid) { - const [size] = bid.sizes; + return getSizes(bid.sizes); +} + +function getSizes(sizes) { return { - h: size[0], - w: size[1] + format: sizes.map(size => { + return { + h: size[0], + w: size[1] + } + }) } } diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index 5a84ab378be..d02cdf4126a 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -9,39 +9,41 @@ Maintainer: prebid@taboola.com # Description Module that connects to Taboola bidder to fetch bids. -support display format. Using OpenRTB standard. +- Supports ‘display’ format +- Uses OpenRTB standard + +The Taboola Bidding adapter requires setup before beginning. Please contact us on prebid@taboola.com # Test Display Parameters -``` - var adUnits = [{ - code: 'your-unit-container-id', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]], - } - }, - bids: [{ - bidder: 'taboola', - params: { - tagId: 'test-1', - publisherId: 'test', - bidfloor: 0.25, // optional default is null - bidfloorcur: 'USD', // optional default is USD - bcat: ['IAB1-1'], // optional default is [] - badv: ['example.com'] // optional default is [] - } - }] - }]; +``` javascript + var adUnits = [{ + code: 'your-unit-container-id', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'taboola', + params: { + tagId: 'Placement Name', + publisherId: 'your-publisher-id', + bidfloor: 0.25, // Optional - default is null + bcat: ['IAB1-1'], // Optional - default is [] + badv: ['example.com'] // Optional - default is [] + } + }] +}]; ``` # Parameters -| Name | Scope | Description | Example | Type | -|----------------|----------|-----------------------------------------------------|--------------------------|--------------| -| `tagId` | required | Tag Id / Placement name | `below the article` | `String` | -| `publisherId` | required | Publisher id | `Publisher name` | `String` | -| `bcat` | optional | list of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | -| `badv` | optional | Blocked Advertiser Domains | `example.com` | `String Url` | -| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | -| `bidfloorcur` | optional | CPM bid floor currency | `Euro` | `Integer` | +| Name | Scope | Description | Example | Type | +|----------------|----------|---------------------------------------------------------|----------------------------|--------------| +| `tagId` | required | Tag ID / Placement Name
(as provided by Taboola) | `'Below The Article'` | `String` | +| `publisherId` | required | Alphabetic Publisher ID
(as provided by Taboola) | `'acme-publishing'` | `String` | +| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | +| `badv` | optional | Blocked Advertiser Domains | `'example.com'` | `String Url` | +| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | + diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 57d49cb9f1c..e5a34dfb36d 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -15,9 +15,7 @@ describe('Taboola Adapter', function () { } const displayBidRequestParams = { - sizes: [ - [300, 250] - ] + sizes: [[300, 250], [300, 600]] } describe('isBidRequestValid', function () { @@ -85,8 +83,13 @@ describe('Taboola Adapter', function () { 'imp': [{ 'id': 1, 'banner': { - 'h': displayBidRequestParams.sizes[0][0], - 'w': displayBidRequestParams.sizes[0][1] + format: [{ + h: displayBidRequestParams.sizes[0][0], + w: displayBidRequestParams.sizes[0][1]}, + { + h: displayBidRequestParams.sizes[1][0], + w: displayBidRequestParams.sizes[1][1]} + ] }, 'tagid': commonBidRequest.params.tagId, 'bidfloor': null, @@ -114,7 +117,7 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) - expect(res.url).to.equal(`${END_POINT_URL}?pid=${commonBidRequest.params.publisherId}`) + expect(res.url).to.equal(`${END_POINT_URL}${commonBidRequest.params.publisherId}`) expect(res.data).to.deep.equal(JSON.stringify(expectedData)) }) From 0cf48adc552fb29aa33d830c610226db10577e3d Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 21 Feb 2022 10:09:29 +0200 Subject: [PATCH 13/30] small fixes + update epi url --- modules/taboolaBidAdapter.js | 14 +++++++------- modules/taboolaBidAdapter.md | 4 ++-- test/spec/modules/taboolaBidAdapter_spec.js | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index d0d9db415f9..534edcc6e63 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -9,17 +9,17 @@ import {getStorageManager} from '../src/storageManager.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; const CURRENCY = 'USD'; -export const END_POINT_URL = 'hb.bidder.taboola.com/TaboolaHBOpenRTBRequestHandlerServlet'; +export const END_POINT_URL = 'http://hb.bidder.taboola.com/TaboolaHBOpenRTBRequestHandlerServlet'; const USER_ID = 'user-id'; const STORAGE_KEY = `taboola global:${USER_ID}`; const COOKIE_KEY = 'trc_cookie_storage'; /** - * try to extract User Id by that order: - * local storage - * first party cookie - * rendered trc - * new user set it to 0 + * extract User Id by that order: + * 1. local storage + * 2. first party cookie + * 3. rendered trc + * 4. new user set it to 0 */ export const userData = { storageManager: getStorageManager(GVLID, BIDDER_CODE), @@ -139,7 +139,7 @@ export const spec = { regs }; - const url = [END_POINT_URL, publisherId].join(''); + const url = [END_POINT_URL, publisherId].join('/'); return { url, diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index d02cdf4126a..a3cd1d9261b 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -9,8 +9,8 @@ Maintainer: prebid@taboola.com # Description Module that connects to Taboola bidder to fetch bids. -- Supports ‘display’ format -- Uses OpenRTB standard +- Supports `display` format +- Uses `OpenRTB` standard The Taboola Bidding adapter requires setup before beginning. Please contact us on prebid@taboola.com diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index e5a34dfb36d..f6cbee45668 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -117,7 +117,7 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) - expect(res.url).to.equal(`${END_POINT_URL}${commonBidRequest.params.publisherId}`) + expect(res.url).to.equal(`${END_POINT_URL}/${commonBidRequest.params.publisherId}`) expect(res.data).to.deep.equal(JSON.stringify(expectedData)) }) From e6e0235a1512b874553334c302a6a3c8c38ec7f9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 May 2022 14:40:06 +0300 Subject: [PATCH 14/30] remove the destruction from the bidResponse property --- modules/taboolaBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 534edcc6e63..a35f75c8079 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -210,11 +210,11 @@ function getSizes(sizes) { } function getBidResponses({body}) { - if (!body || (body && !body.bidResponse)) { + if (!body) { return []; } - const {seatbid, cur} = body.bidResponse; + const {seatbid, cur} = body; if (!seatbid.length || !seatbid[0].bid) { return []; From 1dabc419d22086eed1e86cfd6ae10f160785fe2e Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 8 May 2022 15:14:37 +0300 Subject: [PATCH 15/30] (update the unit tests) remove the destruction from the bidResponse property --- modules/taboolaBidAdapter.js | 2 +- test/spec/modules/taboolaBidAdapter_spec.js | 75 ++++++++++----------- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index a35f75c8079..cb6a6048d7f 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -22,7 +22,7 @@ const COOKIE_KEY = 'trc_cookie_storage'; * 4. new user set it to 0 */ export const userData = { - storageManager: getStorageManager(GVLID, BIDDER_CODE), + storageManager: getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE}), getUserId: () => { const {getFromLocalStorage, getFromCookie, getFromTRC} = userData; diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index f6cbee45668..86e32843228 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -85,10 +85,12 @@ describe('Taboola Adapter', function () { 'banner': { format: [{ h: displayBidRequestParams.sizes[0][0], - w: displayBidRequestParams.sizes[0][1]}, + w: displayBidRequestParams.sizes[0][1] + }, { h: displayBidRequestParams.sizes[1][0], - w: displayBidRequestParams.sizes[1][1]} + w: displayBidRequestParams.sizes[1][1] + } ] }, 'tagid': commonBidRequest.params.tagId, @@ -283,34 +285,31 @@ describe('Taboola Adapter', function () { describe('interpretResponse', function () { const serverResponse = { body: { - 'bidResponse': { - 'id': '49ffg4d58ef9a163a69fhgfghd4fad03621b9e036f24f7_15', - 'seatbid': [ - { - 'bid': [ - { - 'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c', - 'impid': '1', - 'price': 0.342068, - 'adid': '2785119545551083381', - 'adm': '\u003chtml\u003e\n\u003chead\u003e\n\u003cmeta charset\u003d"UTF-8"\u003e\n\u003cmeta http-equiv\u003d"Content-Type" content\u003d"text/html; charset\u003dutf-8"/\u003e\u003c/head\u003e\n\u003cbody style\u003d"margin: 0px; overflow:hidden;"\u003e \n\u003cscript type\u003d"text/javascript"\u003e\nwindow.tbl_trc_domain \u003d \u0027us-trc.taboola.com\u0027;\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({article:\u0027auto\u0027});\n!function (e, f, u, i) {\nif (!document.getElementById(i)){\ne.async \u003d 1;\ne.src \u003d u;\ne.id \u003d i;\nf.parentNode.insertBefore(e, f);\n}\n}(document.createElement(\u0027script\u0027),\ndocument.getElementsByTagName(\u0027script\u0027)[0],\n\u0027//cdn.taboola.com/libtrc/wattpad-placement-255/loader.js\u0027,\n\u0027tb_loader_script\u0027);\nif(window.performance \u0026\u0026 typeof window.performance.mark \u003d\u003d \u0027function\u0027)\n{window.performance.mark(\u0027tbl_ic\u0027);}\n\u003c/script\u003e\n\n\u003cdiv id\u003d"taboola-below-article-thumbnails" style\u003d"height: 250px; width: 300px;"\u003e\u003c/div\u003e\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({\nmode: \u0027Rbox_300x250_1x1\u0027,\ncontainer: \u0027taboola-below-article-thumbnails\u0027,\nplacement: \u0027wattpad.com_P18694_S257846_W300_H250_N1_TB\u0027,\ntarget_type: \u0027mix\u0027,\n"rtb-win":{ \nbi:\u002749ff4d58ef9a163a696d4fad03621b9e036f24f7_15\u0027,\ncu:\u0027USD\u0027,\nwp:\u0027${AUCTION_PRICE:BF}\u0027,\nwcb:\u0027~!audex-display-impression!~\u0027,\nrt:\u00271643227025284\u0027,\nrdc:\u0027us.taboolasyndication.com\u0027,\nti:\u00274212\u0027,\nex:\u0027MagniteSCoD\u0027,\nbs:\u0027xapi:257846:lvvSm6Ak7_wE\u0027,\nbp:\u002718694\u0027,\nbd:\u0027wattpad.com\u0027,\nsi:\u00279964\u0027\n} \n,\nrec: {"trc":{"si":"a69c7df43b2334f0aa337c37e2d80c21","sd":"v2_a69c7df43b2334f0aa337c37e2d80c21_3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD_1643227025_1643227025_CJS1tQEQ5NdWGPLA0d76xo-9ngEgASgEMCY4iegHQIroB0iB09kDUKPPB1gAYABop-G2i_Hl-eVucAA","ui":"3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD","plc":"PHON","wi":"-643136642229425433","cc":"CA","route":"US:US:V","el2r":["bulk-metrics","debug","social","metrics","perf"],"uvpw":"1","pi":"1420260","cpb":"GNO629MGIJz__________wEqGXVzLnRhYm9vbGFzeW5kaWNhdGlvbi5jb20yC3RyYy1zY29kMTI5OIDwmrUMQInoB0iK6AdQgdPZA1ijzwdjCN3__________wEQ3f__________ARgjZGMI3AoQoBAYFmRjCNIDEOAGGAhkYwiWFBCcHBgYZGMI9AUQiwoYC2RjCNkUEPkcGB1kYwj0FBCeHRgfZGorNDlmZjRkNThlZjlhMTYzYTY5NmQ0ZmFkMDM2MjFiOWUwMzZmMjRmN18xNXgCgAHpbIgBrPvTxQE","dcga":{"pubConfigOverride":{"border-color":"black","font-weight":"bold","inherit-title-color":"true","module-name":"cta-lazy-module","enable-call-to-action-creative-component":"true","disable-cta-on-custom-module":"true"}},"tslt":{"p-video-overlay":{"cancel":"סגור","goto":"עבור לדף"},"read-more":{"DEFAULT_CAPTION":"%D7%A7%D7%A8%D7%90%20%D7%A2%D7%95%D7%93"},"next-up":{"BTN_TEXT":"לקריאת התוכן הבא"},"time-ago":{"now":"עכשיו","today":"היום","yesterday":"אתמול","minutes":"לפני {0} דקות","hour":"לפני שעה","hours":"לפני {0} שעות","days":"לפני {0} ימים"},"explore-more":{"TITLE_TEXT":"המשיכו לקרוא","POPUP_TEXT":"אל תפספסו הזדמנות לקרוא עוד תוכן מעולה, רגע לפני שתעזבו"}},"evh":"-1964913910","vl":[{"ri":"185db6d274ce94b27caaabd9eed7915b","uip":"wattpad.com_P18694_S257846_W300_H250_N1_TB","ppb":"COIF","estimation_method":"EcpmEstimationMethodType_ESTIMATION","baseline_variant":"false","original_ecpm":"0.4750949889421463","v":[{"thumbnail":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg","all-thumbnails":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg!-#@1600x1000","origin":"default","thumb-size":"1600x1000","title":"Get Roofing Services At Prices You Can Afford In Edmonton","type":"text","published-date":"1641997069","branding-text":"Roofing Services | Search Ads","url":"https://inneth-conded.xyz/9ad2e613-8777-4fe7-9a52-386c88879289?site\u003dwattpad-placement-255\u0026site_id\u003d1420260\u0026title\u003dGet+Roofing+Services+At+Prices+You+Can+Afford+In+Edmonton\u0026platform\u003dSmartphone\u0026campaign_id\u003d15573949\u0026campaign_item_id\u003d3108610633\u0026thumbnail\u003dhttp%3A%2F%2Fcdn.taboola.com%2Flibtrc%2Fstatic%2Fthumbnails%2Fa2b272be514ca3ebe3f97a4a32a41db5.jpg\u0026cpc\u003d{cpc}\u0026click_id\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1\u0026tblci\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1#tblciGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1","duration":"0","sig":"328243c4127ff16e3fdcd7270bab908f6f3fc5b4c98d","item-id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","uploader":"","is-syndicated":"true","publisher":"search","id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","category":"home","views":"0","itp":[{"u":"https://trc.taboola.com/1326786/log/3/unip?en\u003dclickersusa","t":"c"}],"description":""}]}],"cpcud":{"upc":"0.0","upr":"0.0"}}}\n});\n\u003c/script\u003e\n\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({flush: true});\n\u003c/script\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e', - 'adomain': [ - 'example.xyz' - ], - 'cid': '15744349', - 'crid': '278195503434041083381', - 'w': 300, - 'h': 250, - 'lurl': 'http://us-trc.taboola.com/sample' - } - ], - 'seat': '14204545260' - } - ], - 'bidid': 'da43860a-4644-442a-b5e0-93f268cf8d19', - 'cur': 'USD' - }, - 'debugResponse': {} + 'id': '49ffg4d58ef9a163a69fhgfghd4fad03621b9e036f24f7_15', + 'seatbid': [ + { + 'bid': [ + { + 'id': '0b3dd94348-134b-435f-8db5-6bf5afgfc39e86c', + 'impid': '1', + 'price': 0.342068, + 'adid': '2785119545551083381', + 'adm': '\u003chtml\u003e\n\u003chead\u003e\n\u003cmeta charset\u003d"UTF-8"\u003e\n\u003cmeta http-equiv\u003d"Content-Type" content\u003d"text/html; charset\u003dutf-8"/\u003e\u003c/head\u003e\n\u003cbody style\u003d"margin: 0px; overflow:hidden;"\u003e \n\u003cscript type\u003d"text/javascript"\u003e\nwindow.tbl_trc_domain \u003d \u0027us-trc.taboola.com\u0027;\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({article:\u0027auto\u0027});\n!function (e, f, u, i) {\nif (!document.getElementById(i)){\ne.async \u003d 1;\ne.src \u003d u;\ne.id \u003d i;\nf.parentNode.insertBefore(e, f);\n}\n}(document.createElement(\u0027script\u0027),\ndocument.getElementsByTagName(\u0027script\u0027)[0],\n\u0027//cdn.taboola.com/libtrc/wattpad-placement-255/loader.js\u0027,\n\u0027tb_loader_script\u0027);\nif(window.performance \u0026\u0026 typeof window.performance.mark \u003d\u003d \u0027function\u0027)\n{window.performance.mark(\u0027tbl_ic\u0027);}\n\u003c/script\u003e\n\n\u003cdiv id\u003d"taboola-below-article-thumbnails" style\u003d"height: 250px; width: 300px;"\u003e\u003c/div\u003e\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({\nmode: \u0027Rbox_300x250_1x1\u0027,\ncontainer: \u0027taboola-below-article-thumbnails\u0027,\nplacement: \u0027wattpad.com_P18694_S257846_W300_H250_N1_TB\u0027,\ntarget_type: \u0027mix\u0027,\n"rtb-win":{ \nbi:\u002749ff4d58ef9a163a696d4fad03621b9e036f24f7_15\u0027,\ncu:\u0027USD\u0027,\nwp:\u0027${AUCTION_PRICE:BF}\u0027,\nwcb:\u0027~!audex-display-impression!~\u0027,\nrt:\u00271643227025284\u0027,\nrdc:\u0027us.taboolasyndication.com\u0027,\nti:\u00274212\u0027,\nex:\u0027MagniteSCoD\u0027,\nbs:\u0027xapi:257846:lvvSm6Ak7_wE\u0027,\nbp:\u002718694\u0027,\nbd:\u0027wattpad.com\u0027,\nsi:\u00279964\u0027\n} \n,\nrec: {"trc":{"si":"a69c7df43b2334f0aa337c37e2d80c21","sd":"v2_a69c7df43b2334f0aa337c37e2d80c21_3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD_1643227025_1643227025_CJS1tQEQ5NdWGPLA0d76xo-9ngEgASgEMCY4iegHQIroB0iB09kDUKPPB1gAYABop-G2i_Hl-eVucAA","ui":"3c70f7c7d64a65b15e4a4175c9a2cfa51072f04bMagniteSCoD","plc":"PHON","wi":"-643136642229425433","cc":"CA","route":"US:US:V","el2r":["bulk-metrics","debug","social","metrics","perf"],"uvpw":"1","pi":"1420260","cpb":"GNO629MGIJz__________wEqGXVzLnRhYm9vbGFzeW5kaWNhdGlvbi5jb20yC3RyYy1zY29kMTI5OIDwmrUMQInoB0iK6AdQgdPZA1ijzwdjCN3__________wEQ3f__________ARgjZGMI3AoQoBAYFmRjCNIDEOAGGAhkYwiWFBCcHBgYZGMI9AUQiwoYC2RjCNkUEPkcGB1kYwj0FBCeHRgfZGorNDlmZjRkNThlZjlhMTYzYTY5NmQ0ZmFkMDM2MjFiOWUwMzZmMjRmN18xNXgCgAHpbIgBrPvTxQE","dcga":{"pubConfigOverride":{"border-color":"black","font-weight":"bold","inherit-title-color":"true","module-name":"cta-lazy-module","enable-call-to-action-creative-component":"true","disable-cta-on-custom-module":"true"}},"tslt":{"p-video-overlay":{"cancel":"סגור","goto":"עבור לדף"},"read-more":{"DEFAULT_CAPTION":"%D7%A7%D7%A8%D7%90%20%D7%A2%D7%95%D7%93"},"next-up":{"BTN_TEXT":"לקריאת התוכן הבא"},"time-ago":{"now":"עכשיו","today":"היום","yesterday":"אתמול","minutes":"לפני {0} דקות","hour":"לפני שעה","hours":"לפני {0} שעות","days":"לפני {0} ימים"},"explore-more":{"TITLE_TEXT":"המשיכו לקרוא","POPUP_TEXT":"אל תפספסו הזדמנות לקרוא עוד תוכן מעולה, רגע לפני שתעזבו"}},"evh":"-1964913910","vl":[{"ri":"185db6d274ce94b27caaabd9eed7915b","uip":"wattpad.com_P18694_S257846_W300_H250_N1_TB","ppb":"COIF","estimation_method":"EcpmEstimationMethodType_ESTIMATION","baseline_variant":"false","original_ecpm":"0.4750949889421463","v":[{"thumbnail":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg","all-thumbnails":"https://cdn.taboola.com/libtrc/static/thumbnails/a2b272be514ca3ebe3f97a4a32a41db5.jpg!-#@1600x1000","origin":"default","thumb-size":"1600x1000","title":"Get Roofing Services At Prices You Can Afford In Edmonton","type":"text","published-date":"1641997069","branding-text":"Roofing Services | Search Ads","url":"https://inneth-conded.xyz/9ad2e613-8777-4fe7-9a52-386c88879289?site\u003dwattpad-placement-255\u0026site_id\u003d1420260\u0026title\u003dGet+Roofing+Services+At+Prices+You+Can+Afford+In+Edmonton\u0026platform\u003dSmartphone\u0026campaign_id\u003d15573949\u0026campaign_item_id\u003d3108610633\u0026thumbnail\u003dhttp%3A%2F%2Fcdn.taboola.com%2Flibtrc%2Fstatic%2Fthumbnails%2Fa2b272be514ca3ebe3f97a4a32a41db5.jpg\u0026cpc\u003d{cpc}\u0026click_id\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1\u0026tblci\u003dGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1#tblciGiCIypnAQogsMTFL3e_mPaVM2qLvK3KRU6LWzEMUgeB6piCit1Uox6CNr5v5n-x1","duration":"0","sig":"328243c4127ff16e3fdcd7270bab908f6f3fc5b4c98d","item-id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","uploader":"","is-syndicated":"true","publisher":"search","id":"~~V1~~2785119550041083381~~PnBkfBE9JnQxpahv0adkcuIcmMhroRAHXwLZd-7zhunTxvAnL2wqac4MyzR7uD46gj3kUkbS3FhelBtnsiJV6MhkDZRZzzIqDobN6rWmCPA3hYz5D3PLat6nhIftiT1lwdxwdlxkeV_Mfb3eos_TQavImGhxk0e7psNAZxHJ9RKL2w3lppALGgQJoy2o6lkf-pOqODtX1VkgWpEEM4WsVoWOnUTAwdyGd-8yrze8CWNp752y28hl7lleicyO1vByRdbgwlJdnqyroTPEQNNEn1JRxBOSYSWt-Xm3vkPm-G4","category":"home","views":"0","itp":[{"u":"https://trc.taboola.com/1326786/log/3/unip?en\u003dclickersusa","t":"c"}],"description":""}]}],"cpcud":{"upc":"0.0","upr":"0.0"}}}\n});\n\u003c/script\u003e\n\n\u003cscript type\u003d"text/javascript"\u003e\nwindow._taboola \u003d window._taboola || [];\n_taboola.push({flush: true});\n\u003c/script\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e', + 'adomain': [ + 'example.xyz' + ], + 'cid': '15744349', + 'crid': '278195503434041083381', + 'w': 300, + 'h': 250, + 'lurl': 'http://us-trc.taboola.com/sample' + } + ], + 'seat': '14204545260' + } + ], + 'bidid': 'da43860a-4644-442a-b5e0-93f268cf8d19', + 'cur': 'USD' } }; @@ -335,28 +334,28 @@ describe('Taboola Adapter', function () { it('should return empty array if server response without seatbid', function () { const overriddenServerResponse = {...serverResponse}; - const seatbid = {...serverResponse.body.bidResponse.seatbid[0]}; - overriddenServerResponse.body.bidResponse.seatbid[0] = {}; + const seatbid = {...serverResponse.body.seatbid[0]}; + overriddenServerResponse.body.seatbid[0] = {}; const res = spec.interpretResponse(overriddenServerResponse, request) expect(res).to.be.an('array').that.is.empty - overriddenServerResponse.body.bidResponse.seatbid[0] = seatbid; + overriddenServerResponse.body.seatbid[0] = seatbid; }); it('should return empty array if server response without bids', function () { const overriddenServerResponse = {...serverResponse}; - const bid = [...serverResponse.body.bidResponse.seatbid[0].bid]; - overriddenServerResponse.body.bidResponse.seatbid[0].bid = {}; + const bid = [...serverResponse.body.seatbid[0].bid]; + overriddenServerResponse.body.seatbid[0].bid = {}; const res = spec.interpretResponse(overriddenServerResponse, request) expect(res).to.be.an('array').that.is.empty - overriddenServerResponse.body.bidResponse.seatbid[0].bid = bid; + overriddenServerResponse.body.seatbid[0].bid = bid; }); it('should interpret display response', function () { - const [bid] = serverResponse.body.bidResponse.seatbid[0].bid; + const [bid] = serverResponse.body.seatbid[0].bid; const expectedRes = [ { requestId: request.bids[0].bidId, @@ -364,7 +363,7 @@ describe('Taboola Adapter', function () { creativeId: bid.crid, ttl: 360, netRevenue: false, - currency: serverResponse.body.bidResponse.cur, + currency: serverResponse.body.cur, mediaType: 'banner', ad: bid.adm, width: bid.w, From 4e4ff4af384339923fda6609e5904602aa45b570 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 9 May 2022 15:31:21 +0300 Subject: [PATCH 16/30] fix tests --- test/spec/modules/taboolaBidAdapter_spec.js | 30 +++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 86e32843228..070d6637aa2 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -4,6 +4,16 @@ import {config} from '../../../src/config' import * as utils from '../../../src/utils' describe('Taboola Adapter', function () { + let hasLocalStorage, cookiesAreEnabled, getDataFromLocalStorage, localStorageIsEnabled, getCookie; + + before(() => { + hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); + cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); + getCookie = sinon.stub(userData.storageManager, 'getCookie'); + getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); + localStorageIsEnabled = sinon.stub(userData.storageManager, 'localStorageIsEnabled'); + }); + const commonBidRequest = { bidder: 'taboola', params: { @@ -196,8 +206,9 @@ describe('Taboola Adapter', function () { describe('handle userid ', function () { it('should get user id from local storage', function () { - const getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); getDataFromLocalStorage.returns(51525152); + hasLocalStorage.returns(true); + localStorageIsEnabled.returns(true); const bidderRequest = { ...commonBidderRequest, @@ -206,16 +217,17 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], bidderRequest); const resData = JSON.parse(res.data); expect(resData.user.buyeruid).to.equal(51525152); + getDataFromLocalStorage.restore(); + hasLocalStorage.restore(); + localStorageIsEnabled.restore(); }); it('should get user id from cookie if local storage isn`t defined', function () { - const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); - const getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); - const getCookie = sinon.stub(userData.storageManager, 'getCookie'); - getDataFromLocalStorage.returns(51525152); hasLocalStorage.returns(false); + localStorageIsEnabled.returns(false); + cookiesAreEnabled.returns(true); getCookie.returns('taboola%20global%3Auser-id=12121212'); const bidderRequest = { @@ -223,17 +235,16 @@ describe('Taboola Adapter', function () { }; const res = spec.buildRequests([defaultBidRequest], bidderRequest); const resData = JSON.parse(res.data); + expect(resData.user.buyeruid).to.equal('12121212'); getDataFromLocalStorage.restore(); hasLocalStorage.restore(); + cookiesAreEnabled.restore(); getCookie.restore(); }); it('should get user id from TRC if local storage and cookie isn`t defined', function () { - const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); - const cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); - hasLocalStorage.returns(false); cookiesAreEnabled.returns(false); @@ -254,9 +265,6 @@ describe('Taboola Adapter', function () { }); it('should get user id to be 0 if cookie, local storage, TRC isn`t defined', function () { - const hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); - const cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); - hasLocalStorage.returns(false); cookiesAreEnabled.returns(false); From 9f972224e39237cd25d9fcfc11f0f08365c9825e Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 9 May 2022 21:34:44 +0300 Subject: [PATCH 17/30] fix tests - run stubs on each test --- test/spec/modules/taboolaBidAdapter_spec.js | 33 +++++++++------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 070d6637aa2..f1522e72fa9 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -6,7 +6,7 @@ import * as utils from '../../../src/utils' describe('Taboola Adapter', function () { let hasLocalStorage, cookiesAreEnabled, getDataFromLocalStorage, localStorageIsEnabled, getCookie; - before(() => { + beforeEach(() => { hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); getCookie = sinon.stub(userData.storageManager, 'getCookie'); @@ -14,6 +14,14 @@ describe('Taboola Adapter', function () { localStorageIsEnabled = sinon.stub(userData.storageManager, 'localStorageIsEnabled'); }); + afterEach(() => { + hasLocalStorage.restore(); + cookiesAreEnabled.restore(); + getCookie.restore(); + getDataFromLocalStorage.restore(); + localStorageIsEnabled.restore(); + }) + const commonBidRequest = { bidder: 'taboola', params: { @@ -114,7 +122,7 @@ describe('Taboola Adapter', function () { 'page': commonBidderRequest.refererInfo.canonicalUrl, 'ref': commonBidderRequest.refererInfo.referer, 'publisher': {'id': commonBidRequest.params.publisherId}, - 'content': {'language': 'en-US'} + 'content': {'language': navigator.language} }, 'device': {'ua': navigator.userAgent}, 'source': {'fd': 1}, @@ -127,10 +135,10 @@ describe('Taboola Adapter', function () { 'regs': {'coppa': 0, 'ext': {}} }; - const res = spec.buildRequests([defaultBidRequest], commonBidderRequest) + const res = spec.buildRequests([defaultBidRequest], commonBidderRequest); - expect(res.url).to.equal(`${END_POINT_URL}/${commonBidRequest.params.publisherId}`) - expect(res.data).to.deep.equal(JSON.stringify(expectedData)) + expect(res.url).to.equal(`${END_POINT_URL}/${commonBidRequest.params.publisherId}`); + expect(res.data).to.deep.equal(JSON.stringify(expectedData)); }) it('should pass optional parameters in request', function () { @@ -217,10 +225,6 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], bidderRequest); const resData = JSON.parse(res.data); expect(resData.user.buyeruid).to.equal(51525152); - - getDataFromLocalStorage.restore(); - hasLocalStorage.restore(); - localStorageIsEnabled.restore(); }); it('should get user id from cookie if local storage isn`t defined', function () { @@ -237,16 +241,12 @@ describe('Taboola Adapter', function () { const resData = JSON.parse(res.data); expect(resData.user.buyeruid).to.equal('12121212'); - - getDataFromLocalStorage.restore(); - hasLocalStorage.restore(); - cookiesAreEnabled.restore(); - getCookie.restore(); }); it('should get user id from TRC if local storage and cookie isn`t defined', function () { hasLocalStorage.returns(false); cookiesAreEnabled.returns(false); + localStorageIsEnabled.returns(false); window.TRC = { user_id: 31313131 @@ -259,8 +259,6 @@ describe('Taboola Adapter', function () { const resData = JSON.parse(res.data); expect(resData.user.buyeruid).to.equal(31313131); - hasLocalStorage.restore(); - cookiesAreEnabled.restore(); delete window.TRC; }); @@ -274,9 +272,6 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([defaultBidRequest], bidderRequest); const resData = JSON.parse(res.data); expect(resData.user.buyeruid).to.equal(0); - - hasLocalStorage.restore(); - cookiesAreEnabled.restore(); }); it('should set buyeruid to be 0 if it`s a new user', function () { From 40a0cf62a8142baf0f2609f1a1476ab089b96a12 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 9 May 2022 21:45:38 +0300 Subject: [PATCH 18/30] rerun because of another adapter flaky test --- test/spec/modules/taboolaBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index f1522e72fa9..7f1b1feb1f0 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -257,7 +257,7 @@ describe('Taboola Adapter', function () { } const res = spec.buildRequests([defaultBidRequest], bidderRequest); const resData = JSON.parse(res.data); - expect(resData.user.buyeruid).to.equal(31313131); + expect(resData.user.buyeruid).to.equal(window.TRC.user_id); delete window.TRC; }); From 07a150815a15701eba98c846aa1800b273e39531 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 9 May 2022 21:59:01 +0300 Subject: [PATCH 19/30] rerun because of another adapter flaky test --- test/spec/modules/taboolaBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 7f1b1feb1f0..994b3c2e35f 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -249,7 +249,7 @@ describe('Taboola Adapter', function () { localStorageIsEnabled.returns(false); window.TRC = { - user_id: 31313131 + user_id: 31313132 }; const bidderRequest = { From 6f734854650087a428f1907afde091e4e3f1b0ba Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 10 May 2022 16:23:31 +0300 Subject: [PATCH 20/30] fix cors issue, switch between height, width position --- modules/taboolaBidAdapter.js | 9 ++++++--- test/spec/modules/taboolaBidAdapter_spec.js | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index cb6a6048d7f..578a94039fe 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -145,7 +145,10 @@ export const spec = { url, method: 'POST', data: JSON.stringify(request), - bids: validBidRequests + bids: validBidRequests, + options: { + withCredentials: false + }, }; }, interpretResponse: (serverResponse, {bids}) => { @@ -202,8 +205,8 @@ function getSizes(sizes) { return { format: sizes.map(size => { return { - h: size[0], - w: size[1] + w: size[0], + h: size[1] } }) } diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 994b3c2e35f..39dd1f9105b 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -102,12 +102,12 @@ describe('Taboola Adapter', function () { 'id': 1, 'banner': { format: [{ - h: displayBidRequestParams.sizes[0][0], - w: displayBidRequestParams.sizes[0][1] + w: displayBidRequestParams.sizes[0][0], + h: displayBidRequestParams.sizes[0][1] }, { - h: displayBidRequestParams.sizes[1][0], - w: displayBidRequestParams.sizes[1][1] + w: displayBidRequestParams.sizes[1][0], + h: displayBidRequestParams.sizes[1][1] } ] }, From c13e0c20fc9f774ff62a5f87e587766dc085d1a0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 May 2022 09:31:34 +0300 Subject: [PATCH 21/30] update badv, bcat to be based in the ortb2 to support prebid 7 new protocols + update Ut --- modules/taboolaBidAdapter.js | 11 ++++++++--- test/spec/modules/taboolaBidAdapter_spec.js | 9 +++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 578a94039fe..f93dd39a484 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -100,7 +100,7 @@ export const spec = { buildRequests: (validBidRequests, bidderRequest) => { const [bidRequest] = validBidRequests; const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; - const {bcat = [], badv = [], publisherId} = bidRequest.params; + const {publisherId} = bidRequest.params; const site = getSiteProperties(bidRequest.params, refererInfo); const device = {ua: navigator.userAgent}; const imps = getImps(validBidRequests); @@ -126,6 +126,11 @@ export const spec = { regs.coppa = 1 } + const ortb2 = config.getConfig('ortb2') || { + badv: [], + bcat: [] + }; + const request = { id: bidderRequest.auctionId, imp: imps, @@ -133,8 +138,8 @@ export const spec = { device, source: {fd: 1}, tmax: bidderRequest.timeout, - bcat, - badv, + bcat: ortb2.bcat, + badv: ortb2.badv, user, regs }; diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 39dd1f9105b..cbc6b4cd6fd 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -143,11 +143,16 @@ describe('Taboola Adapter', function () { it('should pass optional parameters in request', function () { const optionalParams = { - badv: ['adadadbcd.com'], - bcat: ['IAB25', 'IAB7-39'], + bidfloor: 0.25, bidfloorcur: 'EUR' } + + config.setConfig({ortb2: { + badv: ['adadadbcd.com'], + bcat: ['IAB25', 'IAB7-39'] + }}); + const bidRequest = { ...defaultBidRequest, params: {...commonBidRequest.params, ...optionalParams} From 1a81f33c2da619f8e73929e3fe40e1993b6d60a7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 May 2022 09:44:06 +0300 Subject: [PATCH 22/30] retry run circleci --- test/spec/modules/taboolaBidAdapter_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index cbc6b4cd6fd..795a436949d 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -143,7 +143,6 @@ describe('Taboola Adapter', function () { it('should pass optional parameters in request', function () { const optionalParams = { - bidfloor: 0.25, bidfloorcur: 'EUR' } From 425281ff9d8d312b6cb8ed026fa5289d20234066 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 May 2022 09:53:13 +0300 Subject: [PATCH 23/30] retry run circleci --- test/spec/modules/taboolaBidAdapter_spec.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 795a436949d..58e872aabb4 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -145,7 +145,7 @@ describe('Taboola Adapter', function () { const optionalParams = { bidfloor: 0.25, bidfloorcur: 'EUR' - } + }; config.setConfig({ortb2: { badv: ['adadadbcd.com'], @@ -155,14 +155,14 @@ describe('Taboola Adapter', function () { const bidRequest = { ...defaultBidRequest, params: {...commonBidRequest.params, ...optionalParams} - } + }; - const res = spec.buildRequests([bidRequest], commonBidderRequest) - const resData = JSON.parse(res.data) - expect(resData.bcat).to.deep.equal(['IAB25', 'IAB7-39']) - expect(resData.badv).to.deep.equal(['adadadbcd.com']) - expect(resData.imp[0].bidfloor).to.deep.equal(0.25) - expect(resData.imp[0].bidfloorcur).to.deep.equal('EUR') + const res = spec.buildRequests([bidRequest], commonBidderRequest); + const resData = JSON.parse(res.data); + expect(resData.bcat).to.deep.equal(['IAB25', 'IAB7-39']); + expect(resData.badv).to.deep.equal(['adadadbcd.com']); + expect(resData.imp[0].bidfloor).to.deep.equal(0.25); + expect(resData.imp[0].bidfloorcur).to.deep.equal('EUR'); }); it('should pass bidder timeout', function () { From 3196a745300a7f3a2ebcb55b9610e007fe96ec65 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 May 2022 10:04:47 +0300 Subject: [PATCH 24/30] pull from upstream update md (placement + pub ) --- modules/taboolaBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/taboolaBidAdapter.md b/modules/taboolaBidAdapter.md index a3cd1d9261b..a4213355049 100644 --- a/modules/taboolaBidAdapter.md +++ b/modules/taboolaBidAdapter.md @@ -26,8 +26,8 @@ The Taboola Bidding adapter requires setup before beginning. Please contact us o bids: [{ bidder: 'taboola', params: { - tagId: 'Placement Name', - publisherId: 'your-publisher-id', + tagId: 'tester-placement', // Placement Name + publisherId: 'tester-pub', // your-publisher-id bidfloor: 0.25, // Optional - default is null bcat: ['IAB1-1'], // Optional - default is [] badv: ['example.com'] // Optional - default is [] From 637c11f2fff6a056c4703a6208d140b2ad1e0d23 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 22 May 2022 11:59:43 +0300 Subject: [PATCH 25/30] update badv, bcat UT --- test/spec/modules/taboolaBidAdapter_spec.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 58e872aabb4..d3b22b7291c 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -147,11 +147,6 @@ describe('Taboola Adapter', function () { bidfloorcur: 'EUR' }; - config.setConfig({ortb2: { - badv: ['adadadbcd.com'], - bcat: ['IAB25', 'IAB7-39'] - }}); - const bidRequest = { ...defaultBidRequest, params: {...commonBidRequest.params, ...optionalParams} @@ -159,8 +154,6 @@ describe('Taboola Adapter', function () { const res = spec.buildRequests([bidRequest], commonBidderRequest); const resData = JSON.parse(res.data); - expect(resData.bcat).to.deep.equal(['IAB25', 'IAB7-39']); - expect(resData.badv).to.deep.equal(['adadadbcd.com']); expect(resData.imp[0].bidfloor).to.deep.equal(0.25); expect(resData.imp[0].bidfloorcur).to.deep.equal('EUR'); }); From 7ae29954d88b1668ae0dd62c214fc3cc5dd3c059 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 23 May 2022 14:02:24 +0300 Subject: [PATCH 26/30] rerun build --- test/spec/modules/taboolaBidAdapter_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index d3b22b7291c..998bf2ef560 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -163,9 +163,9 @@ describe('Taboola Adapter', function () { ...commonBidderRequest, timeout: 500 } - const res = spec.buildRequests([defaultBidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.tmax).to.equal(500) + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.tmax).to.equal(500); }); describe('handle privacy segments when building request', function () { From 8b564064770304be81b02ae68e6b77c5008171ba Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 23 May 2022 14:41:11 +0300 Subject: [PATCH 27/30] rerun build --- test/spec/modules/taboolaBidAdapter_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 998bf2ef560..30553bd9190 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -193,9 +193,9 @@ describe('Taboola Adapter', function () { }, uspConsent: 'consentString' } - const res = spec.buildRequests([defaultBidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.regs.ext.us_privacy).to.equal('consentString') + const res = spec.buildRequests([defaultBidRequest], bidderRequest); + const resData = JSON.parse(res.data); + expect(resData.regs.ext.us_privacy).to.equal('consentString'); }); it('should pass coppa consent', function () { From fdc1ca34cc0ae92b79eb4e71c095b5bc886d16c2 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 26 May 2022 19:45:00 +0300 Subject: [PATCH 28/30] support storageAllowed restriction on unit tests for prebid 7 --- test/spec/modules/taboolaBidAdapter_spec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 30553bd9190..1178d4062c4 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -12,6 +12,12 @@ describe('Taboola Adapter', function () { getCookie = sinon.stub(userData.storageManager, 'getCookie'); getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); localStorageIsEnabled = sinon.stub(userData.storageManager, 'localStorageIsEnabled'); + + $$PREBID_GLOBAL$$.bidderSettings = { + taboola: { + storageAllowed: true + } + }; }); afterEach(() => { From 3ea96c1cb17727b64627d85f7a95921a33a6f085 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 26 May 2022 19:54:55 +0300 Subject: [PATCH 29/30] add it also to the aftereach --- test/spec/modules/taboolaBidAdapter_spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 1178d4062c4..aae2f2ea507 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -26,6 +26,9 @@ describe('Taboola Adapter', function () { getCookie.restore(); getDataFromLocalStorage.restore(); localStorageIsEnabled.restore(); + + $$PREBID_GLOBAL$$.bidderSettings = { + }; }) const commonBidRequest = { From c525fc1f87ec3bc9227d05962777508b2ed0d3ef Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 26 May 2022 19:55:45 +0300 Subject: [PATCH 30/30] add it also to the aftereach --- test/spec/modules/taboolaBidAdapter_spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index aae2f2ea507..1c4f0fa4c32 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -27,8 +27,7 @@ describe('Taboola Adapter', function () { getDataFromLocalStorage.restore(); localStorageIsEnabled.restore(); - $$PREBID_GLOBAL$$.bidderSettings = { - }; + $$PREBID_GLOBAL$$.bidderSettings = {}; }) const commonBidRequest = {