处理请求

当 Google 向您的应用发送出价请求时,实时出价互动便会开始。本指南介绍了如何对应用进行编码以处理出价请求。

解析请求

Google 会发送以 OpenRTB JSON 或 Protobuf 格式序列化的出价请求,并将其作为 HTTP POST 请求的载荷附加。收到的格式取决于端点的配置。如需查看示例,请参阅出价请求示例

您必须解析此请求才能接收序列化的 BidRequest。如果您使用的是 Protobuf 格式,则必须从参考数据页面下载 openrtb.protoopenrtb-adx.proto,并使用它们生成可用于解析 BidRequest 消息的库。例如,以下 C++ 代码会解析字符串中的 POST 载荷所给定的请求:

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

获得 BidRequest 后,您就可以将其作为对象进行处理,提取并解读所需的字段。例如,在 C++ 中,遍历 OpenRTB `BidRequest` 中的交易可能如下所示:

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

结算 ID

当发布商的广告资源被您的一项或多项 预定位配置定位时,您会收到出价请求。BidRequest.imp.ext.billing_id 将填充任何符合条件的买方的结算 ID 和相关预定位配置。此外,对于交易广告资源,您可以使用 BidRequest.imp.pmp.deal.ext.billing_id 查找与相关买方关联的结算 ID。出价时,只能指定出价请求中包含的买方的结算 ID。

如果出价请求中包含多个结算 ID,您必须使用 BidResponse.seatbid.bid.ext.billing_id 字段指定您打算将出价归因于的买方的结算 ID。

imp {
  ext {
    // The billing IDs of all of your matching pretargeting configs and eligible child seats are
    // stored in a flat list here.
    billing_id: 123
    billing_id: 456
    billing_id: 789
  }
  pmp {
    // All eligible deals are stored in a single flat list.
    deal {
      id: 1000
      ext {
        // The specific billing IDs eligible to bid on this deal are indicated here.
        billing_id: 789
      }
      ...
    }
    deal {
      id: 2000
      ext {
        billing_id: 123
        billing_id: 456
      }
      ...
    }
  }
  ...
}
...

确定已屏蔽的类别

您出价时,所含广告素材不得包含发布商屏蔽的检测到的类别。否则,相应出价会被滤除,无法参与竞价。

您可以查看 BidRequest.bcat 字段,该字段会填充为您的账号配置的分类目录中的类别,从而了解展示的屏蔽类别。

以下示例展示了基于配置的广告类别分类屏蔽的类别:

IAB 内容类目 1.0

// Bid request
{
  // Indicates the blocked categories using IAB Content 1.0 Taxonomy.
  "bcat": [
    "IAB9-9",  // Cigars
    "IAB8-18"  // Wine
  ]
  "imp": {
    ...
  }
}
      
// Bid request
{
  // Indicates the blocked categories using Google Ad Category Taxonomy.
  "bcat": [
    "10138",  // Cigar and tobacco collecting
    "10080",  // Tobacco
    "11649",  // Wine
    "10674",  // Wine collecting
    "13008"   // Wine clubs
  ]
  "imp": {
    ...
  }
}
      

字典文件

出价请求使用字典文件中定义的标识符,这些标识符可在参考数据页面上找到。

出价方网址宏

(可选)可以使用宏将 BidRequest 中的某些信息插入到出价端点网址中。如果您使用一个或多个宏配置了端点网址,那么如果出价请求中包含相应信息,这些宏就会展开。例如,如果您想根据 BidRequest 中的信息执行负载均衡,此功能会非常有用。请与您的客户经理联系,请求支持新宏。

说明
%%GOOGLE_USER_ID%%

已替换为 BidRequest.user.id 中找到的 Google 用户 ID。例如,出价方网址 http://google.bidder.com/path?gid=%%GOOGLE_USER_ID%% 将在请求时替换为类似 http://google.bidder.com/path?gid=dGhpyBhbiBleGFtGxl 的网址。

如果 Google 用户 ID 未知,则替换为空字符串,结果类似于

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

已替换为 1,以指示出价请求来自移动设备,否则为 0。这是根据 BidRequest.device.devicetype 的值确定的,其中移动设备由 HIGHEND_PHONE (4) 或 Tablet (5) 表示。

%%HAS_VIDEO%%

已替换为 1,用于指明出价请求包含视频广告资源;否则,替换为 0。这取决于出价请求中是否填充了 BidRequest.imp.video

