Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2d76511
Add AlvaDS Bid Adapter for banner and video
Aug 25, 2025
77e56bd
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Aug 25, 2025
bb819be
fixed test
Aug 25, 2025
82af29e
Merge branch 'alvadsBidAdapter' of https://github.com/SamuelAlejandro…
Aug 25, 2025
9b22914
alvads
Aug 27, 2025
0f8cff9
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Aug 27, 2025
b298c79
removed application/json header
Aug 27, 2025
b39bc9b
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Aug 27, 2025
667536d
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Aug 27, 2025
014113e
removed application/json header
Aug 27, 2025
3e0b06f
Merge branch 'alvadsBidAdapter' of https://github.com/SamuelAlejandro…
Aug 27, 2025
ede3df3
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Aug 29, 2025
9ba0f63
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 1, 2025
f0143ed
ready for review
Sep 2, 2025
99a4662
Merge branch 'alvadsBidAdapter' of https://github.com/SamuelAlejandro…
Sep 2, 2025
1b1077e
ready for review
Sep 2, 2025
bc81fb8
ready for review
Sep 2, 2025
aa5e594
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 2, 2025
ad17152
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 3, 2025
f6e599d
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 3, 2025
7e466cc
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 3, 2025
b394677
added some methods
Sep 4, 2025
6669544
Merge branch 'alvadsBidAdapter' of https://github.com/SamuelAlejandro…
Sep 4, 2025
b5f2f49
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 4, 2025
08b00fd
added some methods
Sep 4, 2025
20981e7
added some methods
Sep 4, 2025
b967e6e
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 5, 2025
fbee49c
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 5, 2025
667dae7
ready for review
Sep 11, 2025
f8121ee
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 11, 2025
30219ea
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 11, 2025
b040c5d
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 12, 2025
7094206
fixes
Sep 25, 2025
19c4f16
Merge branch 'alvadsBidAdapter' of https://github.com/SamuelAlejandro…
Sep 25, 2025
6330ac3
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 25, 2025
b7e70dc
Merge branch 'master' into alvadsBidAdapter
SamuelAlejandroNT Sep 26, 2025
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
151 changes: 151 additions & 0 deletions modules/alvadsBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import * as utils from '../src/utils.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
const BIDDER_CODE = 'alvads';
const ENDPOINT_BANNER = 'https://helios-ads-qa-core.ssidevops.com/decision/openrtb';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: (bid) => {
return Boolean(
bid.params &&
bid.params.publisherId &&
(bid.mediaTypes?.[BANNER] ? bid.params.tagid : true)
);
},

buildRequests: function(validBidRequests, bidderRequest) {
return validBidRequests.map(bid => {
const floorInfo = (typeof bid.getFloor === 'function')
? bid.getFloor({
currency: 'USD',
mediaType: bid.mediaTypes?.banner ? BANNER : VIDEO,
size: '*'
})
: { floor: 0, currency: 'USD' };

const imps = [];
// Banner
if (bid.mediaTypes?.banner) {
const sizes = utils.parseSizesInput(bid.mediaTypes.banner.sizes || bid.sizes)
.map(s => {
const parts = s.split('x').map(Number);
return { w: parts[0], h: parts[1] };
});

sizes.forEach(size => {
imps.push({
id: bid.bidId,
banner: { w: size.w, h: size.h },
tagid: bid.params.tagid,
bidfloor: floorInfo.floor,
bidfloorcur: floorInfo.currency,
ext: { userId: bid.params.userId }
});
});
}

// Video
if (bid.mediaTypes?.video) {
const wh = (bid.mediaTypes.video.playerSize && bid.mediaTypes.video.playerSize[0]) || [1280, 720];
imps.push({
id: bid.bidId,
video: { w: wh[0], h: wh[1] },
tagid: bid.params.tagid,
bidfloor: floorInfo.floor,
bidfloorcur: floorInfo.currency,
ext: { userId: bid.params.userId }
});
}

// Payload OpenRTB por bid
const payload = {
id: 'REQ-OPENRTB-' + Date.now(),
site: {
page: bidderRequest.refererInfo.page,
ref: bidderRequest.refererInfo.ref,
publisher: { id: bid.params.publisherId }
},
imp: imps,
device: {
ua: navigator.userAgent
},
user: {
id: bid.params.userId || utils.generateUUID(),
buyeruid: utils.generateUUID()
},
regs: {
gpp: '',
gpp_sid: [],
ext: {
gdpr: Number(bidderRequest.gdprConsent?.gdprApplies)
}
},
ext: {
user_fingerprint: utils.generateUUID()
}
};
const endpoint = bid.params.endpoint || ENDPOINT_BANNER;

return {
method: 'POST',
url: endpoint,
data: JSON.stringify(payload),
options: { withCredentials: false }
};
});
},

