Skip to content

Commit

Permalink
Loglylift Bid Adapter: add new bid adapter (#7761)
Browse files Browse the repository at this point in the history
* make buildRequests

* remove useless code

* change ENDPOINTN_URL

* add spec test

* format code

* fix serverResponse

* add test

* add overview

* fix the bid adpter to adapt the actual response

* treat adspotId as integer

* add getUserSyncs

* add serverResponses.length > 0 on 'if' condition

* fix typo

* use test adspotId which has a test ad

* fix prebidJsVersion test

* adapt advertiserDomains
  • Loading branch information
HashimotoLogly authored Dec 13, 2021
1 parent 72921a3 commit e722a30
Show file tree
Hide file tree
Showing 3 changed files with 306 additions and 0 deletions.
79 changes: 79 additions & 0 deletions modules/loglyliftBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { config } from '../src/config.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { NATIVE } from '../src/mediaTypes.js';

const BIDDER_CODE = 'loglylift';
const ENDPOINT_URL = 'https://bid.logly.co.jp/prebid/client/v1';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [NATIVE],

isBidRequestValid: function (bid) {
return !!(bid.params && bid.params.adspotId);
},

buildRequests: function (bidRequests, bidderRequest) {
const requests = [];
for (let i = 0, len = bidRequests.length; i < len; i++) {
const request = {
method: 'POST',
url: ENDPOINT_URL + '?adspot_id=' + bidRequests[i].params.adspotId,
data: JSON.stringify(newBidRequest(bidRequests[i], bidderRequest)),
options: {},
bidderRequest
};
requests.push(request);
}
return requests;
},

interpretResponse: function (serverResponse, { bidderRequest }) {
serverResponse = serverResponse.body;
const bidResponses = [];
if (!serverResponse || serverResponse.error) {
return bidResponses;
}
serverResponse.bids.forEach(function (bid) {
bidResponses.push(bid);
})
return bidResponses;
},

getUserSyncs: function (syncOptions, serverResponses) {
const syncs = [];

if (syncOptions.iframeEnabled && serverResponses.length > 0) {
syncs.push({
type: 'iframe',
url: 'https://sync.logly.co.jp/sync/sync.html'
});
}
return syncs;
}

};

function newBidRequest(bid, bidderRequest) {
const currencyObj = config.getConfig('currency');
const currency = (currencyObj && currencyObj.adServerCurrency) || 'USD';

return {
auctionId: bid.auctionId,
bidderRequestId: bid.bidderRequestId,
transactionId: bid.transactionId,
adUnitCode: bid.adUnitCode,
bidId: bid.bidId,
mediaTypes: bid.mediaTypes,
params: bid.params,
prebidJsVersion: '$prebid.version$',
url: window.location.href,
domain: config.getConfig('publisherDomain'),
referer: bidderRequest.refererInfo.referer,
auctionStartTime: bidderRequest.auctionStart,
currency: currency,
timeout: config.getConfig('bidderTimeout')
};
}

registerBidder(spec);
55 changes: 55 additions & 0 deletions modules/loglyliftBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Overview
```
Module Name: LOGLY lift for Publisher
Module Type: Bidder Adapter
Maintainer: dev@logly.co.jp
```

# Description
Module that connects to Logly's demand sources.
Currently module supports only native mediaType.

# Test Parameters
```
var adUnits = [
// Native adUnit
{
code: 'test-native-code',
sizes: [[1, 1]],
mediaTypes: {
native: {
title: {
required: true
},
image: {
required: true
},
sponsoredBy: {
required: true
}
}
},
bids: [{
bidder: 'loglylift',
params: {
adspotId: 4302078
}
}]
}
];
```

# UserSync example

```
pbjs.setConfig({
userSync: {
filterSettings: {
iframe: {
bidders: '*', // '*' represents all bidders
filter: 'include'
}
}
}
});
```
172 changes: 172 additions & 0 deletions test/spec/modules/loglyliftBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { expect } from 'chai';
import { spec } from '../../../modules/loglyliftBidAdapter';
import * as utils from 'src/utils.js';

