Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
17a7958
InsurAds Rtd Provider
JoseClimaco Mar 4, 2026
8727523
Update Example with Rtd config
JoseClimaco Mar 4, 2026
b31e731
Enrich the slot with targeting
JoseClimaco Mar 5, 2026
d6501a3
Wait for context before executing the callback
JoseClimaco Mar 6, 2026
7ee1108
Remove import not in use
JoseClimaco Mar 6, 2026
2332963
Remove changes that are not needed anymore on interpretResponse and i…
JoseClimaco Mar 6, 2026
6ed96d8
Update test/spec/modules/insuradsRtdProvider_spec.js
JoseClimaco Mar 6, 2026
b3cac8a
Clear keyvalues on non-ok responses
JoseClimaco Mar 6, 2026
bd5a981
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 6, 2026
6a736e9
Initialize api call promise as resolved as per suggestion
JoseClimaco Mar 9, 2026
9aaa627
Update test/spec/modules/insuradsRtdProvider_spec.js
JoseClimaco Mar 9, 2026
5fcd496
Clear keyValues on error or empty responses
JoseClimaco Mar 9, 2026
3ee870e
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 9, 2026
d84988a
Remove tests on functions that doesn't exist anymore
JoseClimaco Mar 9, 2026
795c57a
Fix module name
JoseClimaco Mar 9, 2026
170e9cc
Improve rtdData handling
JoseClimaco Mar 9, 2026
429a512
Remove tests not needed
JoseClimaco Mar 9, 2026
1443fcf
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 9, 2026
c72e629
Fix tests to match updated rtcData location
JoseClimaco Mar 9, 2026
b9dd435
Fix failing tests
JoseClimaco Mar 9, 2026
bf488fc
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 11, 2026
7017904
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 12, 2026
c7f54b3
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 16, 2026
70e4422
InsurAds RTD Provider: Register in parentModules map and standardize …
JoseClimaco Mar 17, 2026
4947d49
InsurAds Bid Adapter: Replace any type with AdapterRequest in getRtdT…
JoseClimaco Mar 17, 2026
fdd8cc1
InsurAds RTD Provider: Remove keepalive option from fetch request
JoseClimaco Mar 17, 2026
002d384
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 17, 2026
1658da6
InsurAds RTD Provider: Remove hardcoded credentials to honor privacy …
JoseClimaco Mar 17, 2026
4897db3
InsurAds RTD Provider: Fix unit test expectations for fetch options
JoseClimaco Mar 17, 2026
f3e215a
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 20, 2026
1875cb2
InsurAds RTD Provider: type config and validate publicId
JoseClimaco Mar 23, 2026
a1ff9df
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 23, 2026
cd20030
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 23, 2026
c9ec7ec
Merge branch 'master' into InsurAds-RtdProvider
JoseClimaco Mar 30, 2026
268d485
align docs with bidder-only enrichment
JoseClimaco Mar 30, 2026
dd0dff9
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 30, 2026
8f449c0
Update test/spec/modules/insuradsBidAdapter_spec.js
JoseClimaco Mar 30, 2026
84b9d6b
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 30, 2026
13e76e6
make async test deterministic
JoseClimaco Mar 30, 2026
546367c
Update modules/insuradsBidAdapter.ts
JoseClimaco Mar 30, 2026
4a7863c
Update test/spec/modules/insuradsRtdProvider_spec.js
JoseClimaco Mar 30, 2026
be131ca
document params.timeout
JoseClimaco Mar 30, 2026
0b7e18b
Merge branch 'InsurAds-RtdProvider' of https://github.com/InsurAds-Te…
JoseClimaco Mar 30, 2026
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
17 changes: 14 additions & 3 deletions integrationExamples/gpt/insurads.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
<script>
var FAILSAFE_TIMEOUT = 5300;
var PREBID_TIMEOUT = 2000;
var PREBID_TIMEOUT = 5000;

