Process the Request

A real-time bidding interaction begins when Google sends a bid request to your application. This guide explains how to code your application to process the bid request.

Parse Protobuf request

Google sends a bid request as a serialized protocol buffer attached as the binary payload of an HTTP POST request. The Content-Type is set to application/octet-stream. See Example bid request for an example.

You must parse this request into an instance of the BidRequest message. Depending on your chosen protocol, BidRequest is defined in either openrtb.proto or the deprecated realtime-bidding.proto, which can be obtained from the reference data page. You can parse the message using the ParseFromString() method in the generated class for the BidRequest. For example, the following C++ code parses a request given a POST payload in a string:

string post_payload = /* the payload from the POST request */;
BidRequest bid_request;
if (bid_request.ParseFromString(post_payload)) {
  // Process the request.
}

Once you have the BidRequest you can then work with it as an object, extracting and interpreting the fields you need. For example, in C++ iterating through deals in an OpenRTB `BidRequest` could look like the following:

for (const BidRequest::Imp::Pmp::Deal& deal : pmp.deals()) {
  DoSomething(deal.id(), deal.wseat());
}

Billing IDs

You receive a bid request when a publisher's ad inventory is targeted by one or more of your pretargeting configurations. BidRequest.imp.ext.billing_id will be populated with the billing IDs of any eligible buyers, and relevant pretargeting configurations. Additionally, for deal inventory, you can find billing IDs associated with the relevant buyer using BidRequest.imp.pmp.deal.ext.billing_id. Only billing IDs of buyers included in the bid request may be specified when placing a bid.

If multiple billing IDs are included in the bid request, you must specify the billing ID of the buyer you intend to attribute your bid to with the BidResponse.seatbid.bid.ext.billing_id field.

Dictionary files

The bid request uses identifiers defined in dictionary files, which are available on the reference data page.

Google RTB protocol bid URL macros

Optionally, some fields of the BidRequest can be inserted into the URL used in the HTTP POST request. This is useful, for example, if you use a lightweight frontend that load balances over multiple backends using a value from the request. Contact your technical account manager to request support for new macros.

MacroDescription
%%GOOGLE_USER_ID%%

Replaced with the google_user_id from the BidRequest. For example, the bidder URL

http://google.bidder.com/path?gid=%%GOOGLE_USER_ID%%
will be replaced by something like
http://google.bidder.com/path?gid=dGhpyBhbiBleGFtGxl
at request time.

If the Google User ID is unknown, the empty string is substituted, with a result similar to

http://google.bidder.com/path?gid=
%%HAS_MOBILE%%

Replaced with 1 or 0 when calling BidRequest's has_mobile().

%%HAS_VIDEO%%

Replaced with 1 (true) or 0 (false) when calling BidRequest's has_video().

%%HOSTED_MATCH_DATA%%

Replaced with the value of the hosted_match_data field from the BidRequest.

%%MOBILE_IS_APP%%

Replaced with 1 (true) or 0 (false) from BidRequest's mobile.is_app field.

Find mobile app ID from transaction URL

Mobile application transactions will report URLs that look like this:

mbappgewtimrzgyytanjyg4888888.com

Use a base-32 decoder to decode the portion of the string in bold (gewtimrzgyytanjyg4888888).

You can use an online decoder, but you'll have to capitalize the letters and replace trailing 8s with = values.

So decoding this value:

GEWTIMRZGYYTANJYG4======
results in:
1-429610587
The string 429610587 is the app ID for the iOS app iFunny.

Here's another example. The reported URL is:

mbappgewtgmjug4ytmmrtgm888888.com
Decoding this value:
GEWTGMJUG4YTMMRTGM======
results in:
1-314716233
The result 314716233 is the app ID for the iOS app TextNow.

Find mobile app name from transaction URL

Here's an example of getting the app name. The reported URL is as follows:

mbappMFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q888.com
Decoding this value:
MFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q===
results in:
air.com.hypah.io.slither
The result equates to the Android app slither.io.

Open Bidding fields

Bid requests sent to exchange and network bidders participating in Open Bidding are similar to those of Authorized Buyers participating in standard real-time bidding. Open Bidding customers will receive a small number of additional fields, and a few existing fields may have alternative uses. These include the following:

