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

IntentIq ID & Analytics Modules : manual reporting, bug fixes, refactoring #12314

Merged
merged 14 commits into from
Oct 23, 2024
Merged
10 changes: 10 additions & 0 deletions libraries/intentIqConstants/intentIqConstants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const FIRST_PARTY_KEY = '_iiq_fdata';

export const WITH_IIQ = 'A';
export const WITHOUT_IIQ = 'B';
export const NOT_YET_DEFINED = 'U';
export const OPT_OUT = 'O';
export const BLACK_LIST = 'L';
export const CLIENT_HINTS_KEY = '_iiq_ch';
export const EMPTY = 'EMPTY'
export const VERSION = 0.21
121 changes: 82 additions & 39 deletions modules/intentIqAnalyticsAdapter.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import { logInfo, logError, getWindowSelf, getWindowTop, getWindowLocation } from '../src/utils.js';
import {getWindowLocation, getWindowSelf, getWindowTop, logError, logInfo} from '../src/utils.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
import adapterManager from '../src/adapterManager.js';
import { ajax } from '../src/ajax.js';
import { getStorageManager } from '../src/storageManager.js';
import { config } from '../src/config.js';
import { EVENTS } from '../src/constants.js';
import { MODULE_TYPE_ANALYTICS } from '../src/activities/modules.js';
import { detectBrowser } from '../libraries/detectBrowserUtils/detectBrowserUtils.js';
import {ajax} from '../src/ajax.js';
import {getStorageManager} from '../src/storageManager.js';
import {config} from '../src/config.js';
import {EVENTS} from '../src/constants.js';
import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js';
import {detectBrowser} from '../libraries/detectBrowserUtils/detectBrowserUtils.js';
import {CLIENT_HINTS_KEY, FIRST_PARTY_KEY, VERSION} from '../libraries/intentIqConstants/intentIqConstants.js';

const MODULE_NAME = 'iiqAnalytics'
const analyticsType = 'endpoint';
const defaultUrl = 'https://reports.intentiq.com/report';
const storage = getStorageManager({ moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_NAME });
const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_NAME});
const prebidVersion = '$prebid.version$';
export const REPORTER_ID = Date.now() + '_' + getRandom(0, 1000);

const FIRST_PARTY_KEY = '_iiq_fdata';
const FIRST_PARTY_DATA_KEY = '_iiq_fdata';
const JSVERSION = 0.2