%%HOSTED_MATCH_DATA%%

替换为基于 BidRequest.user.buyeruid 的值。

%%MOBILE_IS_APP%%

已替换为 1,用于指明出价请求是针对移动应用广告资源的,否则为 0。这取决于是否填充了 BidRequest.app

从交易网址中查找移动应用 ID

移动应用交易将报告如下所示的网址:

mbappgewtimrzgyytanjyg4888888.com

使用 base-32 解码器对粗体部分 (gewtimrzgyytanjyg4888888) 的字符串进行解码。

您可以使用在线解码器,但必须将字母大写,并将末尾的 8 替换为 = 值。

因此,解码此值:

GEWTIMRZGYYTANJYG4======
结果:
1-429610587
字符串 429610587 是 iOS 应用 iFunny 的应用 ID。

再看下面一个示例。被举报的网址是:

mbappgewtgmjug4ytmmrtgm888888.com
解码此值:
GEWTGMJUG4YTMMRTGM======
结果:
1-314716233
结果 314716233 是 iOS 应用 TextNow 的应用 ID。

从交易网址中查找移动应用名称

以下是获取应用名称的示例。报告的网址如下:

mbappMFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q888.com
解码此值:
MFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q===
结果:
air.com.hypah.io.slither
此结果相当于 Android 应用 slither.io

公开出价字段

发送给参与公开出价的广告交易平台和广告联盟出价方的出价请求与发送给参与标准实时出价的 Authorized Buyers 买方的出价请求类似。公开出价客户将收到少量额外的字段,并且一些现有字段可能会有其他用途。这些情况包括:

OpenRTB 详细信息
BidRequest.imp.ext.dfp_ad_unit_code

包含发布商的 Ad Manager 广告资源网代码,后跟广告单元层次结构,两者之间以正斜线分隔。

例如,此内容会以类似于以下格式显示:/1234/cruises/mars

BidRequest.user.data.segment

从发布商发送到广告交易平台出价方的重复键值对。

您可以确定,当 BidRequest.user.data.name 设置为 “Publisher Passed” 时,这些值是发布者发送的键值对。

声明允许的供应商

提供调研、再营销和广告投放等服务的技术供应商可能会在买卖双方的互动中发挥作用。只有经过 Google 审核的供应商才能参与 Authorized Buyers 互动。

如需了解 BidRequest 并创建 BidResponse,您需要了解声明技术供应商的两种不同方式:

  1. 部分供应商无需声明;这些供应商已列在经过 Ad Manager 认证的外部供应商中。
  2. 其他供应商只有在 BidRequest 中声明时才能参与:
    • BidRequest 中,BidRequest.imp.ext.allowed_vendor_type 字段用于指定卖家允许哪些供应商。将在 allowed_vendor_type 中发送的供应商列在 vendors.txt 字典文件中。

出价请求示例

以下示例以人类可读的格式展示了 Protobuf 和 JSON 请求。

OpenRTB Protobuf

OpenRTB JSON

如需将出价请求转换为二进制形式(就像从实际请求中的 POST 载荷获取的那样),您可以执行以下操作(在 C++ 中)。不过请注意,这不适用于 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
  }
}

实时反馈

Authorized Buyers 买方以及使用公开出价的广告交易平台和广告联盟可以获得实时反馈。

实时反馈会根据您之前出价的一次或多次竞价的结果填充 BidRequest.ext.bid_feedback,可用于查找详细信息,例如出价是否在竞价中胜出,或者胜出所需的最低出价。如需启用实时反馈,请与您的客户经理联系。

除了出价响应反馈中发送的默认字段外,您还可以使用 BidResponse.seatbid.bid.ext.event_notification_token 字段在出价响应中发送自定义数据。event_notification_token 是只有出价方知道的任意数据,可能有助于调试,例如:代表新策略的新定位 ID 或出价 ID,或者只有出价方知道的与广告素材相关联的元数据。如需了解详情,请参阅 OpenRTB 扩展协议缓冲区文件

当 Authorized Buyers 向出价方发送出价请求时,出价方会回复 BidResponse。如果出价方启用了实时反馈,那么在后续的出价请求中,Authorized Buyers 会在 BidFeedback 消息中发送有关响应的反馈:

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;

  // Deprecated. This field will be removed in February 2026.
  // 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 [deprecated = true];

  // 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;
  }

  // Deprecated. This field will be removed in February 2026.
  // 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 [deprecated = true];

  // Deprecated. This field will be removed in February 2026.
  // 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 [deprecated = true];

  // Deprecated. This field will be removed in February 2026.
  // 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 [deprecated = true];
}

