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

Invibes Bid Adapter : infinite scroll tcf #10764

Merged
56 changes: 50 additions & 6 deletions modules/invibesBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const CONSTANTS = {
SYNC_ENDPOINT: 'https://k.r66net.com/GetUserSync',
TIME_TO_LIVE: 300,
DEFAULT_CURRENCY: 'EUR',
PREBID_VERSION: 10,
PREBID_VERSION: 11,
METHOD: 'GET',
INVIBES_VENDOR_ID: 436,
USERID_PROVIDERS: ['pubcid', 'pubProvidedId', 'uid2', 'zeotapIdPlus', 'id5id'],
Expand Down Expand Up @@ -49,14 +49,36 @@ registerBidder(spec);
// some state info is required: cookie info, unique user visit id
const topWin = getTopMostWindow();
let invibes = topWin.invibes = topWin.invibes || {};
invibes.purposes = invibes.purposes || [false, false, false, false, false, false, false, false, false, false];
invibes.legitimateInterests = invibes.legitimateInterests || [false, false, false, false, false, false, false, false, false, false];
invibes.purposes = invibes.purposes || [false, false, false, false, false, false, false, false, false, false, false];
invibes.legitimateInterests = invibes.legitimateInterests || [false, false, false, false, false, false, false, false, false, false, false];
invibes.placementBids = invibes.placementBids || [];
invibes.pushedCids = invibes.pushedCids || {};
let preventPageViewEvent = false;
let isInfiniteScrollPage = false;
let isPlacementRefresh = false;
let _customUserSync;
let _disableUserSyncs;

function updateInfiniteScrollFlag() {
const { scrollHeight } = document.documentElement;

if (invibes.originalURL === undefined) {
invibes.originalURL = window.location.href;
return;
}

if (invibes.originalScrollHeight === undefined) {
invibes.originalScrollHeight = scrollHeight;
return;
}

const currentURL = window.location.href;

if (scrollHeight > invibes.originalScrollHeight && invibes.originalURL !== currentURL) {
isInfiniteScrollPage = true;
}
}

function isBidRequestValid(bid) {
if (typeof bid.params !== 'object') {
return false;
Expand Down Expand Up @@ -87,10 +109,24 @@ function buildRequest(bidRequests, bidderRequest) {
const _placementIds = [];
const _adUnitCodes = [];
let _customEndpoint, _userId, _domainId;
let _ivAuctionStart = bidderRequest.auctionStart || Date.now();
let _ivAuctionStart = Date.now();
window.invibes = window.invibes || {};
window.invibes.placementIds = window.invibes.placementIds || [];

if (isInfiniteScrollPage == false) {
updateInfiniteScrollFlag();
}

bidRequests.forEach(function (bidRequest) {
bidRequest.startTime = new Date().getTime();

if (window.invibes.placementIds.includes(bidRequest.params.placementId)) {
isPlacementRefresh = true;
}

window.invibes.placementIds.push(bidRequest.params.placementId);

_placementIds.push(bidRequest.params.placementId);
_placementIds.push(bidRequest.params.placementId);
_adUnitCodes.push(bidRequest.adUnitCode);
_domainId = _domainId || bidRequest.params.domainId;
Expand Down Expand Up @@ -138,6 +174,8 @@ function buildRequest(bidRequests, bidderRequest) {
tc: invibes.gdpr_consent,
isLocalStorageEnabled: storage.hasLocalStorage(),
preventPageViewEvent: preventPageViewEvent,
isPlacementRefresh: isPlacementRefresh,
isInfiniteScrollPage: isInfiniteScrollPage,
};

let lid = readFromLocalStorage('ivbsdid');
Expand Down Expand Up @@ -368,7 +406,9 @@ function addMeta(bidModelMeta) {
}

function generateRandomId() {
return (Math.round(Math.random() * 1e12)).toString(36).substring(0, 10);
return '10000000100040008000100000000000'.replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}

function getDocumentLocation(bidderRequest) {
Expand Down Expand Up @@ -568,7 +608,7 @@ function readGdprConsent(gdprConsent) {
}

let legitimateInterests = getLegitimateInterests(gdprConsent.vendorData);
tryCopyValueToArray(legitimateInterests, invibes.legitimateInterests, 10);
tryCopyValueToArray(legitimateInterests, invibes.legitimateInterests, purposesLength);

let invibesVendorId = CONSTANTS.INVIBES_VENDOR_ID.toString(10);
let vendorConsents = getVendorConsents(gdprConsent.vendorData);
Expand Down Expand Up @@ -621,6 +661,10 @@ function tryCopyValueToArray(value, target, length) {

function getPurposeConsentsCounter(vendorData) {
if (vendorData.purpose && vendorData.purpose.consents) {
if (vendorData.tcfPolicyVersion >= 4) {
return 11;
}

return 10;
}

Expand Down
99 changes: 99 additions & 0 deletions test/spec/modules/invibesBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,78 @@ describe('invibesBidAdapter:', function () {
}
];

let bidRequestsWithDuplicatedplacementId = [
{
bidId: 'b1',
bidder: BIDDER_CODE,
bidderRequestId: 'r1',
params: {
placementId: PLACEMENT_ID,
disableUserSyncs: false

},
adUnitCode: 'test-div1',
auctionId: 'a1',
sizes: [
[300, 250],
[400, 300],
[125, 125]
],
transactionId: 't1'
}, {
bidId: 'b2',
bidder: BIDDER_CODE,
bidderRequestId: 'r2',
params: {
placementId: PLACEMENT_ID,
disableUserSyncs: false
},
adUnitCode: 'test-div2',
auctionId: 'a2',
sizes: [
[300, 250],
[400, 300]
],
transactionId: 't2'
}
];

let bidRequestsWithUniquePlacementId = [
{
bidId: 'b1',
bidder: BIDDER_CODE,
bidderRequestId: 'r1',
params: {
placementId: 'PLACEMENT_ID_1',
disableUserSyncs: false

},
adUnitCode: 'test-div1',
auctionId: 'a1',
sizes: [
[300, 250],
[400, 300],
[125, 125]
],
transactionId: 't1'
}, {
bidId: 'b2',
bidder: BIDDER_CODE,
bidderRequestId: 'r2',
params: {
placementId: 'PLACEMENT_ID_2',
disableUserSyncs: false
},
adUnitCode: 'test-div2',
auctionId: 'a2',
sizes: [
[300, 250],
[400, 300]
],
transactionId: 't2'
}
];

let bidRequestsWithUserId = [
{
bidId: 'b1',
Expand Down Expand Up @@ -185,17 +257,44 @@ describe('invibesBidAdapter:', function () {
expect(request.data.preventPageViewEvent).to.be.false;
});

it('sends isPlacementRefresh as false when the placement ids are used for the first time', function () {
let request = spec.buildRequests(bidRequestsWithUniquePlacementId, bidderRequestWithPageInfo);
expect(request.data.isPlacementRefresh).to.be.false;
});

it('sends preventPageViewEvent as true on 2nd call', function () {
let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.data.preventPageViewEvent).to.be.true;
});

it('sends isPlacementRefresh as true on multi requests on the same placement id', function () {
let request = spec.buildRequests(bidRequestsWithDuplicatedplacementId, bidderRequestWithPageInfo);
expect(request.data.isPlacementRefresh).to.be.true;
});

it('sends isInfiniteScrollPage as false initially', function () {
let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.data.isInfiniteScrollPage).to.be.false;
});

it('sends isPlacementRefresh as true on multi requests multiple calls with the same placement id from second call', function () {
let request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.data.isInfiniteScrollPage).to.be.false;
let duplicatedRequest = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(duplicatedRequest.data.isPlacementRefresh).to.be.true;
});

it('sends bid request to ENDPOINT via GET', function () {
const request = spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(request.url).to.equal(ENDPOINT);
expect(request.method).to.equal('GET');
});

it('generates a visitId of length 32', function () {
spec.buildRequests(bidRequests, bidderRequestWithPageInfo);
expect(top.window.invibes.visitId.length).to.equal(32);
});

it('sends bid request to custom endpoint via GET', function () {
const request = spec.buildRequests([{
bidId: 'b1',
Expand Down