OpenRTB protocol

OpenRTB substitution macros

Substitution macros are how the exchange reports auction outcomes back to the bidder. Before calling a win, billing, or loss notice URL, and when serving ad markup, the exchange replaces every recognized ${MACRO} token with live auction data: the clearing price, the impression ID, the loss reason. Section 4.4 of the 2.6 spec defines fourteen of them.

The full 2.6 macro table

MacroSubstituted withSince
${AUCTION_ID}ID of the bid request, from BidRequest.id.2.x core
${AUCTION_BID_ID}ID of the bid, from BidResponse.bidid.2.x core
${AUCTION_IMP_ID}ID of the impression just won, from imp.id.2.x core
${AUCTION_SEAT_ID}ID of the bidder seat for whom the bid was made.2.x core
${AUCTION_AD_ID}ID of the ad markup the bidder wishes to serve, from bid.adid.2.x core
${AUCTION_PRICE}Clearing price in the same currency and units as the bid; the final price after discount.2.x core
${AUCTION_CURRENCY}Currency of the bid, explicit or implied; confirmation only.2.x core
${AUCTION_MBR}Market Bid Ratio: clearing price divided by bid price.2.5
${AUCTION_LOSS}Loss reason code; the code list lives in OpenRTB 3.0.2.5
${AUCTION_MIN_TO_WIN}Minimum bid needed to win (or to tie the winner), same currency and units as the bid.2.6
${AUCTION_MULTIPLIER}Total quantity of impressions won, for DOOH-style multi-viewer inventory; float, may be below 1.2.6 updates
${AUCTION_IMP_TS}Unix timestamp in milliseconds of when the impression was fulfilled.2.6 updates
${AUCTION_DISCOUNT_PCT}Seller discount as a percentage of the bid price.2.6 updates
${AUCTION_DISCOUNT_CPM}Seller discount expressed as a CPM.2.6 updates

${AUCTION_MBR} and ${AUCTION_LOSS} arrived in 2.5, ${AUCTION_MIN_TO_WIN} in 2.6, and the multiplier, timestamp, and discount macros through the rolling 2.6 updates alongside DOOH and discount support. OpenRTB 3.0 defines a similar list under an OPENRTB_ prefix, for example ${OPENRTB_PRICE}, with item-based names (${OPENRTB_ITEM_ID}, ${OPENRTB_MEDIA_ID}) and without the multiplier, timestamp, and discount macros.

Where macros expand

Macros work in the notice URLs on the Bid object, nurl (win), burl (billing), and lurl (loss), and in the ad markup, whether it is returned in bid.adm or as the body of the win notice. See the bid response anatomy for how those fields relate. A common pattern is putting macros in a tracking pixel inside the markup so the win confirmation fires from the device itself.

A win notice URL before substitution:

https://bidder.example/win?req=${AUCTION_ID}&imp=${AUCTION_IMP_ID}&p=${AUCTION_PRICE}&cur=${AUCTION_CURRENCY}

And as the exchange calls it:

https://bidder.example/win?req=80ce30c5-3a3f-4862&imp=1&p=2.15&cur=USD

Substitution is textual and blind: "wherever a legal macro is found, it will be replaced without regard for syntax correctness", and an unknown optional value becomes a zero-length string. Values are not URL-encoded for you, so keep macros in query-string positions where the raw values (numbers, IDs, ISO codes) are URL-safe, and be careful when a macro lands inside markup you also escape.

Price encryption and loss reasons

When price data travels beyond the exchange, through the publisher page into the browser, exchanges often require the price macro encrypted. The spec's convention is a suffix naming the agreed algorithm: ${AUCTION_PRICE:B64}. The algorithms themselves are not standardized; each pair of parties agrees on one. Exchange policy may also strip ${AUCTION_PRICE} from loss notices entirely, replacing it with an empty string.

${AUCTION_LOSS} in a lurl carries a loss reason code from the list maintained in OpenRTB 3.0: 100 = bid was below auction floor, 102 = lost to higher bid, 200-range codes for creative filtering, and so on. Loss reasons describe a bid that lost; they are a different list from the no-bid reason codes a bidder sends in nbr, covered in no-bid reason codes.

FAQ

Where can OpenRTB macros be used?

In the win notice (bid.nurl), billing notice (bid.burl), and loss notice (bid.lurl) URLs, and in the ad markup itself, whether that markup is returned in bid.adm or in the body of the win notice response. The exchange performs the same substitution in all of these places, and compliant exchanges must support every macro for which data is available.

What is AUCTION_MIN_TO_WIN?

A macro added in OpenRTB 2.6 for bid shading feedback. If your bid lost, it is replaced with the minimum price that would have tied the winning bid. If your bid won, it is the price needed to tie the next-closest bid, or the floor if yours was the only bid. Exchanges may substitute the empty string when policy forbids sharing price data or when price was not the deciding factor.

What if a macro's value is unknown?

If the source value is an optional parameter that was not specified, the macro is replaced with a zero-length string. When markup is rendered for testing or ad quality review, the spec's best practice is to substitute the literal string AUDIT.

Validate it

Macros live in the bid response, and response validation is on the rtblint roadmap. What ships today is full bid request validation: paste a request into the bid request tester or run the CLI to catch structural mistakes before the auction ever reaches the notice-URL stage.