OpenRTB Authorized Buyers Details
BidRequest.imp[].ext.dfp_ad_unit_code BidRequest.adslot[].dfp_ad_unit_code

Contains the publisher's Ad Manager network code followed by the ad unit hierarchy, separated by forward slashes.

As an example, this would appear with formatting similar to: /1234/cruises/mars.

BidRequest.user.data[].segment[] BidRequest.adslot[].exchange_bidding.key_value[]

Repeated key-value pairs sent from publisher to exchange bidder.

You can determine that the values are key-value pairs sent by the publisher when BidRequest.user.data[].name is set to “Publisher Passed”.

Declare allowed vendors

Technology vendors which provide services such as research, remarketing, and ad serving may play a role in the interaction between buyers and sellers. Only vendors which Google has vetted for participation in Authorized Buyers interactions are allowed.

To understand the BidRequest and create your BidResponse, you need to be aware of the two different possibilities for declaring technology vendors:

  1. Some vendors don't need to be declared; these vendors are listed in Ad Manager Certified External Vendors.
  2. Other vendors can only participate if they are declared in the BidRequest:
    • In the BidRequest, the BidRequest.imp.ext.allowed_vendor_type field specifies which vendors the seller allows. Vendors that will be sent in the allowed_vendor_type are listed in the vendors.txt dictionary file.

Example bid request

The following examples represent human-readable samples of the Protobuf and JSON requests.

OpenRTB Protobuf

OpenRTB JSON

Google (Deprecated)

To convert the bid request into a binary form, like you would get from the POST payload in a real request, you can do the following (in C++). Note, however, that this is not applicable to OpenRTB JSON.

string text_format_example = /* example from above */;
BidRequest bid_request;
if (TextFormat::ParseFromString(text_format_example, &bid_request)) {
  string post_payload;
  if (bid_request.SerializeToString(&post_payload)) {
    // post_payload is a binary serialization of the protocol buffer
  }
}

Real-time feedback

Real-time feedback is available to Authorized Buyers, as well as exchanges and networks using Open Bidding.

Bid response feedback is supported on the subsequent bid request for both OpenRTB and the deprecated Google RTB protocol. For OpenRTB, it is sent in BidRequest.ext.bid_feedback.

In addition to the default fields sent in Bid Response Feedback, you can also send custom data in the bid response using the BidResponse.seatbid.bid.ext.event_notification_token field. The event_notification_token is arbitrary data known only to the bidder that might help with debugging, for example: a new targeting ID or bidding ID representing a new tactic, or metadata associated with the creative known only to the bidder. For details, see OpenRTB Extensions Protocol Buffer for OpenRTB or the deprecated Google RTB protocol.

When Authorized Buyers sends a bid request to a bidder, the bidder replies with a BidResponse. If the bidder has real-time feedback enabled, then in a subsequent bid request, Authorized Buyers sends feedback on the response in a BidFeedback message:

