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

Sonobi Bid Adapter: add IntentIq Id #9649

Merged
merged 6 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
67 changes: 66 additions & 1 deletion modules/sonobiBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { config } from '../src/config.js';
import { Renderer } from '../src/Renderer.js';
import { userSync } from '../src/userSync.js';
import { bidderSettings } from '../src/bidderSettings.js';
const BIDDER_CODE = 'sonobi';
const STR_ENDPOINT = 'https://apex.go.sonobi.com/trinity.json';
const PAGEVIEW_ID = generateUUID();
Expand Down Expand Up @@ -49,6 +50,7 @@ export const spec = {

return true;
},

/**
* Make a server request from the list of BidRequests.
*
Expand Down Expand Up @@ -93,7 +95,7 @@ export const spec = {
'lib_name': 'prebid',
'lib_v': '$prebid.version$',
'us': 0,

'iqid': bidderSettings.get(BIDDER_CODE, 'storageAllowed') ? (loadOrCreateFirstPartyData()).pcid : null,
};

const fpd = bidderRequest.ortb2;
Expand Down Expand Up @@ -388,6 +390,69 @@ export function _getPlatform(context = window) {
}
return 'desktop';
}
/**
* Check for local storage
* Generate a UUID for the user if one does not exist in local storage
* Store the UUID in local storage for future use
* @return {object} firstPartyData - Data object containing first party information
*/
function loadOrCreateFirstPartyData() {
var localStorageEnabled;

var FIRST_PARTY_KEY = '_iiq_fdata';
var tryParse = function (data) {
try {
return JSON.parse(data);
} catch (err) {
return null;
}
};
var readData = function (key) {
if (hasLocalStorage()) {
return window.localStorage.getItem(key);
}
return null;
};
var hasLocalStorage = function () {
if (typeof localStorageEnabled != 'undefined') { return localStorageEnabled; } else {
try {
localStorageEnabled = !!window.localStorage;
return localStorageEnabled;
} catch (e) {
localStorageEnabled = false;
}
}
return false;
};
var generateGUID = function () {
var d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
};
var storeData = function (key, value) {
try {
if (typeof key === 'string' && key.startsWith('_iiq_fdata')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is unnecessary. storeData is only called once, and always with the FIRST_PARTY_KEY

if (value && hasLocalStorage()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also unnecessary to check if there is a value. The code already checks if firstPartyData is defined, and defines it if not prior to this function being called.

window.localStorage.setItem(key, value);
}
}
} catch (error) {

}
};
var firstPartyData = tryParse(readData(FIRST_PARTY_KEY));
if (!firstPartyData || !firstPartyData.pcid) {
var firstPartyId = generateGUID();
firstPartyData = { pcid: firstPartyId, pcidDate: Date.now() };
} else if (firstPartyData && !firstPartyData.pcidDate) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

firstPartyData will always be defined by this point and doesn't need to be checked

firstPartyData.pcidDate = Date.now();
}
storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData));
return firstPartyData;
};

function newRenderer(adUnitCode, bid, rendererOptions = {}) {
const renderer = Renderer.install({
Expand Down
8 changes: 8 additions & 0 deletions test/spec/modules/sonobiBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,13 @@ describe('SonobiBidAdapter', function () {
});

describe('.buildRequests', function () {
before(function () {
$$PREBID_GLOBAL$$.bidderSettings = {
sonobi: {
storageAllowed: true
}
};
});
let sandbox;
beforeEach(function () {
sinon.stub(userSync, 'canBidderRegisterSync');
Expand Down Expand Up @@ -398,6 +405,7 @@ describe('SonobiBidAdapter', function () {
expect(bidRequests.data.ref).not.to.be.empty
expect(bidRequests.data.s).not.to.be.empty
expect(bidRequests.data.pv).to.equal(bidRequestsPageViewID.data.pv)
expect(bidRequests.data.iqid).to.match(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the localStorage aspects be tested?

expect(bidRequests.data.hfa).to.not.exist
expect(bidRequests.bidderRequests).to.eql(bidRequest);
expect(bidRequests.data.ref).to.equal('overrides_top_window_location');
Expand Down