从这条消息中,您应首先检查 bid_feedback.creative_status_code 字段;您可以在 creative-status-codes.txt 中找到相应代码的含义。请注意,如果您赢得竞价,可以选择停用价格反馈功能。如需了解详情,请参阅如何选择停用

实时反馈包括出价请求 ID 和以下信息之一:

竞价结果 实时反馈
买方未提交出价。 什么都不会发生。
买方提交的出价在到达竞价之前就被过滤掉了。 广告素材状态代码 (creative-status-codes.txt)。
买方提交了出价,但未赢得竞价。 广告素材状态代码 79(在竞价中出价过高)。
买方提交的出价赢得了竞价。 清仓价和广告素材状态代码 1

对于应用展示和 83 的广告素材状态代码,应用发布商可能使用了中介瀑布流,因此胜出的出价会与发布商回传瀑布流链中的其他需求竞争。了解如何在出价时使用 sampled_mediation_cpm_ahead_of_auction_winner

示例

以下是支持的协议中显示的实时反馈示例:

OpenRTB Protobuf

OpenRTB JSON

为最高出价竞价构建出价模型

在最高出价竞价中出价后,如果出价未被滤除,您将收到实时反馈,其中包括 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 字段。这些信号可用于指导您的出价逻辑,让您了解为了赢得展示机会,您的出价本可以提高或降低多少。

  • minimum_bid_to_win:在实时出价竞价中胜出所需的最低出价。如果您赢得了竞价,那么此值将是您在赢得竞价时可以设置的最低出价。如果您在竞价中失利,此值将为胜出价。
  • sampled_mediation_cpm_ahead_of_auction_winner:如果中介链中还有其他广告联盟,则此字段的值是一个价格,表示来自某个符合条件的中介广告联盟(高于胜出出价)的样本出价,并按预期填充率加权。如果中介链中的任何广告资源都不需要填充,或者发布商不使用 SDK 中介,则此值将设置为 0。

运作方式

为了描述用于确定 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 可能值的计算,我们首先需要定义以下内容:

  • 以下内容表示中介链中的 CPM(按降序排列):
    \[C_1, C_2, …, C_n\]
  • 以下数据表示中介链中相应 CPM 的填充率:
    \[f_1, f_2, …, f_n\]
  • 以下函数用于根据给定的填充率,从中介链元素 \(i\)确定预期 CPM 及其概率:
    \(X_i = \{C_i\) ,概率为 \(f_i\); \(0\) ,概率为 \(1 - f_i\}\)
  • 最终胜出的中介链将是:
    \[\{C_1, C_2, …, C_K, W\}\]
    其中, \(W\) 是胜出出价, \(C_K > W >= C_{K+1}\)
  • 底价或最低价格表示为 \(F\)。
  • 次高出价表示为 \(R\)。
竞价胜出者的计算
字段 计算
minimum_bid_to_win
\(max\{F, R, X_{K+1}, …, X_n\}\)
sampled_mediation_cpm_ahead_
of_auction_winner
\(\{C_i\) 概率为 \(\prod_{j=1}^{i-1}(1-f_j) \cdot f_i \div \prod_{j=1}^{K}(1-f_j)\}\)
适用于 \(1 <= i <= K\)。

竞价失败者的计算
字段 计算
minimum_bid_to_win
\(max\{F, W\}\)
sampled_mediation_cpm_ahead_
of_auction_winner
\(max\{X_1, …, X_K\}\)

包含简单中介链的示例

假设某发布商同时使用实时出价和 SDK 中介链,如下所示:

SDK 中介链 预期 CPM 填充率
网络 1 \(C_1 = $3.00\) \(f_1 = 5\%\)
广告联盟 2 \(C_2 = $2.00\) \(f_2 = 45\%\)
广告联盟 3 \(C_3 = $0.50\) \(f_3 = 80\%\)
网络 4 \(C_4 = $0.10\) \(f_4 = 85\%\)

假设实时出价竞价的结果如下:

RTB 竞价 每千次展示费用
竞价胜出者 (W) $1.00
竞价亚军 (R) $0.05
预订价格 / 底价 (F) $0
在竞价中胜出的出价