message BidFeedback {
  // The unique id from BidRequest.id.
  optional string request_id = 1;

  // The status code for the ad. See creative-status-codes.txt in the
  // technical documentation for a list of ids.
  optional int32 creative_status_code = 2;

  // Deprecated. This field is not populated and will be removed after March,
  // 2025. If the bid won the auction, this is the price paid in your account
  // currency. If the bid participated in the auction but was out-bid, this
  // is the CPM that should have been exceeded in order to win. This is not
  // set if the bid was filtered prior to the auction, if the publisher or
  // winning bidder has opted out of price feedback or if your account has
  // opted out of sharing winning prices with other bidders. For first-price
  // auctions, minimum_bid_to_win is populated instead of this field.
  optional double price = 3 [deprecated = true];

  // The minimum bid value necessary to have won the auction, in your account
  // currency. If your bid won the auction, this is the second highest bid
  // that was not filtered (including the floor price). If your bid didn't win
  // the auction, this is the winning candidate's bid. This field will only be
  // populated if your bid participated in a first-price auction, and will not
  // be populated if your bid was filtered prior to the auction.
  optional double minimum_bid_to_win = 6;

  // The minimum bid value necessary to have won the server-side component of
  // the overall auction given that there was also an interest group bidding
  // component to the overall auction which ran using the Protected Audience
  // API. The value is expressed in CPM of the buyer account currency. The
  // minimum bid to win for the overall auction, including bids from the
  // server-side and the on-device interest group components, is populated in
  // the minimum_bid_to_win field of the same BidFeedback object.
  optional double sscminbidtowin = 14;

  // Billable event rate multiplier that was applied to this bid during
  // ranking. The adjustment reflects the likelihood that your bid would
  // generate a billable event (namely, the ad renders successfully) if it won
  // the auction, relative to the probability that other bids generate a
  // billable event if they won the auction. This adjustment can be larger or
  // smaller than 1. This affects the final ranking in the auction only; in
  // particular, this multiplier does not affect the payment or whether the
  // bid clears any floor price.
  optional float billable_event_rate_bid_adjustment = 13 [default = 1];

  // When a publisher uses an RTB auction and waterfall-based SDK mediation on
  // the same query, the winner of the real-time auction must also compete in
  // a mediation waterfall (which is ordered by price) to win the impression.
  // If the bid participated in the auction and there was no waterfall, the
  // value of this field is 0. If the bid participated in the auction and
  // there was a waterfall, the value of this field is a price representing a
  // sample bid from the eligible mediation networks that were higher than the
  // auction winner, weighted by expected fill rate. This field can be used
  // in conjunction with minimum_bid_to_win to train bidding models. The CPM
  // is in your account currency.
  optional double sampled_mediation_cpm_ahead_of_auction_winner = 8;

  message EventNotificationToken {
    // The contents of the token.
    optional string payload = 1;
  }

  // The token included in the corresponding bid.
  optional EventNotificationToken event_notification_token = 4;

  // The creative ID included in the corresponding bid.
  optional string buyer_creative_id = 5;

  // Possible types of bid response feedback objects.
  enum FeedbackType {
    FEEDBACK_TYPE_UNSPECIFIED = 0;

    // Feedback for a bid that was submitted on a bid response.
    BID_FEEDBACK = 1;

    // Feedback for an interest group buyer submitted on a bid response to
    // particpate in an interest group bidding component of the auction run
    // using the Protected Audience API.
    INTEREST_GROUP_BUYER_FEEDBACK = 2;
  }

  // The type of the BidFeedback message. Google will send separate
  // BidFeedback objects for:
  // a) Each bid submitted on a bid response
  // b) Each buyer submitted on a bid response to particpate in an interest
  // group bidding component of the auction run using the Protected Audience
  // API.
  optional FeedbackType feedbacktype = 15;

  // Origin of an interest group buyer that was included in the bid response.
  // This field is populated only for feedback where a bidder opted in an
  // interest group buyer to participate in the interest group bidding
  // component of the overall auction run using the Protected Audience API.
  // To learn more about origins, see https://www.rfc-editor.org/rfc/rfc6454.
  // To learn more about interest group bidding and the Protected Audience
  // API, see
  // https://developers.google.com/authorized-buyers/rtb/fledge-origin-trial.
  optional string buyerorigin = 16;

  // The status code for the submitted interest group buyer. This field is
  // only populated in the feedback for an interest group buyer that a bidder
  // requested to enter into the interest group auction through the bid
  // response. Individual creative status codes of bids submitted by the buyer
  // in the on-device interest group auction are not available. See
  // https://storage.googleapis.com/adx-rtb-dictionaries/interest-group-buyer-status-codes.txt
  // for a list of interest group buyer status codes.
  optional int32 igbuyerstatus = 17;
}

From this message, the first field you should check is bid_feedback.creative_status_code; you can find the code meaning in creative-status-codes.txt. Note that if you win the bid, you can opt out from the price feedback. For more information, see How to opt-out.

The real-time feedback includes the bid request ID and one of the following:

Auction outcome Real-time feedback
The buyer didn't submit a bid. Nothing.
The buyer submitted a bid that was filtered out before reaching the auction. The creative status code (creative-status-codes.txt).
The buyer submitted a bid but lost the auction. The creative status code 79 (outbid in auction).
The buyer submitted a bid that won the auction. The clearing price and creative status code 1.

For an app impression and a creative status code of 83, the app publisher could have been using a mediation waterfall and therefore the winning bid would have competed against other demand in the publisher's passback waterfall chain. Learn how to use sampled_mediation_cpm_ahead_of_auction_winner when bidding.

Sample

The following is a sample of real-time feedback as seen in supported protocols:

OpenRTB Protobuf

OpenRTB JSON

Google (Deprecated)

Build a bidding model for first-price auctions

After placing a bid in a first-price auction, you will receive real-time feedback including the minimum_bid_to_win and sampled_mediation_cpm_ahead_of_auction_winner fields if the bid was not filtered from the auction. These signals can be used to inform your bidding logic on how much higher or lower your bid could have been in order to win the impression.

  • minimum_bid_to_win: The minimum bid that could have been placed to win the real-time bidding auction. If you won the auction, this will be the lowest bid you could have placed while still winning. If you lost the auction, this will be the winning bid.
  • sampled_mediation_cpm_ahead_of_auction_winner: If there are other networks in the mediation chain, the value of this field is a price representing a sample bid from one of the eligible mediation networks that were higher than the auction winner, weighted by expected fill rate. This will be set to 0 if none of the networks in the mediation chain are expected to fill, or if the publisher does not use SDK mediation.

How it works

In order to describe the calculations used to determine the possible values for minimum_bid_to_win and sampled_mediation_cpm_ahead_of_auction_winner, we first need to define the following:

  • The following represents the CPMs in the mediation chain in descending order:
    \[C_1, C_2, …, C_n\]
  • The following represents the corresponding fill rates for the CPMs in the mediation chain:
    \[f_1, f_2, …, f_n\]
  • The following is a function used to determine the expected CPM and its probability from mediation chain element \(i\), based on the given fill rate:
    \(X_i = \{C_i\) with probability \(f_i\); \(0\) with probability \(1 - f_i\}\)
  • The final winning mediation chain will be:
    \[\{C_1, C_2, …, C_K, W\}\]
    where \(W\) is the winning bid, and \(C_K > W >= C_{K+1}\)
  • The reserve price, or floor, is denoted as \(F\).
  • The runner-up bid is denoted as \(R\).
Calculations for auction winner
Field Calculation
minimum_bid_to_win
\(max\{F, R, X_{K+1}, …, X_n\}\)
sampled_mediation_cpm_ahead_
of_auction_winner
\(\{C_i\) with probability \(\prod_{j=1}^{i-1}(1-f_j) \cdot f_i \div \prod_{j=1}^{K}(1-f_j)\}\)
For \(1 <= i <= K\).

Calculations for auction loser
Field Calculation
minimum_bid_to_win
\(max\{F, W\}\)
sampled_mediation_cpm_ahead_
of_auction_winner
\(max\{X_1, …, X_K\}\)

Example with a simple mediation chain

Assume a publisher uses both real-time bidding and an SDK mediation chain as follows:

SDK Mediation Chain Expected CPM Fill Rate
Network 1 \(C_1 = $3.00\) \(f_1 = 5\%\)
Network 2 \(C_2 = $2.00\) \(f_2 = 45\%\)
Network 3 \(C_3 = $0.50\) \(f_3 = 80\%\)
Network 4 \(C_4 = $0.10\) \(f_4 = 85\%\)

Assume the following as the result of the RTB auction:

RTB Auction CPM
Auction Winner (W) $1.00
Auction Runner-UP (R) $0.05
Reserve Price / Floor (F) $0
Bid that won the auction

The following is an example of how values and probabilities for minimum_bid_to_win and sampled_mediation_cpm_ahead_of_auction_winner are calculated for a bid that won.

minimum_bid_to_win Probability
\(max(F, R, C_3) = $0.50\) \(f_3 = 80\%\)
\(max(F, R, C_4) = $0.10\) \((1-f_3) \cdot f_4 = 17\%\)
\(max(F, R, 0) = $0.05\) \((1-f_3) \cdot (1-f_4) = 3\%\)
sampled_mediation_cpm_
ahead_of_auction_winner
Probability
\(C_1 = $3.00\) \(f_1 \div (1-(1-f_1) \cdot (1-f_2)) =~ 10.5\%\)
\(C_2 = $2.00\) \(((1-f_1) \cdot f_2) \div (1-(1-f_1) \cdot (1-f_2)) =~ 89.5\%\)
Bids that lost the auction

The following is an example of how values and probabilities for minimum_bid_to_win and sampled_mediation_cpm_ahead_of_auction_winner are calculated for a bids that lost.

