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

Pubx.ai RTD Provider - Initial Release #11300

Merged
merged 28 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe4b493
Add pubx RTD module
pnhegde Sep 20, 2022
2ceafa4
Add pubx RTD module documentation
pnhegde Sep 20, 2022
99da428
Add basic tests for pubx RTD module
pnhegde Sep 20, 2022
72db7e1
Fix the failing tests
pnhegde Sep 20, 2022
9f9c78f
Added logic to fetch floors and set to auction
pnhegde Feb 9, 2024
d5ad5e2
Updated setDataToConfig to attach floors data to bidder requests object
pnhegde Feb 14, 2024
c2bc4d9
pubx rtd module:
pruthvimuga Mar 3, 2024
5473a62
move fetch floors to init and also wait for it before auction
pruthvimuga Mar 12, 2024
abf021b
TESTS: update
pruthvimuga Mar 12, 2024
361d83d
replace createFloorsDataForAuction to avoid circular dep - WIP
pruthvimuga Mar 12, 2024
f37e645
reset default floors when no floor response is received
pruthvimuga Mar 12, 2024
5baa9fe
TESTS: add test
pruthvimuga Mar 12, 2024
451f552
tag integration - fetch floors api events
pruthvimuga Mar 15, 2024
f32ebdd
* Remove coonsole.log
pruthvimuga Mar 23, 2024
fd15c9f
TESTS: add getBidRequestData, refactor stubs
pruthvimuga Mar 23, 2024
d39782b
TESTS: setFloorsApiStatus
pruthvimuga Mar 23, 2024
56208b0
TESTS: add fetchFloorRules
pruthvimuga Mar 25, 2024
51581f7
Merge branch 'master' into pubx-rtd-module
pruthvimuga Mar 25, 2024
6bb5196
remove useRtd
pruthvimuga Mar 28, 2024
4e8332c
make endpoint potional and take pubxId form provider config
pruthvimuga Mar 28, 2024
3bdfbc6
TESTS: use xhr to fakeServer instead of sinon
pruthvimuga Mar 28, 2024
5cecc4c
make default data optional
pruthvimuga Mar 28, 2024
f4798aa
update README
pruthvimuga Mar 28, 2024
04041f7
TEST: update tests
pruthvimuga Apr 5, 2024
87bde8a
add integration example
pruthvimuga Apr 5, 2024
2ed5aa9
remove floorProvider from default config
pruthvimuga Apr 5, 2024
b5e3821
fix linting
pruthvimuga Apr 5, 2024
8335461
update readme.md
pruthvimuga Apr 9, 2024
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
113 changes: 113 additions & 0 deletions integrationExamples/gpt/pubxaiRtdProvider_example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<html>
<head>
<title>Individual Ad Unit Refresh Example</title>
<script async src="//www.googletagservices.com/tag/js/gpt.js"></script>
<script async src="http://localhost:9999/build/dev/prebid.js"></script>
<script>
var sizes = [[300, 250]];
var PREBID_TIMEOUT = 1000;

var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

var adUnits = [
{
code: "/19968336/header-bid-tag-0",
mediaTypes: {
banner: {
sizes: sizes,
},
},
bids: [
{
bidder: "appnexus",
params: {
placementId: 13144370,
},
cpm: 2.5,
ad: '<html><body><img src="https://files.prebid.org/creatives/prebid300x250.png"></body></html>',
},
],
},
];

pbjs.que.push(function () {
pbjs.addAdUnits(adUnits);

// -----------------------------------------------
// pubxai RTD module

pbjs.setConfig({
debug: "true",
realTimeData: {
auctionDelay: 2500,
dataProviders: [
{
name: "pubxai",
waitForIt: true,
params: {
pubxId: "74d8356b-35a7-514b-c648-e7e4ad72af63",
endpoint: "http://localhost:3001/floors", // (optional)
floorMin: 3, // (optional)
enforcement: {
bidAdjustment: true,
enforceJS: false,
}, // (optional)
data: {
currency: "USD",
modelVersion: "default",
schema: { fields: ["gptSlot", "mediaType", "size"] },
values: { "*|banner|*": 0.02 },
}, // (optional)
},
},
],
},
});

// -----------------------------------------------
});
</script>

