Skip to content

Commit

Permalink
Merge pull request #175 from indexexchange/master
Browse files Browse the repository at this point in the history
  • Loading branch information
ix-certification committed Mar 6, 2020
2 parents 1967ee4 + aec233e commit 9708190
Show file tree
Hide file tree
Showing 6 changed files with 693 additions and 0 deletions.
Empty file added teads/CHANGES.md
Empty file.
129 changes: 129 additions & 0 deletions teads/DOCUMENTATION.md
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]]
}
```
5 changes: 5 additions & 0 deletions teads/teads-htb-exports.js
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')
};
//? }
132 changes: 132 additions & 0 deletions teads/teads-htb-system-tests.js
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
};
63 changes: 63 additions & 0 deletions teads/teads-htb-validator.js
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;
Loading

0 comments on commit 9708190

Please sign in to comment.