Skip to content

Commit 6928f2a

Browse files
committed
Common user-sync
1 parent ca4c66a commit 6928f2a

File tree

2 files changed

+125
-80
lines changed

2 files changed

+125
-80
lines changed

src/adapters/adkernel.js

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ const AdKernelAdapter = function AdKernelAdapter() {
4242
if (!(zone in _dispatch[host])) {
4343
_dispatch[host][zone] = [];
4444
}
45-
let imp = {'id': bidId, 'tagid': bid.placementCode, 'banner': {'w': size[0], 'h': size[1]}};
45+
let imp = {
46+
'id' : bidId,
47+
'tagid' : bid.placementCode,
48+
'banner' : {'w' : size[0], 'h' : size[1]}
49+
};
4650
if (utils.getTopWindowLocation().protocol === 'https:') {
4751
imp.secure = 1;
4852
}
@@ -55,21 +59,9 @@ const AdKernelAdapter = function AdKernelAdapter() {
5559
}
5660
if (syncedHostZones[host].indexOf(zone) === -1) {
5761
syncedHostZones[host].push(zone);
58-
insertUserSync(host, zone);
5962
}
6063
};
6164

62-
function insertUserSync(host, zone) {
63-
var iframe = utils.createInvisibleIframe();
64-
iframe.src = `//${host}/user-sync?zone=${zone}`;
65-
try {
66-
document.body.appendChild(iframe);
67-
} catch (error) {
68-
/* istanbul ignore next */
69-
utils.logError(error);
70-
}
71-
}
72-
7365
/**
7466
* Main function to get bid requests
7567
*/
@@ -82,6 +74,16 @@ const AdKernelAdapter = function AdKernelAdapter() {
8274
});
8375
});
8476
};
77+
/**
78+
* Build flat user-sync queue from host->zones mapping
79+
*/
80+
this.buildUserSyncQueue = function() {
81+
return Object.keys(syncedHostZones)
82+
.reduce((m, k) => {
83+
syncedHostZones[k].forEach((v) => m.push([k, v]));
84+
return m;
85+
}, []);
86+
};
8587