var adUnits = [{
code: 'div-gpt-ad-1460505748561-0',
Expand Down Expand Up @@ -41,6 +41,17 @@
pbjs.setConfig({
enableTIDs: true,
debug: true, // use only for testing, remove in production
// Uncomment the following to test InsurAds real-time data integration with your adapter
// realTimeData: {
// auctionDelay: 1000,
// dataProviders: [{
// name: 'insuradsRtd',
// waitForIt: true,
// params: {
// publicId: 'ALIYJZJD'
// }
// }]
// }
});

// You can set up gzip compression like so, and the adapter will use this setting when sending bid requests
Expand All @@ -51,10 +62,10 @@
// }
// });


pbjs.bidderSettings = {
insurads: {
storageAllowed : true
storageAllowed: true
Comment thread
patmmccann marked this conversation as resolved.
}
}

Expand Down
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"hadronRtdProvider",
"humansecurityRtdProvider",
"iasRtdProvider",
"insuradsRtdProvider",
"imRtdProvider",
"intersectionRtdProvider",
"jwplayerRtdProvider",
Expand Down
49 changes: 46 additions & 3 deletions modules/insuradsBidAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AdapterRequest, BidderSpec, registerBidder } from '../src/adapters/bidd
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { ortbConverter } from '../libraries/ortbConverter/converter.js'

import { interpretResponse, enrichImp, enrichRequest, getAmxId, getLocalStorageFunctionGenerator, getUserSyncs } from '../libraries/nexx360Utils/index.js';
import { interpretResponse as nexxInterpretResponse, enrichImp, enrichRequest, getAmxId, getLocalStorageFunctionGenerator, getUserSyncs } from '../libraries/nexx360Utils/index.js';
import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js';
import { BidRequest, ClientBidderRequest } from '../src/adapterManager.js';
import { ORTBImp, ORTBRequest } from '../src/prebid.public.js';
Expand Down Expand Up @@ -36,11 +36,12 @@ type InsurAdsBidParams = RequireAtLeastOne<{
allBids?: boolean;
customId?: string;
bidders?: Record<string, unknown>;
rtdData?: Record<string, unknown>;
}, "tagId" | "placement">;

declare module '../src/adUnits' {
interface BidderParams {
['nexx360']: InsurAdsBidParams;
['insurads']: InsurAdsBidParams;
}
}

Expand Down Expand Up @@ -82,6 +83,11 @@ const converter = ortbConverter({
deepSetValue(imp, 'ext.dimensions.cssMaxW', slotEl.style?.maxWidth);
deepSetValue(imp, 'ext.dimensions.cssMaxH', slotEl.style?.maxHeight);
}
if (bidRequest.params.rtdData) {
deepSetValue(imp, 'ext.rtdData', bidRequest.params.rtdData);
delete bidRequest.params.rtdData;
}

deepSetValue(imp, 'ext.nexx360', bidRequest.params);
deepSetValue(imp, 'ext.nexx360.divId', divId);
if (bidRequest.params.adUnitPath) deepSetValue(imp, 'ext.adUnitPath', bidRequest.params.adUnitPath);
Expand All @@ -96,6 +102,24 @@ const converter = ortbConverter({
},
});

function getRtdTargetingFromRequest(request: AdapterRequest): Record<string, string> {
const targeting: Record<string, string> = {};
const imps = request?.data?.imp;
if (!Array.isArray(imps)) return targeting;

for (const imp of imps) {
const rtdData = imp?.ext?.rtdData;
if (!rtdData || typeof rtdData !== 'object') continue;

for (const [key, value] of Object.entries(rtdData)) {
if (value === null || value === undefined) continue;
targeting[key] = String(value);
}
}

return targeting;
}

const isBidRequestValid = (bid: BidRequest<typeof BIDDER_CODE>): boolean => {
if (bid.params.adUnitName && (typeof bid.params.adUnitName !== 'string' || bid.params.adUnitName === '')) {
logError('bid.params.adUnitName needs to be a string');
Expand Down Expand Up @@ -136,14 +160,33 @@ const buildRequests = (
return adapterRequest;
}

const interpretResponse = (serverResponse, request) => {
const responses: any[] = nexxInterpretResponse(serverResponse) as any;
const rtdTargeting = getRtdTargetingFromRequest(request);

if (!rtdTargeting || Object.keys(rtdTargeting).length === 0) {
return responses;
}
Comment thread
JoseClimaco marked this conversation as resolved.

return responses.map((bidResponse) => {
return {
...bidResponse,
adserverTargeting: {
...(bidResponse?.adserverTargeting || {}),
...rtdTargeting,
Comment thread
JoseClimaco marked this conversation as resolved.
}
};
});
};

export const spec: BidderSpec<typeof BIDDER_CODE> = {
code: BIDDER_CODE,
gvlid: GVLID,
supportedMediaTypes: [BANNER, VIDEO, NATIVE],
isBidRequestValid,
buildRequests,
interpretResponse,
getUserSyncs,
getUserSyncs
};

registerBidder(spec);
61 changes: 61 additions & 0 deletions modules/insuradsRtdProvider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
## InsurAds Real-time Data Submodule

The [InsurAds](https://insurads.com) real-time data module in Prebid enables publishers to leverage
contextual targeting and audience segmentation capabilities. This module provides real-time
key-value targeting data that seamlessly integrates into your existing Prebid deployment,
helping you maximize your advertising strategies.

## Building Prebid with InsurAds Support

Compile the InsurAds RTD module into your Prebid build:

`gulp serve --modules=rtdModule,insuradsBidAdapter,insuradsRtdProvider`

Comment thread
JoseClimaco marked this conversation as resolved.
Please visit https://insurads.com/ for more information.

```javascript
pbjs.setConfig({
...
realTimeData: {
auctionDelay: 1000,
dataProviders: [{
name: 'insuradsRtd',
waitForIt: true,
params: {
publicId: 'YOUR_PUBLIC_ID',
timeout: 1000
}
}]
}
...
});
```

### Parameter Descriptions for the InsurAds Configuration Section

| Name | Type | Description | Notes |
|:------------------|:--------|:--------------------------------------------------------------------------|:-------------------------|
| name | String | Real time data module name | Always 'insuradsRtd' |
| waitForIt | Boolean | When true, delays the auction until this provider calls back (bounded by `auctionDelay` / `params.timeout`) | Optional. Defaults to false |
| params | Object | | |
| params.publicId | String | This is the Public ID value obtained from InsurAds | Required |
| params.timeout | Number | Max time (ms) to wait for the InsurAds API response before continuing the auction without enrichment | Optional. Defaults to 1000 |

Comment thread
JoseClimaco marked this conversation as resolved.
Comment thread
JoseClimaco marked this conversation as resolved.
## Testing

To view an example of InsurAds RTD provider:

`gulp serve --modules=rtdModule,insuradsBidAdapter,insuradsRtdProvider`

and then point your browser at:

`http://localhost:9999/integrationExamples/gpt/insurads.html`

## How It Works

The InsurAds RTD provider:

1. Fetches contextual targeting data from the InsurAds API using your `publicId`
2. Stores the returned key-values internally
3. Enriches bid requests for the `insurads` bidder by attaching the key-values onto `bid.params.rtdData`
4. Leaves other bidders unchanged
126 changes: 126 additions & 0 deletions modules/insuradsRtdProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { submodule } from '../src/hook.js';
import { logInfo } from '../src/utils.js'
import { fetch } from '../src/ajax.js';
import type { RtdProviderSpec } from './rtdModule/spec.ts';

/**
* @typedef {import('../modules/rtdModule/index.js').RtdSubmodule} RtdSubmodule
*/

const SERVER_IP = 'https://services.insurads.com';
const MODULE_NAME = 'insuradsRtd';
const ENDPOINT = `${SERVER_IP}/core/init/prebid`;
const LOG_PREFIX = 'insurads Rtd: ';
const GVLID = 596;

// Internal state to store keyValues
let keyValues = {};
let apiCallPromise = Promise.resolve();

declare module './rtdModule/spec.ts' {
interface ProviderConfig {
insuradsRtd: {
params: {
publicId: string;
timeout?: number;
};
};
}
}

export const insuradsRtdProvider: RtdProviderSpec<'insuradsRtd'> = {
name: MODULE_NAME,
gvlid: GVLID,
init: (config, userConsent) => {
const publicId = config?.params?.publicId;

if (typeof publicId !== 'string' || publicId.trim().length === 0) {
logInfo(LOG_PREFIX + 'publicId is required and must be a non-empty string');
return false;
}

// Reset keyValues to avoid stale values after failed/empty response
keyValues = {};

// Start fetch immediately without blocking init
apiCallPromise = makeApiCall(publicId);

Comment thread
JoseClimaco marked this conversation as resolved.
logInfo(LOG_PREFIX + 'submodule init', config, userConsent);
return true;
},
getBidRequestData: (reqBidsConfigObj, callback, config, userConsent) => {
logInfo(LOG_PREFIX + 'submodule getBidRequestData', reqBidsConfigObj, config, userConsent);

// Wait for API call to complete before enriching bid requests
const timeout = config?.params?.timeout || 1000; // Default 1 second timeout
const timeoutPromise = new Promise((resolve) => setTimeout(resolve, timeout));

Comment thread
JoseClimaco marked this conversation as resolved.
Promise.race([apiCallPromise, timeoutPromise])
.then(() => {
// Enrich bid requests with RTD data for insurads bidder
if (keyValues && Object.keys(keyValues).length > 0) {
reqBidsConfigObj.adUnits.forEach(adUnit => {
adUnit.bids.forEach(bid => {
if (bid.bidder === 'insurads') {
// Add RTD data to bid params so it can be accessed by the adapter
bid.params = bid.params || {};

(bid.params as any).rtdData = keyValues;
logInfo(LOG_PREFIX + 'Enriched bid request for insurads', (bid.params as any).rtdData);
}
});
});
} else {
logInfo(LOG_PREFIX + 'No keyValues available for bid enrichment');
}

callback();
})
.catch((_e) => {
logInfo(LOG_PREFIX + 'Error waiting for API call');
callback();
});
},
};

async function makeApiCall(publicId: string) {
const currentUrl = encodeURIComponent(location.href);

try {
const response = await fetch(`${ENDPOINT}/${publicId}?url=${currentUrl}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
keyValues = {};
logInfo(LOG_PREFIX + `Network error: ${response.status} ${response.statusText}, cleared cached values`);
return;
}
if (response.status === 204) {
keyValues = {};
logInfo(LOG_PREFIX + '204 No Content received, cleared cached values');
return;
}

const data = await response.json();
if (data && data.keyValues) {
keyValues = data.keyValues;
logInfo(LOG_PREFIX + 'Received keyValues from endpoint', data.keyValues);
Comment thread
JoseClimaco marked this conversation as resolved.
} else {
keyValues = {};
logInfo(LOG_PREFIX + 'No keyValues in response, cleared cached values');
}
} catch (_e) {
keyValues = {};
logInfo(LOG_PREFIX + 'API call failed, cleared cached keyValues');
}
}

function beforeInit() {
// take actions to get data as soon as possible
submodule('realTimeData', insuradsRtdProvider);
}

beforeInit();
Loading
Loading