interpretResponse: (serverResponse) => {
const bidResponses = [];
const body = serverResponse.body;

// --- Banners OpenRTB ---
if (body && body.seatbid) {
body.seatbid.forEach(seat => {
seat.bid.forEach(bid => {
const isVideo = bid.adm && bid.adm.includes('<VAST');
const common = {
requestId: bid.impid,
cpm: bid.price || 0,
width: bid.w,
height: bid.h,
creativeId: bid.crid || bid.id,
currency: body.cur || 'USD',
netRevenue: true,
ttl: 300,
meta: { advertiserDomains: bid.adomain || [] }
};

if (isVideo) {
bidResponses.push({
...common,
mediaType: VIDEO,
vastXml: bid.adm,
vastUrl: bid.ext && bid.ext.vast_url ? bid.ext.vast_url : undefined,
meta: { advertiserDomains: bid.adomain || [] }
});
} else {
bidResponses.push({
...common,
mediaType: BANNER,
ad: bid.adm
});
}
});
});
}
return bidResponses;
},

onTimeout: (timeoutData) => {
utils.logWarn('Timeout bids ALVA:', timeoutData);
},

onBidWon: (bid) => {
utils.logInfo('Bid winner ALVA:', bid);
}
};

registerBidder(spec);
135 changes: 135 additions & 0 deletions modules/alvadsBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Overview
**Module Name:** alvadsBidAdapter
**Module Type:** bidder
**Maintainer:** alvads@oyealva.com

---

# Description
The **Alva Bid Adapter** allows publishers to connect their banner and video inventory with the Alva demand platform.

- **Bidder Code:** `alvads`
- **Supported Media Types:** `banner`, `video`
- **Protocols:** OpenRTB 2.5 via POST for both banner and video
- **Dynamic Endpoints:** The adapter can use a default endpoint or a custom endpoint provided in the bid params.
- **Price Floors:** Supported via `bid.getFloor()`. If configured, the adapter will send `bidfloor` and `bidfloorcur` per impression.

---
# Parameters

| Parameter | Required | Description |
|------------ |---------------- |------------ |
| publisherId | Yes | Publisher ID assigned by Alva |
| tagid | Banner only | Required for banner impressions |
| bidfloor | No | Optional; adapter supports floors module via `bid.getFloor()` |
| userId | No | Optional; used for user identification |
| endpoint | No | Optional; overrides default endpoint |

---

# Test Parameters

## Banner Example

```javascript
var adUnits = [{
code: 'div-banner',
mediaTypes: {
banner: {
sizes: [[300, 250], [320, 100]]
}
},
bids: [{
bidder: 'alvads',
params: {
publisherId: 'pub-123', // required
tagid: 'tag-456', // required for banner
bidfloor: 0.50, // optional
userId: '+59165352182', // optional
endpoint: 'https://custom-endpoint.com/openrtb' // optional, overrides default
}
}]
}];
```

## Video Example

```javascript
var adUnits = [{
code: 'video-ad',
mediaTypes: {
video: {
context: 'instream',
playerSize: [[640, 360]]
}
},
bids: [{
bidder: 'alvads',
params: {
publisherId: 'pub-123', // required
bidfloor: 0.5, // optional
userId: '+59165352182', // optional
endpoint: 'https://custom-endpoint.com/video' // optional, overrides default
}
}]
}];
```

---

# Request Information

### Banner / Video
- **Endpoint:**
```
https://helios-ads-qa-core.ssidevops.com/decision/openrtb
```
- **Method:** `POST`
- **Payload:** OpenRTB 2.5 request containing `site`, `device`, `user`, `regs`, `imp`.
- **Dynamic Endpoint:** The request URL can be overridden by bid.params.endpoint.


# Response Information

### Banner
The response is standard OpenRTB with `seatbid`. Example:

```json
{
"id": "response-id",
"seatbid": [{
"bid": [{
"impid": "imp-123",
"price": 0.50,
"adm": "<div>Creative</div>",
"crid": "creative-1",
"w": 320,
"h": 100,
"ext": {
"vast_url": "http://example.com/vast.xml"
},
"adomain": ["example.com"]
}]
}],
"cur": "USD"
}

```
# Interpretation:

If adm contains <VAST>, the adapter sets mediaType: 'video' and includes vastXml & vastUrl.

Otherwise, mediaType: 'banner' and ad contains the HTML.


# Additional Details

- **Defaults:**
- `netRevenue = true`
- `ttl = 300`
- Banner fallback size: `320x100`
- Video fallback size: `1280x720`

- **Callbacks:**
- `onTimeout` → logs timeout events
- `onBidWon` → logs winning bid
Loading
Loading