Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharethrough Bid Adapter: Add First Party Data and Outstream Support #7857

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 12 additions & 17 deletions modules/sharethroughBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { generateUUID, deepAccess, inIframe } from '../src/utils.js';
import { deepAccess, generateUUID, inIframe } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { config } from '../src/config.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { createEidsArray } from './userId/eids.js';

const VERSION = '4.0.1';
const VERSION = '4.1.0';
const BIDDER_CODE = 'sharethrough';
const SUPPLY_ID = 'WYu2BXv1';

Expand All @@ -23,6 +23,7 @@ export const sharethroughAdapterSpec = {

buildRequests: (bidRequests, bidderRequest) => {
const timeout = config.getConfig('bidderTimeout');
const firstPartyData = config.getConfig('ortb2') || {};

const nonHttp = sharethroughInternal.getProtocol().indexOf('http') < 0;
const secure = nonHttp || (sharethroughInternal.getProtocol().indexOf('https') > -1);
Expand All @@ -35,12 +36,8 @@ export const sharethroughAdapterSpec = {
site: {
domain: window.location.hostname,
page: window.location.href,
ref: bidderRequest.refererInfo ? bidderRequest.refererInfo.referer || null : null,
},
user: {
ext: {
eids: userIdAsEids(bidRequests[0]),
},
ref: deepAccess(bidderRequest, 'refererInfo.referer'),
...firstPartyData.site,
},
device: {
ua: navigator.userAgent,
Expand All @@ -66,6 +63,10 @@ export const sharethroughAdapterSpec = {
test: 0,
};

req.user = nullish(firstPartyData.user, {});
if (!req.user.ext) req.user.ext = {};
req.user.ext.eids = userIdAsEids(bidRequests[0]);

if (bidderRequest.gdprConsent) {
const gdprApplies = bidderRequest.gdprConsent.gdprApplies === true;
req.regs.ext.gdpr = gdprApplies ? 1 : 0;
Expand All @@ -86,15 +87,9 @@ export const sharethroughAdapterSpec = {
impression.ext = { gpid: gpid };
}

// if request is for video, we only support instream
if (bidReq.mediaTypes && bidReq.mediaTypes.video && bidReq.mediaTypes.video.context === 'outstream') {
// return null so we can easily remove this imp from the array of imps that we send to adserver
return null;
}

if (bidReq.mediaTypes && bidReq.mediaTypes.video) {
const videoRequest = bidReq.mediaTypes.video;
const videoRequest = deepAccess(bidReq, 'mediaTypes.video');

if (videoRequest) {
// default playerSize, only change this if we know width and height are properly defined in the request
let [w, h] = [640, 360];
if (videoRequest.playerSize && videoRequest.playerSize[0] && videoRequest.playerSize[1]) {
Expand All @@ -117,9 +112,9 @@ export const sharethroughAdapterSpec = {
startdelay: nullish(videoRequest.startdelay, 0),
skipmin: nullish(videoRequest.skipmin, 0),
skipafter: nullish(videoRequest.skipafter, 0),
placement: videoRequest.context === 'instream' ? 1 : +deepAccess(videoRequest, 'placement', 4),
};

if (videoRequest.placement) impression.video.placement = videoRequest.placement;
if (videoRequest.delivery) impression.video.delivery = videoRequest.delivery;
if (videoRequest.companiontype) impression.video.companiontype = videoRequest.companiontype;
if (videoRequest.companionad) impression.video.companionad = videoRequest.companionad;
Expand Down
97 changes: 91 additions & 6 deletions test/spec/modules/sharethroughBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect } from 'chai';
import * as sinon from 'sinon';
import { sharethroughAdapterSpec, sharethroughInternal } from 'modules/sharethroughBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
import { config } from 'src/config';
Expand Down Expand Up @@ -157,7 +158,6 @@ describe('sharethrough adapter spec', function () {
startdelay: 42,
skipmin: 10,
skipafter: 20,
placement: 1,
delivery: 1,
companiontype: 'companion type',
companionad: 'companion ad',
Expand Down Expand Up @@ -205,6 +205,7 @@ describe('sharethrough adapter spec', function () {
expect(openRtbReq.cur).to.deep.equal(['USD']);
expect(openRtbReq.tmax).to.equal(242);

expect(Object.keys(openRtbReq.site)).to.have.length(3);
expect(openRtbReq.site.domain).not.to.be.undefined;
expect(openRtbReq.site.page).not.to.be.undefined;
expect(openRtbReq.site.ref).to.equal('https://referer.com');
Expand Down Expand Up @@ -256,6 +257,17 @@ describe('sharethrough adapter spec', function () {
});
});

describe('no referer provided', () => {
beforeEach(() => {
bidderRequest = {};
});

it('should set referer to undefined', () => {
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;
expect(openRtbReq.site.ref).to.be.undefined;
});
});

describe('regulation', () => {
describe('gdpr', () => {
it('should populate request accordingly when gdpr applies', () => {
Expand Down Expand Up @@ -419,17 +431,90 @@ describe('sharethrough adapter spec', function () {
expect(videoImp.startdelay).to.equal(0);
expect(videoImp.skipmin).to.equal(0);
expect(videoImp.skipafter).to.equal(0);
expect(videoImp.placement).to.be.undefined;
expect(videoImp.placement).to.equal(1);
expect(videoImp.delivery).to.be.undefined;
expect(videoImp.companiontype).to.be.undefined;
expect(videoImp.companionad).to.be.undefined;
});

it('should not return a video impression if context is outstream', () => {
bidRequests[1].mediaTypes.video.context = 'outstream';
const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
describe('outstream', () => {
it('should use placement value if provided', () => {
bidRequests[1].mediaTypes.video.context = 'outstream';
bidRequests[1].mediaTypes.video.placement = 3;

const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
const videoImp = builtRequest.data.imp[0].video;

expect(videoImp.placement).to.equal(3);
});

it('should default placement to 4 if not provided', () => {
bidRequests[1].mediaTypes.video.context = 'outstream';

const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
const videoImp = builtRequest.data.imp[0].video;

expect(videoImp.placement).to.equal(4);
});
});
});

describe('first party data', () => {
const firstPartyData = {
site: {
name: 'example',
keywords: 'power tools, drills',
search: 'drill',
content: {
userrating: '4',
},
ext: {
data: {
pageType: 'article',
category: 'repair',
},
},
},
user: {
yob: 1985,
gender: 'm',
ext: {
data: {
registered: true,
interests: ['cars'],
},
},
},
};

let configStub;

beforeEach(() => {
configStub = sinon.stub(config, 'getConfig');
configStub.withArgs('ortb2').returns(firstPartyData);
});

afterEach(() => {
configStub.restore();
});

it('should include first party data in open rtb request, site section', () => {
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;

expect(openRtbReq.site.name).to.equal(firstPartyData.site.name);
expect(openRtbReq.site.keywords).to.equal(firstPartyData.site.keywords);
expect(openRtbReq.site.search).to.equal(firstPartyData.site.search);
expect(openRtbReq.site.content).to.deep.equal(firstPartyData.site.content);
expect(openRtbReq.site.ext).to.deep.equal(firstPartyData.site.ext);
});

it('should include first party data in open rtb request, user section', () => {
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;

expect(builtRequest).to.be.undefined;
expect(openRtbReq.user.yob).to.equal(firstPartyData.user.yob);
expect(openRtbReq.user.gender).to.equal(firstPartyData.user.gender);
expect(openRtbReq.user.ext.data).to.deep.equal(firstPartyData.user.ext.data);
expect(openRtbReq.user.ext.eids).not.to.be.undefined;
});
});
});
Expand Down