-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #167 from ebuzzing/teads-adapter
[HTP-0001]Introduce Teads adapter
- Loading branch information
Showing
6 changed files
with
693 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
# Teads | ||
## General Compatibility | ||
|Feature| | | ||
|---|---| | ||
| Consent | Yes | | ||
| Native Ad Support | Yes | | ||
| SafeFrame Support | Yes | | ||
|
||
## Browser Compatibility | ||
| Browser | | | ||
|--- |---| | ||
| Chrome | Yes | | ||
| Edge | Yes | | ||
| Firefox | Yes | | ||
| Internet Explorer 9 | Yes | | ||
| Internet Explorer 10 | Yes | | ||
| Internet Explorer 11 | Yes | | ||
| Safari | Yes | | ||
| Mobile Chrome | Yes | | ||
| Mobile Safari | Yes | | ||
| UC Browser | Yes | | ||
| Samsung Internet | Yes | | ||
| Opera | Yes | | ||
|
||
## Adapter Information | ||
| Info | | | ||
|---|---| | ||
| Partner Id | TeadsHtb | | ||
| Ad Server Responds in (Cents, Dollars, etc) | Dollars | | ||
| Bid Type (Gross / Net) | Net | | ||
| GAM Key (Open Market) | ix_teads_om | | ||
| GAM Key (Private Market) | ix_teads_pm | | ||
| Ad Server URLs | a.teads.tv/hb/index/bid-request | | ||
| Slot Mapping Style (Size / Multiple Sizes / Slot) | Multiple Sizes | | ||
| Request Architecture (MRA / SRA / FSRA) | SRA | | ||
|
||
## Bid Request Information | ||
### Parameters | ||
| Key | Required | Type | Description | | ||
|---|---|---|---| | ||
| deviceWidth | false | Number | | | ||
| referrer | true | String | page url - Using Browser.getPageUrl() | | ||
| pageReferrer | true | String | document.referrer - Using Browser.getReferrer() | | ||
| networkBandwidth | false | String | Effective bandwidth estimate in megabits per second | | ||
| us_privacy | true | String | CCPA consent string | | ||
| hb_version | true | String | version of the adapter | | ||
|
||
#### gdpr_iab object | ||
|
||
| Key | Required | Type | | ||
|---|---|---| | ||
| status | true | Number | | ||
| consent | true | String | | ||
|
||
#### data object | ||
|
||
| Key | Required | Type | Description | | ||
|---|---|---|---| | ||
| sizes | true | An array containing arrays of 2 number elements | ad sizes from the xSlotRef | | ||
| placementId | true | Number | Teads placement ID | | ||
| pageId | true | Number | Teads page ID | | ||
| adUnitCode | true | String | ID of the htSlot | | ||
| requestId | true | String | Request ID from the parcel | | ||
| transactionId | true | String | Unique ID generated for each slot | | ||
| slotElementId | true | String | ID of the slot element that will contain the creative to display | | ||
|
||
### Example | ||
```javascript | ||
{ | ||
deviceWidth: 123, | ||
referrer: "pageUrl", | ||
pageReferrer: "document.referrer", | ||
networkBandwidth: "window.navigator.connection.downlink", | ||
hb_version: "2.0.0", | ||
gdpr_iab: { | ||
consent: "consentString", | ||
status: 1 | ||
}, | ||
us_privacy: "usPrivacyString", | ||
data: [ // for each parcel | ||
{ | ||
sizes: [[300, 250]], | ||
placementId: 1, | ||
pageId: 2, | ||
adUnitCode: "adUnitCode", | ||
requestId: "requestId", | ||
transactionId: "transactionId", | ||
slotElementId: "slotElementId" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
## Bid Response Information | ||
### Bid Example | ||
```javascript | ||
[ | ||
responses : [ | ||
{ | ||
cpm: 2, | ||
width: "300", | ||
height: "250", | ||
ad: "<script>script containing the ad</script>", | ||
requestId: "requestId" | ||
} | ||
] | ||
``` | ||
|
||
### Pass Example | ||
```javascript | ||
{ | ||
responses: [] | ||
} | ||
``` | ||
|
||
## Configuration Information | ||
### Configuration Keys | ||
| Key | Required | Type | Description | | ||
|---|---|---|---| | ||
| placementId | true | String | Teads placement ID value | | ||
| sizes | true | An array containing arrays of 2 number elements | List of ad sizes for this slot | | ||
|
||
### Example | ||
```javascript | ||
{ | ||
"placementId": "15894224", | ||
"sizes": [[300, 250], [300, 600], [300, 300]] | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
//? if (FEATURES.GPT_LINE_ITEMS) { | ||
shellInterface.TeadsHtb = { | ||
render: SpaceCamp.services.RenderService.renderDfpAd.bind(null, 'TeadsHtb') | ||
}; | ||
//? } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
'use strict'; | ||
|
||
function getPartnerId() { | ||
return 'TeadsHtb'; | ||
} | ||
|
||
function getStatsId() { | ||
return 'TEADS'; | ||
} | ||
|
||
function getBidRequestRegex() { | ||
return { | ||
method: 'POST', | ||
urlRegex: /a\.teads\.tv\/hb\/index\/bid-request/ | ||
}; | ||
} | ||
|
||
function getCallbackType() { | ||
return 'NONE'; | ||
} | ||
|
||
function getArchitecture() { | ||
return 'SRA'; | ||
} | ||
|
||
function getConfig() { | ||
return { | ||
xSlots: { | ||
1: { | ||
placementId: 10, | ||
pageId: 1, | ||
sizes: [[300, 250]] | ||
}, | ||
2: { | ||
placementId: 10, | ||
pageId: 1, | ||
sizes: [[300, 600]] | ||
} | ||
} | ||
}; | ||
} | ||
|
||
function validateBidRequest(request) { | ||
var q = JSON.parse(request.body); | ||
var config = getConfig(); | ||
var sizesSlot1 = config.xSlots['1'].sizes; | ||
var sizesSlot2 = config.xSlots['2'].sizes; | ||
|
||
expect(q.data).toBeDefined(); | ||
expect(q.deviceWidth).toBeDefined(); | ||
expect(q.referrer).toBeDefined(); | ||
expect(q.pageReferrer).toBeDefined(); | ||
expect(q.networkBandwidth).toBeDefined(); | ||
expect(q.hb_version).toBeDefined(); | ||
expect(q.data[0].placementId).toBe(10); | ||
expect(q.data[0].pageId).toBe(1); | ||
expect(q.data[0].sizes[0][0]).toBe(sizesSlot1[0][0]); | ||
expect(q.data[0].sizes[0][1]).toBe(sizesSlot1[0][1]); | ||
expect(q.data[0].adUnitCode).toBeDefined(); | ||
expect(q.data[0].requestId).toBeDefined(); | ||
expect(q.data[0].slotElementId).toBeDefined(); | ||
expect(q.data[0].transactionId).toBeDefined(); | ||
|
||
expect(q.data[1].placementId).toBe(10); | ||
expect(q.data[1].pageId).toBe(1); | ||
expect(q.data[1].sizes[0][0]).toBe(sizesSlot2[0][0]); | ||
expect(q.data[1].sizes[0][1]).toBe(sizesSlot2[0][1]); | ||
expect(q.data[1].adUnitCode).toBeDefined(); | ||
expect(q.data[1].requestId).toBeDefined(); | ||
expect(q.data[1].slotElementId).toBeDefined(); | ||
expect(q.data[1].transactionId).toBeDefined(); | ||
} | ||
|
||
function validateBidRequestWithPrivacy(request) { | ||
var q = JSON.parse(request.body); | ||
expect(q.gdpr_iab).toBeDefined(); | ||
expect(q.gdpr_iab.consent).toBe('TEST_GDPR_CONSENT_STRING'); | ||
expect(q.gdpr_iab.status).toBe(12); | ||
} | ||
|
||
function getValidResponse(request, creative) { | ||
var q = JSON.parse(request.body); | ||
var response = { | ||
responses: [ | ||
{ | ||
cpm: 2, | ||
width: 300, | ||
height: 250, | ||
ad: creative, | ||
requestId: q.data[0].requestId | ||
}, | ||
{ | ||
cpm: 2, | ||
width: 300, | ||
height: 600, | ||
ad: creative, | ||
requestId: q.data[1].requestId | ||
} | ||
] | ||
}; | ||
|
||
return JSON.stringify(response); | ||
} | ||
|
||
function validateTargeting(targetingMap) { | ||
expect(targetingMap).toEqual(jasmine.objectContaining({ | ||
ix_teads_om: jasmine.arrayWithExactContents(['300x250_200', '300x600_200']), | ||
ix_teads_id: jasmine.arrayWithExactContents([jasmine.any(String), jasmine.any(String)]) | ||
})); | ||
} | ||
|
||
function getPassResponse() { | ||
var response = { | ||
responses: [] | ||
}; | ||
|
||
return JSON.stringify(response); | ||
} | ||
|
||
module.exports = { | ||
getPartnerId: getPartnerId, | ||
getStatsId: getStatsId, | ||
getCallbackType: getCallbackType, | ||
getArchitecture: getArchitecture, | ||
getConfig: getConfig, | ||
getBidRequestRegex: getBidRequestRegex, | ||
validateBidRequest: validateBidRequest, | ||
validateBidRequestWithPrivacy: validateBidRequestWithPrivacy, | ||
getValidResponse: getValidResponse, | ||
getPassResponse: getPassResponse, | ||
validateTargeting: validateTargeting | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
'use strict'; | ||
|
||
//////////////////////////////////////////////////////////////////////////////// | ||
// Dependencies //////////////////////////////////////////////////////////////// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
var Inspector = require('../../../libs/external/schema-inspector.js'); | ||
|
||
//////////////////////////////////////////////////////////////////////////////// | ||
// Main //////////////////////////////////////////////////////////////////////// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
/* ============================================================================= | ||
* STEP 0 | Config Validation | ||
* ----------------------------------------------------------------------------- | ||
* This file contains the necessary validation for the partner configuration. | ||
* This validation will be performed on the partner specific configuration object | ||
* that is passed into the wrapper. The wrapper uses an outside library called | ||
* schema-insepctor to perform the validation. Information about it can be found here: | ||
* https://atinux.fr/schema-inspector/. | ||
*/ | ||
function partnerValidator(configs) { | ||
var result = Inspector.validate({ | ||
type: 'object', | ||
properties: { | ||
xSlots: { | ||
type: 'object', | ||
properties: { | ||
'*': { | ||
type: 'object', | ||
properties: { | ||
placementId: { | ||
type: 'integer' | ||
}, | ||
pageId: { | ||
type: 'integer' | ||
}, | ||
sizes: { | ||
type: 'array', | ||
minLength: 1, | ||
items: { | ||
type: 'array', | ||
exactLength: 2, | ||
items: { | ||
type: 'integer' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, configs); | ||
|
||
if (!result.valid) { | ||
return result.format(); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
module.exports = partnerValidator; |
Oops, something went wrong.