minimum_bid_to_win Probability
\(max(F, W) = $1.00\) \(100\%\)
sampled_mediation_cpm_
ahead_of_auction_winner
Probability
\(C_1 = $3.00\) \(f_1 = 5\%\)
\(C_2 = $2.00\) \((1-f_1) \cdot f_2 =~ 42.8\%\)
\(0\) \((1-f_1) \cdot (1-f_2) =~ 52.2\%\)

Bid flattening

Bid flattening describes the processing of a single complex BidRequest into multiple bid requests that are sent to your application. When a bid request is flattened, you can tell which bid requests were part of the original because they will have an identical value in the BidRequest.ext.google_query_id field.

Bid flattening is enabled by default, but you can contact your account manager if you would prefer to disable it.

Ad formats

Some ad opportunities can accept multiple formats. With bid flattening, each format is sent in a distinct bid request where attributes such as eligible billing IDs are relevant to the format specified in the request.

Bid requests containing the following formats will be flattened into distinct bid requests:

  • Banner
  • Video
  • Audio
  • Native

Ad format flattening example

Below is an example showing a simplified OpenRTB JSON bid request without ad format flattening in comparison to an equivalent set of flatenned requests:

Pre-flatten

Post-flatten

Deals

An ad opportunity for a given bidder can be applicable to various deal types, in addition to the open auction. With bid flattening for deals, one bid request will be sent for the open auction, and one for each type of fixed-price deal. In practice, ad constraints can differ between auctions and fixed-price deal types, for example, for a given video ad opportunity that is available to both the open auction and a fixed-price deal, a bidder will receive distinct bid requests for each where constraints such as maximum ad duration and whether skippable ads are allowed can differ. As a result, flattening applied to the ad opportunity lets you more easily discern the ad constraints for the open auction and the fixed-price deal.

Max skippable video duration

Google's protocol and OpenRTB implementation support the following fields for video duration and skipability:

Duration Skippable duration Skipability
Google protocol max_ad_duration skippable_max_ad_duration video_ad_skippable
OpenRTB maxduration n/a skip

This means that while the Google protocol can have a granular skippable and non-skippable duration, the OpenRTB implementation only has a single maximum duration value.

Prior to bid flattening, OpenRTB's maxduration would be set to the lower of the Google protocol's max_ad_duration and skippable_max_ad_duration fields. This behavior has now changed to sending two separate bid requests when these values differ: one representing the maxduration for skippable and the other for non-skippable opportunities.

The following examples show how a Google protocol request translates to OpenRTB before and after bid flattening. The equivalent Google protocol request has a max_ad_duration of 15 and a skippable_max_ad_duration of 60.

Example max_ad_duration skip (true OR false)
Original request without flattening 15 true
Flattened request #1: Non-skippable 15 false
Flattened request #2: Skippable 60 true

Skippable video duration bid request flattening will only take place when these conditions are met:

  • The request allows video.
  • Both skip and no-skip videos are allowed, and the two respective max durations differ in value.
  • This request is Private Auction or Open Auction-eligible.
  • The bidder account has active OpenRTB endpoints.

You can opt out from this type of flattening by contacting your technical account manager.

Video pods

Bid requests for a video pod with multiple ad opportunities are flattened, such that each bid request is for an individual ad opportunity from that pod. This enables you to bid on multiple ad opportunities for a given pod.

Open Measurement

Open Measurement lets you specify third-party vendors that provide independent measurement and verification services for ads served to mobile app environments.

You can determine whether a publisher supports Open Measurement in the bid request by checking whether the ad opportunity excludes the OmsdkType: OMSDK 1.0 attribute found in Publisher-excludable creative attributes. This would be found under the battr attribute for Banner or Video, depending on the format.

For more information on how to interpret bid requests containing Open Measurement signals, refer to the Open Measurement SDK Help Center article.

Sample bid requests

The following sections show sample bid requests for different ad types.

App banner

OpenRTB Protobuf

OpenRTB JSON

Google (Deprecated)

App interstitial

OpenRTB Protobuf

OpenRTB JSON

Google (Deprecated)

App interstitial video

OpenRTB Protobuf

Google (Deprecated)

App native

OpenRTB Protobuf

OpenRTB JSON

Google (Deprecated)

Web video

Google (Deprecated)

Mobile web banner for exchange bidder

OpenRTB Protobuf