<script>
var slot1;
googletag.cmd.push(function () {
slot1 = googletag
.defineSlot("/19968336/header-bid-tag-0", [[300, 250]], "div-1")
.addService(googletag.pubads());
googletag.pubads().disableInitialLoad();
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});

function refreshBid() {
pbjs.que.push(function () {
pbjs.requestBids({
timeout: PREBID_TIMEOUT,
adUnitCodes: ["/19968336/header-bid-tag-0"],
bidsBackHandler: function () {
pbjs.setTargetingForGPTAsync(["/19968336/header-bid-tag-0"]);
googletag.pubads().refresh([slot1]);
},
});
});
}
</script>
</head>

<body>
<h1>Individual Ad Unit Refresh Example</h1>
<h5>Div-1</h5>
<p><button onclick="refreshBid()">Refresh Ad Unit</button></p>
<div id="div-1">
<script type="text/javascript">
googletag.cmd.push(function () {
googletag.display("div-1");
});
</script>
</div>
</body>
</html>
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"optimeraRtdProvider",
"oxxionRtdProvider",
"permutiveRtdProvider",
"pubxaiRtdProvider",
"qortexRtdProvider",
"reconciliationRtdProvider",
"relevadRtdProvider",
Expand Down
146 changes: 146 additions & 0 deletions modules/pubxaiRtdProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { ajax } from '../src/ajax.js';
import { config } from '../src/config.js';
import { submodule } from '../src/hook.js';
import { deepAccess } from '../src/utils.js';
/**
* This RTD module has a dependency on the priceFloors module.
* We utilize the createFloorsDataForAuction function from the priceFloors module to incorporate price floors data into the current auction.
*/
import { createFloorsDataForAuction } from './priceFloors.js'; // eslint-disable-line prebid/validate-imports

const MODULE_NAME = 'realTimeData';
const SUBMODULE_NAME = 'pubxai';
window.__pubxFloorRulesPromise__ = null;
export const FloorsApiStatus = Object.freeze({
IN_PROGRESS: 'IN_PROGRESS',
SUCCESS: 'SUCCESS',
ERROR: 'ERROR',
});
export const FLOORS_EVENT_HANDLE = 'floorsApi';
export const FLOORS_END_POINT = 'https://floor.pbxai.com/';
export const FLOOR_PROVIDER = 'PubxFloorProvider';

export const getFloorsConfig = (provider, floorsResponse) => {
const floorsConfig = {
floors: {
enforcement: { floorDeals: true },
data: floorsResponse,
},
};
const { floorMin, enforcement } = deepAccess(provider, 'params');
if (floorMin) {
floorsConfig.floors.floorMin = floorMin;
}
if (enforcement) {
floorsConfig.floors.enforcement = enforcement;
}
return floorsConfig;
};

export const setFloorsConfig = (provider, data) => {
if (data) {
const floorsConfig = getFloorsConfig(provider, data);
config.setConfig(floorsConfig);
window.__pubxLoaded__ = true;
window.__pubxFloorsConfig__ = floorsConfig;
} else {
config.setConfig({ floors: window.__pubxPrevFloorsConfig__ });
window.__pubxLoaded__ = false;
window.__pubxFloorsConfig__ = null;
}
};

export const setDefaultPriceFloors = (provider) => {
const { data } = deepAccess(provider, 'params');
if (data !== undefined) {
data.floorProvider = FLOOR_PROVIDER;
setFloorsConfig(provider, data);
}
};

export const setPriceFloors = async (provider) => {
window.__pubxPrevFloorsConfig__ = config.getConfig('floors');
setDefaultPriceFloors(provider);
return fetchFloorRules(provider)
.then((floorsResponse) => {
setFloorsConfig(provider, floorsResponse);
setFloorsApiStatus(FloorsApiStatus.SUCCESS);
})
.catch((_) => {
setFloorsApiStatus(FloorsApiStatus.ERROR);
});
};

