OpenRTB
1 Terminology
Term Description:
- Media owner or Publisher- The owner of the player which ultimately plays the ad.
- Player - A unit, with one or multiple screens, which plays digital ads.
- Product - A media owner may classify their players into “products”. For example, all players in malls may be part of a “Mall” product.
2 Goals
The goal of this document is to identify challenges through which a buyer (an advertiser or agency) may use a DSP in order to target and buy ads to be played on a digital signboard and to flesh out the solutions and processes needed to overcome these challenges.
The process tries to leverage as much of the existing OpenRTB 2.5 specification, with as few extensions or modifications as possible.
3 Additional reading
OpenRTB API Specification Version 2.5 Terminology from the OpenRTB API documentation is used extensively in this document. It can be found at https://www.iab.com/guidelines/real-time-bidding-rtb-project/
.
4 Scenarios
Two scenarios are considered in this document: open bidding and pre-approved campaigns.
Open bidding
“Open bidding” is the process in which a media owner can send a bid request in order to fill in an open spot in a player’s schedule (or perhaps even all spots) and all (or selected) buyers can bid for the spot through a DSP and provide the content of the ad.
Pre-approved campaigns
“Pre-approved campaigns” is the process where an advertiser or agency and a media owner have an agreement to play an ad in a predetermined schedule. The media owner can then use the advertiser or agency’s DSP to retrieve the creative and report impressions, with the link being made through a Deal ID.
5 Inventory
5.1 Overview
We publish our inventory to files listed at https://exdsps-inventory.hivestack.com/list. We publish excel and json files for each region (China and rest of world). These files contain all of our inventory for the given region.
We generate one file per month per region on the 20th of the previous month. This file is then updated every week of the month on Saturday. We also provide an evergreen file that is updated weekly on Saturdays as well.
Do note that we don't provide an API to make queries on the inventory at this point and that, as such, these files are the only way to access our inventory's data outside of our bid stream. We recommend using the files to seed your DB and updating it in between with the information provided in the bid requests until an updated file is provided to resolve missing information.
5.2 Details
5.2.1 Identifiers
You will notice that we share two IDs: screen ID and OpenRTB UUID. The first one is the ID the MO gave their units, this value is only unique within the MO but the same value can appear in the inventory of more than one MO (typically if they use sequential values). The second one however, is unique to this unit within Hivestack but not typically used by the MO.
6 Challenges
6.1 Audience targeting
The OpenRTB standard was created for a process in which an ad would be served to an audience consisting of a single person. This meant that the focus of targeting information was placed on the device, the app or site displaying the ad, and the single person viewing the ad. But our case results in many people viewing the ad.
Breakdown
- The current OpenRTB standards provide targeting information for a single person.
- We need a demographic breakdown of the audience viewing the ad.
Solution
The Imp object has been given an extension (called ImpExt ) which contains extra information about the audience of the player, including the total number of viewers and a demographic breakdown.
In order to correctly target ads and ensure correct billing, support for this extension is required.
Additionally, the Bid object now has a BidExt extension which adds the “targetdemo” field where the bidder can specify the targeted demographics in order to receive a count of the targeted audience for reporting purposes.
6.2 Restrictions on impression reporting methods
The OpenRTB standard itself does not specify exactly how a successful impression should be reported. While the VAST protocol, which features an impression reporting URL, is widely used in video, there is no such simple solution for still images. The most popular method for impression reporting of still images is to send a creative consisting of markup language with either embedded JavaScript which makes the impression call or an invisible image whose loading signals the successful impression. The main problem with this method is not only the previously possible lack of Internet connectivity but communication restrictions that could be placed on a player for security purposes.
Breakdown
- The internet connectivity of a player may be lacking, restricted, or simply non-existent
- The most popular method of reporting impressions for a still image is to embed the image in some HTML markup with some JavaScript code tasked with calling an impression reporting URL or with an invisible tracking pixel.
- How can we report an impression if the JavaScript cannot call an external URL or the invisible tracking pixel cannot be loaded?
Solution
The Bid object has received an extension called BidExt which contains the “impurls” field. If specified, the URL will be called by the media owner once the creative has played. This also frees up the win notice URL to directly serve an image or video rather than going through HTML markup.
If a creative is served through a VAST document, the impression URL found there will also be used. But the actual audience numbers cannot be sent to this URL as applying substitution macros to VAST reporting URLs is not standard behaviour. So it is recommended to always use the “impurls” field.
6.3 Retrieving external resources
An ad may contain a ZIP creative, HTML file, or HTML markup. If the ad is a ZIP creative, anindex.html
must be in the archive. When the format is supported for delivery via a VAST, the correct mime types will be sent over the bid stream. These formats usually use external resources, such as images. Once again, a player's possibly limited or non-existent Internet connectivity may preclude the fetching of such resources.
Also, the delay in loading these resources may be unacceptable once comes the time to display the ad. For example, we would not want to display a progressively loading image on the screen because the player could only know it has to load it once it tried displaying the markup!
Breakdown
- HTML markup will normally reference external sources.
- Such external resources may be unavailable due to restricted Internet access.
- It is mostly impossible to guarantee that a player can figure out all the resources needed for a piece of HTML markup, in order to pre-load them before it tries to render the markup.
Solution
There is, unfortunately, no satisfactory solution to this problem. The most obvious solution is to use an image or video directly as the creative rather than using HTML markup. Most reasons why HTML markup is often used (such as impression reporting) are handled by other solutions found in this section.
Note that these problems may not apply to all players, so it is possible to ignore this problem if a buyer is targeting a media owner that it knows can successfully handle their HTML markup content.
6.4 Reporting audience numbers when reporting impressions
Normally, calling an impression/billing reporting URL indicates that a single person has viewed the ad. But an ad playing on a digital billboard can be viewed by multiple people and this number must somehow be reported.
Breakdown
- Calling an impression/billing reporting URL normally signals a single view.
- When a creative is played by a digital billboard, it will be seen by multiple people.
- We must somehow report that number to the DSP for correct impression counting and billing.
Solution
Three substitution macros will be added to help in reporting these numbers. The following macros can be applied to the URL of the “impurls” field of the ImpExt object. Also, these macros can be applied to the HTML markup, but not to the win notice URL (as these numbers are not yet known when the URL is called).
Macro Value:
- ${TOTAL_IMP} - The total audience count when the ad was played. This macro is populated in the tracking URLs.
- ${TARGET_IMP} - The total targeted audience count when the ad was played. This is calculated by multiplying the total audience count by the targeted audience concentration for that play.
- ${AUCTION_PRICE} - Clearing price using the same currency and units as the bid.
- ${TOTAL_PRICE} - The total price to bill. This is calculated according to the winning price and the total audience number. Here,
${TOTAL_PRICE} = ${TOTAL_IMP} * ${AUCTION_PRICE} / 1000
. We divide the auction price by one thousand because it is a CPM (cost per mille).
6.5 Currency conversion
We currently support currency conversion, upon request during the integration process, from any currency to USD. This means bid requests for inventory in any currency can be emitted in the converted USD value and can be answered in USD.
Solution
External DSPs have to make sure that they respond to our bid requests with the same currency specified in the cur
field of bid requests. If currency conversion is enabled, the cur
field will contain the currency to which the original value has been converted. The currency in the response also has to match the bidfloorcur
of the ImpObject the external DSP bids for. We expect a bid response that has the same currency as the bid request.
6.6 Synchronizing ad plays on several units
Some media owners want to have the ability to play ads simultaneously on several units of their inventory. This is especially useful when transacting with sites instead of units, to ensure that all units on the site are playing the same creative.
Solution
The sync group feature allows the synchronization of ad plays on groups of units. When using sync groups, a primary unit will synchronize ad plays on a group of secondary units. The ad scheduled for the primary unit will be played at the same time on all units of the group. In order for sync groups to be able to play the same creative simultaneously, creative files must be provided for all different unit resolutions in the sync group.
Any missing or non-approved creative file for one of the sync group's unit dimensions will result in the ad not being scheduled to play.
There are two methods to handle sync groups at the bid request level, those can be configured during the integration process and are as follow:
- The default method is to send multiple bid requests, one for each resolution in the sync group, each containing a single ImpObject. For this method, a standard bid response as described in section 6.4, containing a single Bid will be accepted for each emitted request.
- The second option is to send a single bid request with one ImpObject for each resolution in the sync group. This option requires answering the bid request with a single response containing several Bid objects, each of them with an adm field corresponding to the ImpObject it is answering to. This is reflected by the
impid
fields in the Bid objects of the response, corresponding to theid
of the ImpObject which were present in the bid request.
For the second method, examples of the emitted bid request and expected bid response are illustrated below.
Example of a single bid request for a sync group:
{
"id":"44ebf533-f884-4432-a581-5f7ed3007c22",
"imp":[
{
"id":"1",
"banner":{
"w":1080,
"h":1920,
"pos":7,
"mimes":[
"image/jpeg",
"image/png",
"image/bmp",
"image/gif",
"image/webp",
"text/html",
"application/html",
"application/zip"
]
},
"video":{
"mimes":[
"video/avi",
"video/mpg",
"video/flv",
"video/mp4",
"video/webm",
"video/quicktime"
"text/html",
"application/html",
"application/zip"
],
"minduration":6,
"maxduration":6,
"protocols":[1, 2, 3, 4, 5, 6, 7, 8],
"w":1080,
"h":1920,
"startdelay":0,
"sequence":0,
"pos":7,
"ext": { "audio": 0 }
},
"displaymanager":"MANAGER-1",
"instl":1,
"bidfloorcur":"EUR",
"secure":0,
"pmp":{
"private_auction":1,
"deals":[
{
"id":"ABCde-1234",
"bidfloor":0.87,
"bidfloorcur":"EUR",
"wseat":[
"seat-id"
],
"ext":{
"deal_type": 2,
"must_bid": 0
}
}
]
},
"ext":{
"totalaud":78.1724,
"screenids":[
"screen-1",
"screen-2",
"screen-3",
"screen-4"
],
"qty": {
"multiplier": 78.1724,
"sourcetype": 1,
"vendor": "Some impression multiplier measurement vendor"
}
}
},
{
"id":"2",
"banner":{
"w":1280,
"h":720,
"pos":7,
"mimes":[
"image/jpeg",
"image/png",
"image/bmp"
]
},
"video":{
"mimes":[
"video/avi",
"video/mpg",
"video/flv",
"video/mp4",
"video/webm",
"video/quicktime"
],
"minduration":6,
"maxduration":6,
"protocols":[1, 2, 3, 4, 5, 6, 7, 8],
"w":1280,
"h":720,
"startdelay":0,
"sequence":0,
"pos":7,
"ext": { "audio": 0 }
},
"displaymanager":"MANAGER-1",
"instl":1,
"bidfloorcur":"EUR",
"secure":0,
"pmp":{
"private_auction":1,
"deals":[
{
"id":"ABCde-1234",
"bidfloor":0.87,
"bidfloorcur":"EUR",
"wseat":[
"seat-id"
],
"ext":{
"deal_type": 2,
"must_bid": 0
}
}
]
},
"ext":{
"totalaud":54.5093,
"screenids":[
"screen-5",
"screen-6",
"screen-7"
]
}
},
{
"id":"3",
"banner":{
"w":1920,
"h":1080,
"pos":7,
"mimes":[
"image/jpeg",
"image/png",
"image/bmp"
]
},
"video":{
"mimes":[
"video/avi",
"video/mpg",
"video/flv",
"video/mp4",
"video/webm",
"video/quicktime"
],
"minduration":6,
"maxduration":6,
"protocols":[1, 2, 3, 4, 5, 6, 7, 8],
"w":1920,
"h":1080,
"startdelay":0,
"sequence":0,
"pos":7,
"ext": { "audio": 0 }
},
"displaymanager":"MANAGER-1",
"instl":1,
"bidfloorcur":"EUR",
"secure":0,
"pmp":{
"private_auction":1,
"deals":[
{
"id":"ABCde-1234",
"bidfloor":0.87,
"bidfloorcur":"EUR",
"wseat":[
"seat-id"
],
"ext":{
"deal_type": 2,
"must_bid": 0
}
}
]
},
"ext":{
"totalaud":31.2125,
"screenids":[
"screen-8",
"screen-9",
"screen-10",
"screen-11"
]
}
}
],
"app":{
"id":"screen-1",
"domain":"domain.com",
"publisher":{
"id":"MANAGER-1",
"name":"Mediaowner",
"domain":"domain.com"
}
},
"device":{
"geo":{
"lat":50.04117,
"lon":10.22613,
"type":3,
"country":"DEU",
"region":"BY",
"city":"DESCW",
"utcoffset":120,
"zip":"80639"
},
"ifa":"57726551-3bc8-fd63-a1e6-6884aa9a6d3e",
"ext":{
"siteid":"1234",
"networkid":"network",
"dooh":{
"venuetypeid":205
}
}
},
"at":1,
"tmax":2000,
"allimps":0,
"cur":[
"EUR"
]
}
Example of a single bid response for a sync group:
{
"id": "44ebf533-f884-4432-a581-5f7ed3007c22",
"seatbid": [
{
"bid": [
{
"id": "7125065197458485130",
"impid": "1",
"price": 0.87,
"adm": "VAST XML, see examples in section 6.4",
"adomain": ["domain-url.com"],
"crid": "123",
"cat": ["IAB3"],
"dealid": "ABCde-1234",
"lurl": "A http or https url",
"burl": "A http or https url",
"nurl": "A http or https url",
"ext": {
"impurls": ["List of imp URLs. We support OpenRTB macros."]
}
},
{
"id": "7125065197458486410",
"impid": "2",
"price": 0.87,
"adm": "VAST XML, see examples in section 6.4",
"adomain": ["domain-url.com"],
"crid": "123",
"cat": ["IAB3"],
"dealid": "ABCde-1234",
"lurl": "A http or https url",
"burl": "A http or https url",
"nurl": "A http or https url",
"ext": {
"impurls": ["List of imp URLs. We support OpenRTB macros."]
}
},
{
"id": "7125065197458487178",
"impid": "3",
"price": 0.87,
"adm": "VAST XML, see examples in section 6.4",
"adomain": ["domain-url.com"],
"crid": "123",
"cat": ["IAB3"],
"dealid": "ABCde-1234",
"lurl": "A http or https url",
"burl": "A http or https url",
"nurl": "A http or https url",
"ext": {
"impurls": ["List of imp URLs. We support OpenRTB macros."]
}
}
],
"seat": "seat-id"
}
],
"cur": "EUR"
}
7 Use of the OpenRTB API
This section of the document describes how the OpenRTB standard is used and extended in order to successfully go through the process of allowing buyers to target players to play their ads.
The workflow itself has not changed: when an ad is needed, a request is made, the bids are tallied, the winner is immediately notified using the win notice URL and the creative is retrieved to be played.
In addition to the extensions mentioned in the “Challenges” section, a few useful fields have been added in order to help with targeting by exposing new information such as the audio capabilities of a player or the kind of location it is in.
Legend
Type | Description |
---|---|
* | No specific value, the “Notes” column contains more information. |
[...] | An array of values or objects. |
{...} | A sub-object. |
empty | Omitted or empty value. |
7.1 Request format
The requests sent by Hivestack simulate a fullscreen ad. Each call is made for a single campaign each time it needs content to play. Support for multiple campaigns in a single request may be considered in the future in order to minimize the number of requests.
The request will typically be made in advance so that the content of the ad can be fully retrieved before the ad is planned to play.
Fields that are not specified here will be omitted in the actual request.
7.1.1 BidRequest
Key | Value | Description |
---|---|---|
id | * | A unique ID in the form of a GUID. |
imp | [...] | An array containing one or more Imp objects. Multiple Imp objects are usually used when dealing with unit groups containing units of different screen resolutions. |
app | {...} | An App object. |
site | {...} | A Site object. |
device | {...} | A Device object. |
test | 0 / 1 | 0 – Normal billable campaign 1 – Non-billable test campaign |
at | 1 / 2 / 3852512 | 1 – First Price 2 – Second Price 3852512 – Pre-approved campaigns only |
tmax | * | The max timeout before closing the connection. 700 ms by default. |
wseat | [...] / empty | White listed seats. |
allimps | 0 | |
cur | [...] / empty | List of supported currencies (ISO-4217 alpha codes). May be empty if the request is for a pre-approved deal. |
bcat | [...] / empty | Blacklisted iab categories. |
badv | [...] / empty | Blacklisted advertisers. |
7.1.2 Imp
Attribute | Value | Notes |
---|---|---|
id | * | A unique(within the request) sequential number. |
banner | {...} / empty | A Banner instance offering information for still image content. If the media owner/player does not support still images, this attribute will be omitted. |
video | {...} / empty | A Video instance offering information for video, flash or HTML content. If the media owner/player does not support video content, this attribute will be omitted. |
displaymanager | * | A unique identifier for the media owner. Can be used by the DSP to customize the response. |
displaymanagerver | * / empty | A version number provided by the media owner. This field may be empty. Can be used to customize the response. |
instl | 1 | The ad is interstitial (full screen). |
bidfloor | * | The minimum bid required. It is expressed in CPM. |
bidfloorcur | * | The currency of the minimum bid. The currency is specified in ISO-4217 alpha codes (e.g. "USD"). |
secure | 0 | A flag to indicate if HTTPS is used. We currently only support HTTP, which is why we default to 0. |
pmp | {...} / empty | A Pmp instance describing any marketplaces deals in effect. |
ext | {...} | An ImpExt instance |
7.1.3 ImpExt (Extension)
Attribute | Value | Type | Notes |
---|---|---|---|
totalaud | * | float | The total number of viewers in the audience. This is equivalent to the value in ${TOTAL_IMP}, unless we are using unit groups and a unit inside the group didn't play. |
dataprovider | * / empty | integer | An optional code indicating the source of the audience information. 0 – Other or not specified 1 – Publisher’s own research 10 – GeoPath 11 – Nielsen 12 – Quividi |
screenids | [...] | array | An array containing the id(s) of the screen(s). There is more than 1 screen when dealing with sync groups. |
screeninfos | [{...}, ...] | array | An array of screen info objects. Each screen info object can contain a name and an external_id , i.e., [{"name": "foo", "external_id": "bar"}, ...] . The availability of the screeninfos The list of objects is media owner-dependent. |
qty | {...} / empty | Qty | An optional Qty object, this object includes the impression multiplier, and describes the source of the multiplier value. See Section 7.1.18 |
7.1.4 Audience (Extension)
Attribute | Value | Type | Notes |
---|---|---|---|
demo | [...] | array of strings | List of demographic categories of this slice of the audience. Each entry contains a string code describing the demographic. If the array contains multiple entries, they all apply (ex: Male and aged 16-21).
See Appendix A for a description of these codes. |
aud | * | float | A value between 0.0 and 1.0 representing the fraction of the total audience that correspond to all the demographic categories in the “demographics” field. |
7.1.5 Banner
Attribute | Value | Notes |
---|---|---|
w | * | Width, in pixels, of the player’s screen. |
h | * | Height, in pixels, of the player’s screen. |
pos | 7 | The ad position of the screen. We default to fullscreen (7). |
mimes | [...] | List of formats supported by the media owner. |
7.1.6 Video
Attribute | Value | Notes |
---|---|---|
mimes | [...] | List of formats supported by the media owner. |
minduration | * | Minimun duration allowed for a video ad, in seconds. |
maxduration | * | Maximum duration allowed for a video ad, in seconds. |
protocols | [...] / empty | This value depends on the support offered by the media owner. If empty, the video should be served directly through the response of the win notice URL. |
w | * | Width, in pixels, of the player’s screen. |
h | * | Height, in pixels, of the player’s screen. |
startdelay | 0 | Not applicable in this case |
sequence | 0 | |
pos | 7 | The ad position of the screen. We default to fullscreen (7). |
ext | {...} | A VideoExt instance |
7.1.7 VideoExt (Extension)
Attribute | Value | Notes |
---|---|---|
audio | * | 0 – No sound 1 – Sound available 2 – Sound required |
7.1.8 Pmp
Attribute | Value | Notes |
---|---|---|
private_auction | 0 / 1 | Always “1” for pre-approved campaigns. |
deals | [...] | An array containing a one or more Deal instances. |
7.1.9 Deal
Attribute | Value | Notes |
---|---|---|
id | * | A friendly string identifying the deal. |
bidfloor | * | Minimum bid for the play, expressed in CPM. In the case of pre-approved campaigns, this amount will always be 0. |
bidfloorcur | * | The currency of the minimum bid. The currency is specified in ISO-4217 alpha codes (e.g. "USD"). |
wseat | [...] / empty | Whitelist of seats allowed to bid for this deal. |
ext | {...} / empty | A DealExt instance |
7.1.10 DealExt
Attribute | Value | Notes |
---|---|---|
deal_type | 0 / 1 / 2 / 3 | 0 - UNKNOWN (Default) 1 - GUARANTEED 2 - NON_GUARANTEED 3 - PREFERRED |
must_bid | 0 / 1 | 0 - False (Default) 1 - True (Only applicable to GUARANTEED deal_type. When True, bidders are expected to bid) |
7.1.11 App
Attribute | Value | Notes |
---|---|---|
id | * / empty | An optional external ID of the primary unit of the unit group making the ad request. |
name | * / empty | An optional name for the media owner’s unit. |
domain | * / empty | An optional domain for the media owner’s unit. |
publisher | {...} | A Publisher object. |
7.1.12 Publisher
Attribute | Value | Notes |
---|---|---|
id | * | A unique ID representing the media owner. |
name | * | Name of the media owner. |
domain | * | Domain of the media owner. |
7.1.13 Device
Attribute | Value | Notes |
---|---|---|
ua | * / empty | If the media owner/player supports HTML ads, it may report the user agent string of the internal engine it uses. |
geo | {...} / empty | A Geo instance. May be omitted if the location is unknown. |
h | * / empty | Physical height of the screen in pixels. Omitted if unknown. |
w | * / empty | Physical width of the screen in pixels. Omitted if unknown. |
ppi | * / empty | Screen size as pixels per linear inch. Omitted if unknown. |
pxratio | 1 | Very unlikely to be any other number. |
js | 0 / 1 | Support for JavaScript. Use of JavaScript is not recommended. |
flashver | Version of Flash supported by the media owner/player. Omitted if Flash is either not supported or the media owner cannot guarantee the support of a specific version. | |
ifa | * / empty | The openRTB UUID of the screen, a value that is unique and that won't change in time for that screen in HS. It can be used as an alternative screen identifier as multiple pubs can have the same screen ID amongst themselves (though the screen ID value will always be unique in a given publisher). In a handful of markets (Japan mainly) this information can sometimes be omitted. |
ext | {...} | A DeviceExt instance. |
7.1.14 DeviceExt (Extension)
Attribute | Value | Type | Notes⠀ |
---|---|---|---|
siteid | * / empty | string | The site id of the screen. |
networkid | * / empty | string | The network id of the screen. |
deviceloc | * / empty | string | The screen's location code. |
aspectratiotolerance | * / empty | float | Defines the acceptable stretching tolerance for the aspect ratio of this media owner. Refer to Appendix B for further details. This value is expressed as a float between 0 and 1, where, for example, 0.1 represents a 10% tolerance. |
dooh | {...} | DOOH | DOOH instance. |
7.1.15 DOOH
Attribute | Value | Type | Notes |
---|---|---|---|
venuetypeid | * / empty | integer | The venue type id of the screen. You can find more info on the different possible venue types here. We plan on integrating a list of venue type ids in the future. |
7.1.16 Geo
Attribute | Value | Notes |
---|---|---|
lat | * | |
long | * | |
type | 3 | Provided by the media owner. |
country | * | |
region | * | |
city | * | |
zip | * | Zip code of the unit's location. |
utcoffset | * |
7.1.17 Site
Attribute | Value | Notes |
---|---|---|
id | * / empty | An optional external ID of the primary unit of the unit group making the ad request. |
name | * / empty | An optional name for the media owner’s unit. |
domain | * / empty | An optional domain for the media owner’s unit. |
page | * / empty | An optional page for the media owner’s unit. |
publisher | {...} | A Publisher object. |
7.1.18 Qty (Extension)
Attribute | Value | Type | Notes |
---|---|---|---|
multiplier | * | float | The quantity of billable events which will be deemed to have occurred if this item is purchased. Equivalent to ImpExt.totalaud |
sourcetype | 0 / 1 / 2 / 3 | int | The source type of the quantity measurement, ie. publisher. Refer to DOOH Multiplier Measurement Source Types enum |
vendor | * | string | If sourcetype is equal to 1, the top level business domain name of the measurement vendor providing the quantity measurement. |
7.2 Bid request sample
Below is a sample of a bid request. It is worth noting that we default to filling the request.site
object by default. If needed, we can fill the request.app
object instead. Either way, we will always fill the same object on subsequent requests.
{
"id": "b4f3e018-022e-4ae5-aca6-fa953348688c",
"imp": [
{
"id": "1",
"banner": {
"w": 1920,
"h": 1080,
"pos": 7,
"mimes": [
"image/jpeg",
"image/png",
"image/bmp",
"image/gif",
"image/webp",
"text/html",
"application/html",
"application/zip"
]
},
"video": {
"mimes": [
"video/avi",
"video/mpg",
"video/flv",
"video/mp4",
"video/webm",
"video/quicktime",
"text/html",
"application/html",
"application/zip"
],
"minduration": 5,
"maxduration": 30,
"protocols": [1, 2, 3, 4, 5, 6, 7, 8],
"w": 1920,
"h": 1080,
"startdelay": 0,
"sequence": 0,
"pos": 7,
"ext": { "audio": 0 }
},
"displaymanager": "MANAGER-1",
"instl": 1,
"bidfloor": 0.01,
"bidfloorcur": "CAD",
"secure": 0,
"pmp": {
"private_auction": 1,
"deals": [
{
"id": "deal-id",
"bidfloor": 2.0,
"bidfloorcur": "CAD",
"wseat": ["seat-id"],
"ext": {
"deal_type": 2,
"must_bid": 0
}
}
]
},
"ext": {
"totalaud": 77.1563333,
"screenids": ["screen-1"],
"screeninfos": [{ "name": "screen-1", "external_id": "screen-1" }],
"qty": {
"multiplier": 77.1563333,
"sourcetype": 2
}
}
}
],
"app": {
"id": "screen-1",
"domain": "domain.com",
"publisher": {
"id": "MANAGER-1",
"name": "Mediaowner",
"domain": "domain.com"
}
},
"site": {
"id": "screen-1",
"domain": "domain.com",
"page": "http://domain.com",
"publisher": {
"id": "MANAGER-1",
"name": "Mediaowner",
"domain": "domain.com"
}
},
"device": {
"geo": {
"lat": 40.137,
"lon": 10.67641,
"type": 3,
"country": "CAN",
"region": "QC",
"city": "MONTREAL",
"utcoffset": 60,
"zip": "H2Y2P1"
},
"w": 1920,
"h": 1080,
"ifa": "cff08971-d5f7-4a25-bd8d-dcbb3fc12ae2",
"ext": {
"siteid": "1234",
"networkid": "network",
"aspectratiotolerance": 0.1,
"dooh": {
"venuetypeid": 105
}
}
},
"test": 0,
"at": 1,
"tmax": 2000,
"allimps": 0,
"cur": ["CAD"]
}
7.3 Expected bid response
The bid response from the DSP.
If the response does not include any bids, an error code is included in the response or the server returns a 40x/50x response, the Hivestack system will try again up to five times. If it does not receive a successful bid by then, it will assume that there is no content to play (if there are no bids) or there is a problem with the DSP (in case of an error).
Values that are not needed by Hivestack will be ignored. The “expected value” column simply represents what would normally be expected in this scenario. Omitting a field or sending a value different from the “expected value” will not trigger an error or rejection of the response unless marked as mandatory in the OpenRTB specification or if specified otherwise in the “notes” column.
7.3.1 BidResponse
Attribute | Expected Value | Notes |
---|---|---|
id | * | ID of the bid request (as normal) |
seatbid | [...] | Represents an array of BidSeat objects. |
bidid | * | Any string. Will be saved for logging/tracking purposes. |
cur | * | The currency of the bid. The currency is specified in ISO-4217 alpha codes (e.g. "USD"). Since we don't support currency conversion, this must be the same currency as one of the currencies specified in the bid request. |
customdata | empty | Not currently supported. |
nbr | empty | Not currently supported. |
ext | empty | No extensions have currently been agreed upon. Any value will be ignored. |
7.3.2 BidSeat
Attribute | Expected Value | Notes |
---|---|---|
bid | [...] | Represents an array of Bid objects. As in the OpenRTB standard, the bid is in CPM, with the final price being determined by the total number of impressions (not targeted impressions) when the ad is played. |
seat | * | The ID of the buyer's seat. |
ext | empty | No extensions have currently been agreed upon. Any value will be ignored. |
7.3.3 Bid
Attribute | Expected Value | Notes |
---|---|---|
id | * | |
impid | * | The ID of the Imp object in the related bid request. Each bid object in the bid response must have a unique impid |
price | * | The bid price expressed in CPM. |
adid | empty | Preloaded ads are not supported. This field can be used as a fallback for creative approval and caching if crid is not available, but use of the crid field is preferred. |
nurl | * | The “${TOTAL_IMP}”, “${TARGET_IMP}” and “${TOTAL_PRICE}” substitutions macros cannot be used in this URL as the actual impression audience numbers are not known yet. We support all OpenRTB macros here. The field is not required, but we recommend filling it. |
burl | * | The url called when a winning bid becomes billable. We support all OpenRTB macros here. The field is not required, but we recommend filling it. |
lurl | * | The url called when a bid has lost. We support all OpenRTB macros here. The field is not required, but we recommend filling it. |
adm | * | This field usually contains the picture or the video. The picture or the video should be VAST XMLs. We do not support HTML or Javascript in this field for the reasons mentioned in 6.3. We support all OpenRTB macros here. Examples of the expected VAST XML formats can be found in section 7.4. |
adomain | [...] | An array of advertiser domains, only the first value of the array is used, to check if the advertiser domain is denylisted and for reporting features. The expected format is domain.com or https://domain.com . Including a trailing / or a path after the domain (e.g. https://domain.com/path ) will result in issues when validating the advertiser. |
bundle | empty | Any value in this field will be ignored. |
iurl | empty | Any value in this field will be ignored, unless support for this field has been explicitly requested by the DSP, during the integration process. In that case this can be the url of the image creative, the field will be ignored if adm is populated. |
cid | empty | Any value in this field will be ignored. |
crid | * | A unique identifier for the creative. Used for creative approval and caching. If this field is not specified, the adid will be used as a fallback, but use of this field is preffered. |
cat | [...] | An array of IAB content categories for the creative. |
attr | [...] / empty | Any values will be ignored. |
dealid | * | |
h | * | |
w | * | |
ext | {...} | A BidExt object. This is optional and can be omitted, but it’s use is highly recommended. |
7.3.4 BidExt (Extension)
Attribute | Expected Value | Type | Notes |
---|---|---|---|
impurl | * | string (URL) | This field has been deprecated in favour of the "impurls" field. |
impurls | * | array of strings (URLs) | A list of URLs to call to submit an impression when the creative is played, thus confirming the billing of the play. Can be used as an alternative in cases where there is no other way to submit such a URL. For example, in cases where the win notice URL directly returns the creative. Substitution macros can be used in the URL. Including the “${TOTAL_IMP}”, “${TARGET_IMP}” and “${TOTAL_PRICE}” macros. This parameter is optional. |
targetdemo | [...] | array of strings | The list of targeted demographics. This list will be used to calculate the number of targeted impressions (for the “${TARGET_IMP}” substitution macro). Each entry in the array is a string with the code of the targeted demographic. As long as person is included in at least one of the values for each demographic type specified, then they are considered part of the target. For example, the ["GNDR-M", "AGE-15-17", "AGE-18-24"] array will target males which are also in either the 15-17 or 18-24 age ranges.If this field is omitted, or the whole BidExt object is omitted, Hivestack will assume that no demographic is specifically targeted. |
imptrackers | [...] | array of strings | Any value in this field will be ignored, unless support for this field has been explicitly requested by the DSP, during the integration process. A list of URLs to call to submit an impression when the creative is played, thus confirming the billing of the play. Can be used as an alternative in cases where there is no other way to submit such a URL. For example, in cases where the win notice URL directly returns the creative. Substitution macros can be used in the URL. Including the “${TOTAL_IMP}”, “${TARGET_IMP}” and “${TOTAL_PRICE}” macros. This parameter is optional. |
7.4 Bid response sample
Here is an example of a bid response. The VAST XML is usually sent in the adm
field of a Bid instance. To make it more readable, the adm
value is displayed further ahead. Although it is not shown in the example, we support VAST redirections (i.e. <VASTAdTagURI>
) and we always unwrap intermediate VASTs.
{
"id": "d212ea04-443f-4dd4-8eb7-084ed71d1429",
"cur": "CAD",
"seatbid": [
{
"bid": [
{
"adm": "VAST XML, see examples below",
"ext": {
"impurls": ["List of imp URLs. We support OpenRTB macros."]
},
"nurl": "A http or https url",
"burl": "A http or https url",
"lurl": "A http or https url",
"id": "7062827105545311234",
"impid": "1",
"price": 6.0,
"adid": "123",
"crid": "123",
"adomain": ["domain-url.com"],
"dealid": "ABCde-1234"
}
],
"seat": "9876"
}
]
}
An example of a VAST XML for a video is shown below.
<?xml version="1.0" encoding="utf-8"?>
<VAST version="2.0">
<Ad id="123">
<InLine>
<AdSystem>DSP</AdSystem>
<AdTitle><![CDATA[Title]]></AdTitle>
<Impression><![CDATA[Impression URI]]></Impression>
<Error><![CDATA[Error URI]]></Error>
<Creatives>
<Creative>
<Linear>
<Duration>00:00:05</Duration>
<TrackingEvents>
<Tracking event="firstQuartile"><![CDATA[First quartile tracking URI]]></Tracking>
<Tracking event="midpoint"><![CDATA[Second quartile tracking URI]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile width="1920" height="1080" type="video/mp4" delivery="progressive"><![CDATA[Media file URI]]></MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>
For a picture, the result is similar, but the type of the <MediaFile>
tag reflects the format of the creative file (e.g. image/jpeg) as shown below.
For images, do not use
bitrate="null"
in the<MediaFile>
tag, as this is not supported. Simply omit the property or set a numeric value such asbitrate="0"
<?xml version="1.0" encoding="utf-8"?>
<VAST version="2.0">
<Ad id="123">
<InLine>
<AdSystem>DSP</AdSystem>
<AdTitle><![CDATA[Title]]></AdTitle>
<Impression><![CDATA[Impression URI]]></Impression>
<Error><![CDATA[Error URI]]></Error>
<Creatives>
<Creative>
<Linear>
<Duration>00:00:05</Duration>
<TrackingEvents>
<Tracking event="firstQuartile"><![CDATA[First quartile tracking URI]]></Tracking>
<Tracking event="midpoint"><![CDATA[Second quartile tracking URI]]></Tracking>
</TrackingEvents>
<MediaFiles>
<MediaFile width="1920" height="1080" type="image/jpeg" delivery="progressive"><![CDATA[Media file URI]]></MediaFile>
</MediaFiles>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>
8 Sellers.json File
Our Sellers.json file allows the identity of the final seller of a bid request to be discovered. Learn more about the Sellers.json file from IAB Tech Lab here.
8.1 Seller
Attribute | Value | Notes |
---|---|---|
seller_id | * | Seller identifier, same as Publisher.Id property of an OpenRTB request |
name | * | The name of the company (the legal entity) that is paid for inventory that is transacted under the given seller_id |
domain | * | The business domain name of the company (the legal entity) that is paid for inventory that is transacted under the given seller_id. |
seller_type | PUBLISHER / INTERMEDIARY / BOTH | PUBLISHER - the inventory sold through this account is on a site, app, or other medium owned by the named entity and the advertising system pays them directly. INTERMEDIARY - the inventory sold through this account is not owned by the named entity or the advertising system does not pay them directly. BOTH - both types of inventory are transacted by this seller. |
ext | {...} | An optional SellerExt object. See section 8.2 |
8.2 SellerExt
Attribute | Value | Notes |
---|---|---|
impression_multiplier_verifier | {...} | A ImpressionMultiplierVerifier object to provide transparency on how publishers verify their impression multipliers for each unit. See Section 8.3 |
8.3 ImpressionMultiplierVerifier
Attribute | Value | Notes |
---|---|---|
sourcetype | 0 / 1 / 2 / 3 | Iab Lab Multiplier Measurement Source Type Enum |
sourcetype_description | * | Iab Lab Multiplier Measurement Source Type Enum Description |
vendor | * | If sourcetype is equal to 1, the top level business domain name of the measurement vendor providing the quantity measurement |
notes | * | Optional notes field to describe in more detail how the seller collects impression multiplier data |
9 Custom Loss Reason Codes
Value | Description |
---|---|
1000 | Not all units in the sync group were bid on |
1001 | Bids for units in sync group do not match |
1004 | Deal name too long |
1005 | Deal name invalid |
Appendix A. Demographic codes
Because media owners may organize their demographic categories differently, the demographic code system was designed to be as flexible as possible. The codes are designed such that they completely describe the demographic without referring to a common table, being overly long or hard to parse.
There are two kinds of demographics: value ranges and discrete values.
Values ranges represent demographics that cover a part of a spectrum of values, such as age and household income. Values ranges use the following format: “[type]-[min]-[max]”. Either or both the “min” or “max” parts can be replaced with “*” in order to signify that there is no minimum or maximum. Also, in order to shorten the numbers, the “K”, “M”, and “B” suffixes can be used for thousands, millions, and billions. See below for a list of types and examples.
Discrete values represent demographics that have discrete possible values, such as gender. Each value can be a number or a code. The following format is used: “[type]-[value]”. If the value is numeric, the “<” (ex: “ABC-<10”) or “+” (ex: “ABC-10+”) characters indicate that lower or higher values are also included. The “*” character can also be used as a placeholder for all possible values. See below for a list of types and examples.
Currently supported demographic types
Note: The demographic codes presented here are the recommended defaults. A supplier may use custom codes to better fit their demographic data. If you are receiving unexpected codes, please contact Hivestack support.
Age
The age demographic uses the “AGE” type code and is made of ranges in which both the
minimum and maximum are included. Once again, there are no predefined or fixed ranges, any interval can be used.
Examples:
Target | Code |
---|---|
All ages | AGE-*-* |
18 to 24 years old | AGE-18-24 |
65 or older | AGE-65-* |
Household income
The household income demographic uses the “HHI” type code and is made of ranges in which the minimum is included and the maximum is excluded. The currency should be inferred as the one in circulation in the country of the player.
Examples:
Target | Code |
---|---|
$0 - $24,999 | HHI-0-25K |
$40,000 - $59,999 | HHI-40K-60K |
$100,000 or more | HHI-100K-* |
$500,000 - $999,999 | HHI-500K-1M |
Gender
The gender uses the “GNDR” type code and corresponds to one of the following codes:
Target | Code |
---|---|
Any gender | GNDR-* |
Male | GNDR-M |
female | GNDR-F |
Other | GNDR-O |
Unknown | GNDR-? |
Appendix B. Aspect Ratio Matching
When determining whether a creative can play on a screen, Hivestack compares the aspect ratio of the screen and the creative. If the aspect ratio of the creative is within 10% of the screen aspect ratio, in either direction, we allow it to play on that screen. This means any creative with aspect ratio between 90% and 110% of a particular screen’s aspect ratio has a chance to play on that screen.
To ensure that portrait and landscape screens can scale equally, we calculate the aspect ratio of both the creative and the screen based on the resolution of the screen:
- if the screen is portrait: aspect ratio = height / width
- if the screen is landscape: aspect ratio = width / height
Once we have the screen aspect ratio, we can calculate the acceptable aspect ratios for creatives wanting to play on that screen. Subtract 10% to find the minimum value, and add 10% to find the maximum value. To illustrate, here are a few examples:
Screen 1 | Screen 2 | Screen 3 | |
---|---|---|---|
Screen dimensions | 1920 w x 1080 h | 1400 w x 400 h | 1080 w x 1920 h |
Screen aspect ratio | 1.7778 (w / h) | 3.5 (w / h) | 1.7778 (h / w) |
Compatible creative aspect ratios | 1.6000 to 1.9556 (w / h) | 3.1500 to 3.8500 (w / h) | 1.6000 to 1.9556 (h / w) |
Note that Hivestack is not the player which runs the creatives. We are simply allowing creatives to be sent to a screen for a given campaign. How the creative is actually displayed on those screens is outside of our control.
Also note that some media owners have a different tolerance than the default 10% for aspect ratio matching. The tolerance is still subtracted from and added to the screen aspect ratio in order to find the range of acceptable creative aspect ratios.
Changelog
Date (MM/DD/YYYY) | Changes |
---|---|
04/01/2025 | Added the description of aspectratiotolerance in section 7.1.14. |
03/21/2025 | Update the description of ifa in section 7.1.13 to clarify the purpose of this attribute. |
01/23/2025 | Updated the description of adomain in section 7.3.3 to better reflect format restrictions. |
01/15/2025 | Updated section 5 to describe inventory report weekly update and evergreen file. |
11/13/2024 | Added section 9 to list the custom loss reason codes we use. |
06/18/2024 | Added a description of screeninfos to section 7.1.3 . Added a screeninfos example to the sample bid request in 7.2. |
05/08/2024 | Updated the first paragraph of section 6.3 . Updated the mime types in examples of bid requests in sections 6.6 and 7.2 to addapplication/html and application/zip to the banner and video mimes lists. |
03/18/2024 | Updated the description of adomain in section 7.3.3 |
03/06/2024 | Added the "zip" property to bid requests examples in sections 6.6 and 7.2 . Added a description of "zip" to section 7.1.16 |
12/08/2023 | Added Appendix B |
09/11/2023 | Added descriptions of "minduration" and "maxduration" in Section 7.1.6 |
05/29/2023 | Added deal type preferred to Section 7.1.10 |
05/04/2023 | Removed mentions of non implemented "audbreakdown" from sections 6.6, 7.1.3, 7.2 and 7.3.4 |
01/27/2023 | Added Section 8.1 to describe all the fields and values we support in the Seller object(Sellers.json). Updated Section 8.2 and Section 8.3 to reflect changes in Section 8.1 |
01/26/2023 | Changed all references of "product" to "unit" in sections 7.1.11 and 7.1.17 |
01/24/2023 | Added Section 8 to describe the extension we added to our Sellers.json file Section 7.1.3 added qty field to ImpExt Added Section 7.1.18 to describe Qty extension added to ImpExt. Adjusted the bid request samples of sections 6.6 and 7.2 to reflect changes to section Section 7.1.3 and Section 7.1.18 |
01/18/2023 | Section 6.4 Added an explanation of the TARGET_IMP macro value calculation. Section 7.3.3 Specified that each bid object must have a unique impid in the same bid response. Section 7.1.9 Added mention of the ext attribute. Added Section 7.1.10 and adjusted following sections numbering. Adjusted the bid request samples of sections 6.6 and 7.2 to reflect changes to sections 7.1.9 and 7.1.10 |
Updated 3 months ago