8688
function dispatchRtbRequest(host, zone, impressions, callback) {
8789
let url = buildEndpointUrl(host);
@@ -160,7 +162,10 @@ const AdKernelAdapter = function AdKernelAdapter() {
160162
dispatcher.addImp(bid);
161163
}
162164
});
163-
// process bids grouped into bidrequests
165+
//start async usersync
166+
processUserSyncQueue(dispatcher.buildUserSyncQueue());
167+
168+
// process bids grouped into bid requests
164169
dispatcher.dispatch((bid, imp, bidResp) => {
165170
let adUnitId = bid.placementCode;
166171
if (bidResp) {
@@ -216,16 +221,42 @@ const AdKernelAdapter = function AdKernelAdapter() {
216221
function createSite() {
217222
var location = utils.getTopWindowLocation();
218223
return {
219-
'domain': location.hostname,
220-
'page': location.href.split('?')[0]
224+
'domain' : location.hostname,
225+
'page' : location.href.split('?')[0]
221226
};
222227
}
223228

229+
/**
230+
* Recursively process user-sync queue
231+
*/
232+
function processUserSyncQueue(queue) {
233+
if (queue.length === 0) {
234+
return;
235+
}
236+
let entry = queue.pop();
237+
insertUserSync(entry[0], entry[1], () => processUserSyncQueue(queue));
238+
}
239+
240+
/**
241+
* Insert single iframe user-sync
242+
*/
243+
function insertUserSync(host, zone, callback) {
244+
var iframe = utils.createInvisibleIframe();
245+
iframe.src = `//sync.adkernel.com/user-sync?zone=${zone}&r=%2F%2F${host}%2Fuser-synced%3Fuid%3D%7BUID%7D`;
246+
utils.addEventHandler(iframe, 'load', callback);
247+
try {
248+
document.body.appendChild(iframe);
249+
} catch (error) {
250+
/* istanbul ignore next */
251+
utils.logError(error);
252+
}
253+
}
254+
224255
return {
225-
callBids: baseAdapter.callBids,
226-
setBidderCode: baseAdapter.setBidderCode,
227-
getBidderCode: baseAdapter.getBidderCode,
228-
createNew: AdKernelAdapter.createNew
256+
callBids : baseAdapter.callBids,
257+
setBidderCode : baseAdapter.setBidderCode,
258+
getBidderCode : baseAdapter.getBidderCode,
259+
createNew : AdKernelAdapter.createNew
229260
};
230261
};
231262

test/spec/adapters/adkernel_spec.js

Lines changed: 74 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,62 +6,63 @@ import bidmanager from 'src/bidmanager';
66
import CONSTANTS from 'src/constants.json';
77

88
describe('Adkernel adapter', () => {
9+
910
const bid1_zone1 = {
10-
bidder: 'adkernel',
11-
bidId: 'Bid_01',
12-
params: {zoneId: 1, host: 'rtb.adkernel.com'},
13-
placementCode: 'ad-unit-1',
14-
sizes: [[300, 250]]
15-
}, bid2_zone2 = {
16-
bidder: 'adkernel',
17-
bidId: 'Bid_02',
18-
params: {zoneId: 2, host: 'rtb.adkernel.com'},
19-
placementCode: 'ad-unit-2',
20-
sizes: [[728, 90]]
21-
}, bid3_host2 = {
22-
bidder: 'adkernel',
23-
bidId: 'Bid_02',
24-
params: {zoneId: 1, host: 'rtb-private.adkernel.com'},
25-
placementCode: 'ad-unit-2',
26-
sizes: [[728, 90]]
27-
}, bid_without_zone = {
28-
bidder: 'adkernel',
29-
bidId: 'Bid_W',
30-
params: {host: 'rtb-private.adkernel.com'},
31-
placementCode: 'ad-unit-1',
32-
sizes: [[728, 90]]
33-
}, bid_without_host = {
34-
bidder: 'adkernel',
35-
bidId: 'Bid_W',
36-
params: {zoneId: 1},
37-
placementCode: 'ad-unit-1',
38-
sizes: [[728, 90]]
39-
};
11+
bidder: 'adkernel',
12+
bidId: 'Bid_01',
13+
params: {zoneId: 1, host: 'rtb.adkernel.com'},
14+
placementCode: 'ad-unit-1',
15+
sizes: [[300, 250]]
16+
}, bid2_zone2 = {
17+
bidder: 'adkernel',
18+
bidId: 'Bid_02',
19+
params: {zoneId: 2, host: 'rtb.adkernel.com'},
20+
placementCode: 'ad-unit-2',
21+
sizes: [[728, 90]]
22+
}, bid3_host2 = {
23+
bidder: 'adkernel',
24+
bidId: 'Bid_02',
25+
params: {zoneId: 1, host: 'rtb-private.adkernel.com'},
26+
placementCode: 'ad-unit-2',
27+
sizes: [[728, 90]]
28+
}, bid_without_zone = {
29+
bidder: 'adkernel',
30+
bidId: 'Bid_W',
31+
params: {host: 'rtb-private.adkernel.com'},
32+
placementCode: 'ad-unit-1',
33+
sizes: [[728, 90]]
34+
}, bid_without_host = {
35+
bidder: 'adkernel',
36+
bidId: 'Bid_W',
37+
params: {zoneId: 1},
38+
placementCode: 'ad-unit-1',
39+
sizes: [[728, 90]]
40+
};
4041

4142
const bidResponse1 = {
42-
'id': 'bid1',
43-
'seatbid': [{
44-
'bid': [{
45-
'id': '1',
46-
'impid': 'Bid_01',
47-
'price': 3.01,
48-
'nurl': 'https://rtb.com/win?i=ZjKoPYSFI3Y_0',
49-
'adm': '<!-- admarkup here -->'
50-
}]
51-
}],
52-
'cur': 'USD'
53-
}, bidResponse2 = {
54-
'id': 'bid2',
55-
'seatbid': [{
56-
'bid': [{
57-
'id': '2',
58-
'impid': 'Bid_02',
59-
'price': 1.31,
60-
'adm': '<!-- admarkup here -->'
61-
}]
62-
}],
63-
'cur': 'USD'
64-
};
43+
'id': 'bid1',
44+
'seatbid': [{
45+
'bid': [{
46+
'id': '1',
47+
'impid': 'Bid_01',
48+
'price': 3.01,
49+
'nurl': 'https://rtb.com/win?i=ZjKoPYSFI3Y_0',
50+
'adm': '<!-- admarkup here -->'
51+
}]
52+
}],
53+
'cur': 'USD'
54+
}, bidResponse2 = {
55+
'id': 'bid2',
56+
'seatbid': [{
57+
'bid': [{
58+
'id': '2',
59+
'impid': 'Bid_02',
60+
'price': 1.31,
61+
'adm': '<!-- admarkup here -->'
62+
}]
63+
}],
64+
'cur': 'USD'
65+
};
6566

6667
let adapter,
6768
sandbox,
@@ -85,6 +86,7 @@ describe('Adkernel adapter', () => {
8586
}
8687

8788
describe('input parameters validation', () => {
89+
8890
let spy;
8991

9092
beforeEach(() => {
@@ -114,6 +116,7 @@ describe('Adkernel adapter', () => {
114116
});
115117

116118
describe('request building', () => {
119+
117120
let bidRequest;
118121

119122
beforeEach(() => {
@@ -164,9 +167,11 @@ describe('Adkernel adapter', () => {
164167
expect(bidRequest.device).to.have.property('ip', 'caller');
165168
expect(bidRequest.device).to.have.property('ua', 'caller');
166169
})
170+
167171
});
168172

169173
describe('requests routing', () => {
174+
170175
it('should issue a request for each network', () => {
171176
ajaxStub.onFirstCall().callsArgWith(1, '')
172177
.onSecondCall().callsArgWith(1, '');
@@ -193,6 +198,7 @@ describe('Adkernel adapter', () => {
193198
});
194199

195200
describe('responses processing', () => {
201+
196202
beforeEach(() => {
197203
sandbox.stub(bidmanager, 'addBidResponse');
198204
});
@@ -238,26 +244,34 @@ describe('Adkernel adapter', () => {
238244
sandbox.spy(utils, 'createTrackPixelHtml');
239245
ajaxStub.onCall(0).callsArgWith(1, JSON.stringify(bidResponse1));
240246
doRequest([bid1_zone1]);
241-
expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD);
242247
expect(utils.createTrackPixelHtml.calledOnce);
243-
let result = pbjs.getBidResponsesForAdUnitCode(bid1_zone1.placementCode);
248+
expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD);
244249
let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1';
245-
expect(result.bids[0].ad).to.include(expectedNurl);
250+
expect(bidmanager.addBidResponse.firstCall.args[1].ad).to.include(expectedNurl);
246251
});
247252

248253
it('should perform usersync for each unique host/zone combination', () => {
249254
ajaxStub.callsArgWith(1, '');
250-
const expectedSyncUrls = ['http://rtb.adkernel.com/user-sync?zone=1', 'http://rtb.adkernel.com/user-sync?zone=2',
251-
'http://rtb-private.adkernel.com/user-sync?zone=1'];
252-
sandbox.spy(utils, 'createInvisibleIframe');
255+
const expectedSyncUrls = ['//sync.adkernel.com/user-sync?zone=1&r=%2F%2Frtb-private.adkernel.com%2Fuser-synced%3Fuid%3D%7BUID%7D',
256+
'//sync.adkernel.com/user-sync?zone=2&r=%2F%2Frtb.adkernel.com%2Fuser-synced%3Fuid%3D%7BUID%7D',
257+
'//sync.adkernel.com/user-sync?zone=1&r=%2F%2Frtb.adkernel.com%2Fuser-synced%3Fuid%3D%7BUID%7D'];
258+
let userSyncUrls = [];
259+
sandbox.stub(utils, 'createInvisibleIframe', () => {
260+
return {};
261+
});
262+
sandbox.stub(utils, 'addEventHandler', (el, ev, cb) => {
263+
userSyncUrls.push(el.src);
264+
cb(); //instant callback
265+
});
253266
doRequest([bid1_zone1, bid2_zone2, bid2_zone2, bid3_host2]);
254267
expect(utils.createInvisibleIframe.calledThrice);
255-
let userSyncUrls = utils.createInvisibleIframe.returnValues.map(val => val.src);
256268
expect(userSyncUrls).to.be.eql(expectedSyncUrls);
257269
});
270+
258271
});
259272

260273
describe('adapter aliasing', () => {
274+
261275
const ALIAS_NAME = 'adkernelAlias';
262276

263277
it('should allow bidder code changing', () => {

0 commit comments

Comments
 (0)