以下示例展示了如何针对赢得的竞价计算 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 的值和概率。

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\%\)
在竞价中未能胜出的出价

以下示例展示了如何针对未赢得的竞价计算 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 的值和概率。

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\%\)

出价拆分

出价扁平化是指将单个复杂的 BidRequest 处理为多个出价请求,然后将这些出价请求发送到您的应用。在出价请求被扁平化后,您可以通过 BidRequest.ext.google_query_id 字段中的相同值来判断哪些出价请求属于原始出价请求。

出价拆分功能默认处于启用状态,但如果您希望停用此功能,可以与您的客户经理联系。

广告格式

某些广告机会可以接受多种格式。通过出价拆分,每种格式都会通过单独的出价请求进行发送,其中符合条件的结算 ID 等属性与请求中指定的格式相关。

包含以下格式的出价请求将被拆分为不同的出价请求:

  • 横幅
  • 视频
  • 音频
  • 原生

广告格式扁平化示例

以下示例展示了一个简化的 OpenRTB JSON 出价请求(未进行广告格式扁平化处理),并将其与一组等效的扁平化请求进行了比较:

预展平

Post-flatten

特惠

对于给定的出价方,广告机会除了适用于公开竞价之外,还可适用于各种交易类型。启用按交易拆分出价功能后,系统会针对公开竞价发送一个出价请求,并针对每种固定价格交易发送一个出价请求。实际上,广告限制在不同竞价和固定价格交易类型之间可能有所不同。例如,对于同时面向公开竞价和固定价格交易的特定视频广告机会,出价方会收到不同的出价请求,其中广告时长上限和是否允许可跳过广告等限制可能会有所不同。因此,对广告机会应用扁平化处理后,您可以更轻松地辨别公开竞价和固定价格交易的广告限制。

可跳过性设置和视频时长

OpenRTB 规范没有单独的字段来指定可跳过式广告和不可跳过式广告的视频时长上限。Google 的实现方式使用出价平缓化,通过现有的 BidRequest.video.maxdurationBidRequest.video.skip 字段来区分这些情况。

以下示例展示了当不可跳过广告的时长上限为 15 且可跳过广告的时长上限为 60 时,视频广告资源是如何扁平化的。

示例 max_ad_duration skip(true 或 false)
未扁平化的原始请求 15 true
拆分后的请求 1:不可跳过 15 false
拆分的请求 #2:可跳过 60 true

只有在满足以下条件时,才会进行可跳过的视频时长出价请求拆分:

  • 该请求允许视频。
  • 允许投放可跳过视频广告和不可跳过视频广告,但这两个广告各自的时长上限不同。
  • 此请求符合私下竞价或公开竞价的条件。

您可以与技术支持客户经理联系,选择停用此类出价扁平化功能。如果停用此设置,并且发布商允许投放可跳过式视频广告和不可跳过式视频广告,但二者的时长上限不同,skip 将设置为 true,而 maxduration 将设置为可跳过式广告和不可跳过式广告时长限制中较短的时长。

视频广告连播

包含多个广告机会的视频广告连播的出价请求会被拆分,以便每个出价请求都对应于该连播中的单个广告机会。 这样一来,您就可以针对特定广告连播中的多个广告机会出价。

开放式衡量

借助 Open Measurement,您可以指定第三方供应商,以便为投放到移动应用环境中的广告提供独立的衡量和验证服务。

您可以通过检查广告机会是否排除了发布商可排除的广告素材属性中的 OmsdkType: OMSDK 1.0 属性,来确定发布商是否支持公开衡量。此属性位于横幅视频battr 属性下,具体取决于格式。

如需详细了解如何解读包含 Open Measurement 信号的出价请求,请参阅 Open Measurement SDK 帮助中心文章。

出价请求示例

以下部分展示了不同广告类型的出价请求示例。

应用横幅广告

OpenRTB Protobuf

OpenRTB JSON

应用插页式广告

OpenRTB Protobuf

OpenRTB JSON

应用插页式视频广告

OpenRTB Protobuf

OpenRTB JSON

应用原生

OpenRTB Protobuf

OpenRTB JSON

网络视频

OpenRTB Protobuf

OpenRTB JSON

面向交易平台出价方的移动网站横幅广告

OpenRTB Protobuf

OpenRTB JSON

多格式原生广告和视频广告

OpenRTB Protobuf

OpenRTB JSON