const PARAMS_NAMES = {
abTestGroup: 'abGroup',
pbPauseUntil: 'pbPauseUntil',
Expand Down Expand Up @@ -55,7 +52,7 @@ const PARAMS_NAMES = {
firstPartyId: 'pcid'
};

let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({ defaultUrl, analyticsType }), {
let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({defaultUrl, analyticsType}), {
initOptions: {
lsValueInitialized: false,
partner: null,
Expand All @@ -64,13 +61,16 @@ let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({ defaultUrl, analytics
dataInLs: null,
eidl: null,
lsIdsInitialized: false,
manualReport: false
manualWinReportEnabled: false
},
track({ eventType, args }) {
track({eventType, args}) {
switch (eventType) {
case BID_WON:
bidWon(args);
break;
case BID_REQUESTED:
defineGlobalVariableName();
break;
default:
break;
}
Expand All @@ -79,7 +79,8 @@ let iiqAnalyticsAnalyticsAdapter = Object.assign(adapter({ defaultUrl, analytics

// Events needed
const {
BID_WON
BID_WON,
BID_REQUESTED
} = EVENTS;

function readData(key) {
Expand Down Expand Up @@ -113,6 +114,7 @@ function initLsValues() {
iiqAnalyticsAnalyticsAdapter.initOptions.partner = iiqArr[0].params.partner;
}
iiqAnalyticsAnalyticsAdapter.initOptions.browserBlackList = typeof iiqArr[0].params.browserBlackList === 'string' ? iiqArr[0].params.browserBlackList.toLowerCase() : '';
iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled = iiqArr[0].params.manualWinReportEnabled || false
}
}

Expand All @@ -123,20 +125,27 @@ function initReadLsIds() {
if (iiqAnalyticsAnalyticsAdapter.initOptions.fpid) {
iiqAnalyticsAnalyticsAdapter.initOptions.currentGroup = iiqAnalyticsAnalyticsAdapter.initOptions.fpid.group;
}
let iData = readData(FIRST_PARTY_DATA_KEY + '_' + iiqAnalyticsAnalyticsAdapter.initOptions.partner);
if (iData) {
const partnerData = readData(FIRST_PARTY_KEY + '_' + iiqAnalyticsAnalyticsAdapter.initOptions.partner);
const clientsHints = readData(CLIENT_HINTS_KEY) || '';

if (partnerData) {
iiqAnalyticsAnalyticsAdapter.initOptions.lsIdsInitialized = true;
let pData = JSON.parse(iData);
let pData = JSON.parse(partnerData);
iiqAnalyticsAnalyticsAdapter.initOptions.terminationCause = pData.terminationCause
iiqAnalyticsAnalyticsAdapter.initOptions.dataInLs = pData.data;
iiqAnalyticsAnalyticsAdapter.initOptions.eidl = pData.eidl || -1;
}

iiqAnalyticsAnalyticsAdapter.initOptions.clientsHints = clientsHints
} catch (e) {
logError(e)
}
}

function bidWon(args) {
if (!iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized) { initLsValues(); }
function bidWon(args, isReportExternal) {
if (!iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized) {
initLsValues();
}

if (isNaN(iiqAnalyticsAnalyticsAdapter.initOptions.partner) || iiqAnalyticsAnalyticsAdapter.initOptions.partner == -1) return;

Expand All @@ -146,12 +155,31 @@ function bidWon(args) {
return;
}

if (iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized && !iiqAnalyticsAnalyticsAdapter.initOptions.lsIdsInitialized) { initReadLsIds(); }
if (!iiqAnalyticsAnalyticsAdapter.initOptions.manualReport) {
ajax(constructFullUrl(preparePayload(args, true)), undefined, null, { method: 'GET' });
if (iiqAnalyticsAnalyticsAdapter.initOptions.lsValueInitialized && !iiqAnalyticsAnalyticsAdapter.initOptions.lsIdsInitialized) {
initReadLsIds();
}
if ((isReportExternal && iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled) || (!isReportExternal && !iiqAnalyticsAnalyticsAdapter.initOptions.manualWinReportEnabled)) {
ajax(constructFullUrl(preparePayload(args, true)), undefined, null, {method: 'GET'});
logInfo('IIQ ANALYTICS -> BID WON')
return true;
}
return false;
}

function defineGlobalVariableName() {
function reportExternalWin(args) {
return bidWon(args, true)
}

logInfo('IIQ ANALYTICS -> BID WON')
let partnerId = 0
const userConfig = config.getConfig('userSync.userIds')

if (userConfig) {
const iiqArr = userConfig.filter(m => m.name == 'intentIqId');
if (iiqArr.length) partnerId = iiqArr[0].params.partner
}

window[`intentIqAnalyticsAdapter_${partnerId}`] = {reportExternalWin: reportExternalWin}
}

function getRandom(start, end) {
Expand All @@ -160,11 +188,11 @@ function getRandom(start, end) {

export function preparePayload(data) {
let result = getDefaultDataObject();

readData(FIRST_PARTY_KEY + '_' + iiqAnalyticsAnalyticsAdapter.initOptions.partner);
result[PARAMS_NAMES.partnerId] = iiqAnalyticsAnalyticsAdapter.initOptions.partner;
result[PARAMS_NAMES.prebidVersion] = prebidVersion;
result[PARAMS_NAMES.referrer] = getReferrer();

result[PARAMS_NAMES.terminationCause] = iiqAnalyticsAnalyticsAdapter.initOptions.terminationCause;
result[PARAMS_NAMES.abTestGroup] = iiqAnalyticsAnalyticsAdapter.initOptions.currentGroup;

result[PARAMS_NAMES.isInTestGroup] = iiqAnalyticsAnalyticsAdapter.initOptions.currentGroup == 'A';
Expand All @@ -187,13 +215,27 @@ function fillEidsData(result) {
}

function fillPrebidEventData(eventData, result) {
if (eventData.bidderCode) { result.bidderCode = eventData.bidderCode; }
if (eventData.cpm) { result.cpm = eventData.cpm; }
if (eventData.currency) { result.currency = eventData.currency; }
if (eventData.originalCpm) { result.originalCpm = eventData.originalCpm; }
if (eventData.originalCurrency) { result.originalCurrency = eventData.originalCurrency; }
if (eventData.status) { result.status = eventData.status; }
if (eventData.auctionId) { result.prebidAuctionId = eventData.auctionId; }
if (eventData.bidderCode) {
result.bidderCode = eventData.bidderCode;
}
if (eventData.cpm) {
result.cpm = eventData.cpm;
}
if (eventData.currency) {
result.currency = eventData.currency;
}
if (eventData.originalCpm) {
result.originalCpm = eventData.originalCpm;
}
if (eventData.originalCurrency) {
result.originalCurrency = eventData.originalCurrency;
}
if (eventData.status) {
result.status = eventData.status;
}
if (eventData.auctionId) {
result.prebidAuctionId = eventData.auctionId;
}

result.biddingPlatformId = 1;
result.partnerAuctionId = 'BW';
Expand All @@ -206,7 +248,7 @@ function getDefaultDataObject() {
'partnerAuctionId': 'BW',
'reportSource': 'pbjs',
'abGroup': 'U',
'jsversion': JSVERSION,
'jsversion': VERSION,
'partnerId': -1,
'biddingPlatformId': 1,
'idls': false,
Expand All @@ -224,18 +266,19 @@ function constructFullUrl(data) {
((iiqAnalyticsAnalyticsAdapter.initOptions && iiqAnalyticsAnalyticsAdapter.initOptions.fpid)
? '&iiqid=' + encodeURIComponent(iiqAnalyticsAnalyticsAdapter.initOptions.fpid.pcid) : '') +
'&agid=' + REPORTER_ID +
'&jsver=' + JSVERSION +
'&jsver=' + VERSION +
'&vrref=' + getReferrer() +
'&source=pbjs' +
'&payload=' + JSON.stringify(report)
'&payload=' + JSON.stringify(report) +
'&uh=' + iiqAnalyticsAnalyticsAdapter.initOptions.clientsHints
}

export function getReferrer() {
try {
if (getWindowSelf() === getWindowTop()) {
return getWindowLocation().href;
return encodeURIComponent(getWindowLocation().href);
} else {
return getWindowTop().location.href;
return encodeURIComponent(getWindowTop().location.href);
}
} catch (error) {
logError(`Error accessing location: ${error}`);
Expand Down
62 changes: 60 additions & 2 deletions modules/intentIqAnalyticsAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,70 @@ No registration for this module is required.

<B>IMPORTANT</B>: only effective when Intent IQ Universal ID module is installed and configured. [(How-To)](https://docs.prebid.org/dev-docs/modules/userid-submodules/intentiq.html)

No additional configuration for this module is required. We will use the configuration provided for Intent IQ Universal IQ module.

#### Example Configuration

```js
pbjs.enableAnalytics({
provider: 'iiqAnalytics'
});
```


### Manual Report Trigger with reportExternalWin

The reportExternalWin function allows for manual reporting, meaning that reports will not be sent automatically but only when triggered manually.

To enable this manual reporting functionality, you must set the manualWinReportEnabled parameter in Intent IQ Unified ID module configuration is true. Once enabled, reports can be manually triggered using the reportExternalWin function.


### Calling the reportExternalWin Function

To call the reportExternalWin function, you need to pass the partner_id parameter as shown in the example below:

```js
window.intentIqAnalyticsAdapter_[partner_id].reportExternalWin()
```
Example use with Partner ID = 123455

```js
window.intentIqAnalyticsAdapter_123455.reportExternalWin()
```

### Function Parameters

The reportExternalWin function takes an object containing auction win data. Below is an example of the object:

```js
var reportData = {
biddingPlatformId: 1, // Platform ID. The value 1 corresponds to PreBid.
partnerAuctionId: '[YOUR_AUCTION_ID_IF_EXISTS]', // Auction ID, if available.
bidderCode: 'xxxxxxxx', // Bidder code.
prebidAuctionId: '3d4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx8e', // PreBid auction ID.
cpm: 1.5, // Cost per thousand impressions (CPM).
currency: 'USD', // Currency for the CPM value.
originalCpm: 1.5, // Original CPM value.
originalCurrency: 'USD', // Original currency.
status: 'rendered', // Auction status, e.g., 'rendered'.
placementId: 'div-1' // ID of the ad placement.
}
```

| Field | Data Type | Description | Example | Mandatory |
|--------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|-----------|
| biddingPlatformId | Integer | Specify the platform in which this ad impression was rendered – 1 – Prebid, 2 – Amazon, 3 – Google, 4 – Open RTB (including your local Prebid server) | 1 | Yes |
| partnerAuctionId | String | Use this when you are running multiple auction solutions across your assets and have a unified identifier for auctions | 3d44542d-xx-4662-xxxx-4xxxx3d8e | No |
| bidderCode | String | Specifies the name of the bidder that won the auction as reported by Prebid and all other bidding platforms | newAppnexus | Yes |
| prebidAuctionId | String | Specifies the identifier of the Prebid auction. Leave empty or undefined if Prebid is not the bidding platform | | |
| cpm | Decimal | Cost per mille of the impression as received from the demand-side auction (without modifications or reductions) | 5.62 | Yes |
| currency | String | Currency of the auction | USD | Yes |
| originalCpm | Decimal | Leave empty or undefined if Prebid is not the bidding platform | 5.5 | No |
| originalCurrency | String | Currency of the original auction | USD | No |
| status | String | Status of the impression. Leave empty or undefined if Prebid is not the bidding platform | rendered | No |
| placementId | String | Unique identifier of the ad unit on the webpage that showed this ad | div-1 | No |


To report the auction win, call the function as follows:

```js
window.intentIqAnalyticsAdapter_[partner_id].reportExternalWin(reportData)
```
Loading