export const setFloorsApiStatus = (status) => {
window.__pubxFloorsApiStatus__ = status;
window.dispatchEvent(
new CustomEvent(FLOORS_EVENT_HANDLE, { detail: { status } })
);
};

export const getUrl = (provider) => {
const { pubxId, endpoint } = deepAccess(provider, 'params');
return `${endpoint || FLOORS_END_POINT}?pubxId=${pubxId}&page=${
window.location.href
}`;
};

export const fetchFloorRules = async (provider) => {
return new Promise((resolve, reject) => {
setFloorsApiStatus(FloorsApiStatus.IN_PROGRESS);
ajax(getUrl(provider), {
success: (responseText, response) => {
try {
if (response && response.response) {
const floorsResponse = JSON.parse(response.response);
resolve(floorsResponse);
} else {
resolve(null);
}
} catch (error) {
reject(error);
}
},
error: (responseText, response) => {
reject(response);
},
});
});
};

const init = (provider) => {
window.__pubxFloorRulesPromise__ = setPriceFloors(provider);
return true;
};

const getBidRequestData = (() => {
let floorsAttached = false;
return (reqBidsConfigObj, onDone) => {
if (!floorsAttached) {
createFloorsDataForAuction(
reqBidsConfigObj.adUnits,
reqBidsConfigObj.auctionId
);
window.__pubxFloorRulesPromise__.then(() => {
createFloorsDataForAuction(
reqBidsConfigObj.adUnits,
reqBidsConfigObj.auctionId
);
onDone();
});
floorsAttached = true;
}
};
})();

export const pubxaiSubmodule = {
name: SUBMODULE_NAME,
init,
getBidRequestData,
};

export const beforeInit = () => {
submodule(MODULE_NAME, pubxaiSubmodule);
};

beforeInit();
68 changes: 68 additions & 0 deletions modules/pubxaiRtdProvider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Overview

- Module Name: pubX.ai RTD Provider
- Module Type: RTD Adapter
- Maintainer: phaneendra@pubx.ai

## Description

This RTD module, provided by pubx.ai, is used to set dynamic floors within Prebid.

## Usage

Ensure that the following modules are listed when building Prebid: `priceFloors`.
For example:

```shell
gulp build --modules=priceFloors
```

To compile the RTD module into your Prebid build:

```shell
gulp build --modules=rtdModule,pubxaiRtdProvider
```

To utilize the pubX.ai RTD module, add `realTimeData` with the parameters mentioned below to the Prebid config.

```js
const AUCTION_DELAY = 100;
pbjs.setConfig({
// rest of the config
...,
realTimeData: {
auctionDelay: AUCTION_DELAY,
dataProviders: {
name: "pubxai",
waitForIt: true,
params: {
pubxId: `<publisher_id>`,
endpoint: `<publisher_endpoint>`, // (optional)
floorMin: `<floorMin>`, // (optional)
enforcement: `<enforcement>`, // (optional)
data: `<defaultConfig>` // (optional)
}
}
}
// rest of the config
...,
});
```

## Parameters

| Name | Type | Description | Default |
| :----------------- | :------ | :------------------------------------------------------------- | :------------------------- |
| name | String | Name of the real-time data module | Always `pubxai` |
| waitForIt | Boolean | Should be `true` if an `auctionDelay` is defined (optional) | `false` |
| params | Object | | |
| params.pubxId | String | Publisher ID | |
| params.endpoint | String | URL to retrieve floor data (optional) | `https://floor.pbxai.com/` |
| params.floorMin | Number | Minimum CPM floor (optional) | `None` |
| params.enforcement | Object | Enforcement behavior within the Price Floors Module (optional) | `None` |
| params.data | Object | Default floor data provided by pubX.ai (optional) | `None` |

## What Should Change in the Bid Request?

There are no direct changes in the bid request due to our RTD module, but floor configuration will be set using the price floors module. These changes will be reflected in adunit bids or bidder requests as floor data.

Loading