处理请求

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

解析请求

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

您必须解析此请求才能接收序列化的 BidRequest。如果您使用的是 Protobuf 格式,则必须从参考数据页面下载 openrtb.proto 和 openrtb-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.bcat 字段相同的分类。Google 或发布商可以提供这些内容相关类别。使用内容相关类别可能会提高展示评估、内容相关定位和品牌保障效果。

Google 检测到的内容相关类别

Google 会使用检测到的网站、应用或网页的 IAB 内容分类填充以下字段:

字段 说明
BidRequest.site.cat 描述网站的内容分类 ID 数组。
BidRequest.site.pagecat 一个内容分类 ID 数组,用于描述网站的当前网页或视图。
BidRequest.app.cat 描述应用的数组,其中包含内容分类 ID。
BidRequest.app.pagecat 内容分类 ID 数组,用于描述应用的当前页面或视图。

您可以在 BidRequest.site.cattax 或 BidRequest.app.cattax 字段中找到给定出价请求的这些字段所使用的确切类目。由于发布商偏好设置或监管方面的原因,上下文类别字段可能并不总是会填充。 如需了解详情,请参阅 Google Ad Manager 中的 OpenRTB 情境类别。

发布商提供的信号

除了 Google 检测到的情境类别之外,出价请求还可能包含发布商提供的信号,这些信号也会描述展示的情境。与 Google 检测到的内容相关类别不同,这些信号仅在发布商提供时才会填充。这些信号在 BidRequest.site.content 和 BidRequest.app.content 对象中发送,例如 content.data.segment 和 content.genre。用于 content.data.segment 条目的分类会报告在 content.data.ext.segtax 中。如需了解详情,请参阅适用于实时出价 (RTB) 的发布商提供的信号 (PPS)。

字典文件

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

出价方网址宏

或者,您也可以使用宏将 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。

%%IS_CTV%%

已替换为 1,用于指示出价请求是否来自 CTV 设备;否则,使用 0。这取决于 BidRequest.device.devicetype 的值。对于 Protobuf,CTV 设备为 CONNECTED_TV、CONNECTED_DEVICE 或 SET_TOP_BOX,这对应于 JSON 的整数值 3、6 或 7。

%%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 广告资源网代码,后跟广告单元层次结构,以正斜杠分隔。

例如,此 ID 的格式类似于:/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;

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

从这条消息中,您应先检查 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_win 和 sampled_mediation_cpm_ahead_of_auction_winner 字段。这些信号可用于指导您的出价逻辑,让您了解为了赢得展示机会,您的出价本可以高出或低出多少。

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

运作方式

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

  • 以下是中介链中的 CPM,按降序排列:
    \[C_1, C_2, …, C_n\]
  • 以下是中介链中每千次展示费用的相应填充率:
    \[f_1, f_2, …, f_n\]
  • 以下函数用于根据给定的填充率,从中介链元素 \(i\)确定预期每千次展示费用及其概率:
    \(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\%\)

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

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

以下示例展示了如何为胜出的出价计算 minimum_bid_to_win 和 sampled_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_win 和 sampled_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 出价请求(未进行广告格式扁平化处理),并将其与一组等效的扁平化请求进行了比较:

预展平

展平后

特惠

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

可跳过性和视频时长

OpenRTB 规范没有单独的字段来指定可跳过式广告和不可跳过式广告的视频时长上限。Google 的实现使用出价拆分,通过现有的 BidRequest.video.maxduration 和 BidRequest.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 属性,来确定发布商是否支持 Open Measurement。此信息位于横幅广告或视频广告的 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