describe('loglyliftBidAdapter', function () {
const nativeBidRequests = [{
bidder: 'loglylift',
bidId: '254304ac29e265',
params: {
adspotId: 16
},
adUnitCode: '/19968336/prebid_native_example_1',
transactionId: '10aee457-617c-4572-ab5b-99df1d73ccb4',
sizes: [
[]
],
bidderRequestId: '15da3afd9632d7',
auctionId: 'f890b7d9-e787-4237-ac21-6d8554abac9f',
mediaTypes: {
native: {
body: {
required: true
},
icon: {
required: false
},
title: {
required: true
},
image: {
required: true
},
sponsoredBy: {
required: true
}
}
}
}];

const bidderRequest = {
refererInfo: {
referer: 'fakeReferer',
reachedTop: true,
numIframes: 1,
stack: []
},
auctionStart: 1632194172781,
bidderCode: 'loglylift',
bidderRequestId: '15da3afd9632d7',
auctionId: 'f890b7d9-e787-4237-ac21-6d8554abac9f',
timeout: 3000
};

const nativeServerResponse = {
body: {
bids: [{
requestId: '254304ac29e265',
cpm: 10.123,
width: 360,
height: 360,
creativeId: '123456789',
currency: 'JPY',
netRevenue: true,
ttl: 30,
meta: {
advertiserDomains: ['advertiserexample.com']
},
native: {
clickUrl: 'https://dsp.logly.co.jp/click?ad=EXAMPECLICKURL',
image: {
url: 'https://cdn.logly.co.jp/images/000/194/300/normal.jpg',
width: '360',
height: '360'
},
impressionTrackers: [
'https://b.logly.co.jp/sorry.html'
],
sponsoredBy: 'logly',
title: 'Native Title',
}
}],
}
};

describe('isBidRequestValid', function () {
it('should return true if the adspotId parameter is present', function () {
expect(spec.isBidRequestValid(nativeBidRequests[0])).to.be.true;
});

it('should return false if the adspotId parameter is not present', function () {
let bidRequest = utils.deepClone(nativeBidRequests[0]);
delete bidRequest.params.adspotId;
expect(spec.isBidRequestValid(bidRequest)).to.be.false;
});
});

describe('buildRequests', function () {
it('should generate a valid single POST request for multiple bid requests', function () {
const request = spec.buildRequests(nativeBidRequests, bidderRequest)[0];
expect(request.method).to.equal('POST');
expect(request.url).to.equal('https://bid.logly.co.jp/prebid/client/v1?adspot_id=16');
expect(request.data).to.exist;

const data = JSON.parse(request.data);
expect(data.auctionId).to.equal(nativeBidRequests[0].auctionId);
expect(data.bidderRequestId).to.equal(nativeBidRequests[0].bidderRequestId);
expect(data.transactionId).to.equal(nativeBidRequests[0].transactionId);
expect(data.adUnitCode).to.equal(nativeBidRequests[0].adUnitCode);
expect(data.bidId).to.equal(nativeBidRequests[0].bidId);
expect(data.mediaTypes).to.deep.equal(nativeBidRequests[0].mediaTypes);
expect(data.params).to.deep.equal(nativeBidRequests[0].params);
expect(data.prebidJsVersion).to.equal('6.5.0-pre');
expect(data.url).to.exist;
expect(data.domain).to.exist;
expect(data.referer).to.equal(bidderRequest.refererInfo.referer);
expect(data.auctionStartTime).to.equal(bidderRequest.auctionStart);
expect(data.currency).to.exist;
expect(data.timeout).to.equal(bidderRequest.timeout);
});
});

describe('interpretResponse', function () {
it('should return an empty array if an invalid response is passed', function () {
const interpretedResponse = spec.interpretResponse({}, {});
expect(interpretedResponse).to.be.an('array').that.is.empty;
});

it('should return valid response when passed valid server response', function () {
const request = spec.buildRequests(nativeBidRequests, bidderRequest)[0];
const interpretedResponse = spec.interpretResponse(nativeServerResponse, request);

expect(interpretedResponse).to.have.lengthOf(1);
expect(interpretedResponse[0].cpm).to.equal(nativeServerResponse.body.bids[0].cpm);
expect(interpretedResponse[0].width).to.equal(nativeServerResponse.body.bids[0].width);
expect(interpretedResponse[0].height).to.equal(nativeServerResponse.body.bids[0].height);
expect(interpretedResponse[0].creativeId).to.equal(nativeServerResponse.body.bids[0].creativeId);
expect(interpretedResponse[0].currency).to.equal(nativeServerResponse.body.bids[0].currency);
expect(interpretedResponse[0].netRevenue).to.equal(nativeServerResponse.body.bids[0].netRevenue);
expect(interpretedResponse[0].ttl).to.equal(nativeServerResponse.body.bids[0].ttl);
expect(interpretedResponse[0].native).to.deep.equal(nativeServerResponse.body.bids[0].native);
expect(interpretedResponse[0].meta.advertiserDomains[0]).to.equal(nativeServerResponse.body.bids[0].meta.advertiserDomains[0]);
});
});

describe('getUserSync tests', function () {
it('UserSync test : check type = iframe, check usermatch URL', function () {
const syncOptions = {
'iframeEnabled': true
}
let userSync = spec.getUserSyncs(syncOptions, [nativeServerResponse]);
expect(userSync[0].type).to.equal('iframe');
const USER_SYNC_URL = 'https://sync.logly.co.jp/sync/sync.html';
expect(userSync[0].url).to.equal(USER_SYNC_URL);
});

it('When iframeEnabled is false, no userSync should be returned', function () {
const syncOptions = {
'iframeEnabled': false
}
let userSync = spec.getUserSyncs(syncOptions, [nativeServerResponse]);
expect(userSync).to.be.an('array').that.is.empty;
});

it('When nativeServerResponses empty, no userSync should be returned', function () {
const syncOptions = {
'iframeEnabled': false
}
let userSync = spec.getUserSyncs(syncOptions, []);
expect(userSync).to.be.an('array').that.is.empty;
});
});
});

0 comments on commit e722a30

Please sign in to comment.