Trusted Arbiter

在 React Native 应用中比较 CloudX 出价和受支持的第三方出价

Trusted Arbiter 会比较已加载的 CloudX 出价与受支持的第三方出价,并返回选中的平台。React Native 支持由 CloudX 原生 SDK 提供,支持 CloudX、Unity LevelPlay、PubMatic 和发布商传入的自定义出价输入。

使用各 SDK 已加载广告对象或广告信息对象来填充出价值:

import { CloudX, CloudXArbiterBid } from 'cloudx-react-native';

// cloudXAdInfo 是 CloudX 加载回调中的 CloudXAdInfo 对象。
// levelPlayAdInfo 是 Unity LevelPlay 广告信息对象。
// pubMaticPrice 和 pubMaticPartnerName 来自 PubMatic/OpenWrap 出价对象。
const result = await CloudX.arbiter({
    bids: [
        CloudXArbiterBid.cloudX(cloudXAdInfo),
        CloudXArbiterBid.levelPlay({
            networkName: levelPlayAdInfo.adNetwork,
            revenue: levelPlayAdInfo.revenue,
            precision: levelPlayAdInfo.precision,
        }),
        CloudXArbiterBid.pubMatic({
            price: pubMaticPrice,
            partnerName: pubMaticPartnerName,
        }),
    ],
});

console.log('Selected platform:', result.platform);

如果 arbiter 服务不可用,SDK 会在传入的受支持出价中回退选择可比较美元出价最高的平台。

AdMob 与 Google Ad Manager

CloudX 会将已加载的 CloudX 广告与已加载的 AdMob 或 Google Ad Manager 广告进行比较。AdMob 和 Ad Manager 是两个独立的需求来源,因此二者可以同时参与同一次仲裁。此方式适用于发布商自行管理的聚合配置,包括商业上称为 AdMob Pro 的账户;SDK 不提供单独的 AdMob Pro API。

Google 需求方通常不会在展示前透露已加载广告的价格,因此仲裁器无法获得可与 CloudX 出价比较的 pre-bid 价格。CloudX 会根据同类广告单元过往的表现估算出价,因此你无需自行提供价格。不需要任何 pre-bid 定价 API。

如果你的 AdMob 账户能够在 pre-bid 阶段提供展示级收益数据,也可以自行提供该精确价格来代替使用估算值——参见下方使用 pre-bid ILRD 手动输入价格

将 Google 付费事件回传给 CloudX(必需)

上报 Google 的展示级收入是 Trusted Arbiter 中 AdMob 与 Ad Manager 集成的必需环节,而不是可选的分析功能。当通过仲裁胜出的 AdMob 或 Ad Manager 广告展示之后,请把 Google 的付费事件(paid event)转发到 CloudX SDK。缺少这些事件,CloudX 就无法了解 Google 需求方的实际成交价格,其为后续仲裁提供的估算值也会逐渐变差。

请在你的 Google 付费事件回调中调用 CloudX.reportRevenueData()。收入值是货币单位,不是 micros——react-native-google-mobile-adsevent.value 已经是货币单位。

import { CloudX, CloudXRevenuePlatform, CloudXRevenuePrecision } from 'cloudx-react-native';

// event 是 Google 广告的 paid event(react-native-google-mobile-ads 的 onPaid)。
const reportGooglePaidEvent = (event, adFormat, adUnitId) =>
    CloudX.reportRevenueData({
        platform: CloudXRevenuePlatform.ADMOB, // Ad Manager 请使用 CloudXRevenuePlatform.GAM
        revenue: event.value,
        adFormat,
        currencyCode: event.currency,
        precision: CloudXRevenuePrecision.ESTIMATED,
        networkName: 'admob',
        adUnitId,
    });

请上报你传给仲裁出价的那个广告单元 ID,这样 CloudX 才能把实际成交价格归因到正确的广告单元。完整的字段说明与精度映射参见发布商上报收入数据

用你已加载广告的广告单元 ID 创建出价:

// networkName 为可选参数;如果你知道获胜的广告来源,请传入它。
const adMobBid = CloudXArbiterBid.adMob({
    adUnitId: adMobAdUnitId,
    networkName: adMobNetworkName ?? 'admob',
});

// Ad Manager 广告单元 ID 的格式为 /NNNNNNN/placement/name。
const adManagerBid = CloudXArbiterBid.gam({
    adUnitId: '/21775744923/example/interstitial',
});

const result = await CloudX.arbiter({
    bids: [CloudXArbiterBid.cloudX(cloudXAdInfo), adMobBid, adManagerBid],
});

if (result.platform === 'ADMOB') {
    // 展示 AdMob 广告
} else if (result.platform === 'GAM') {
    // 展示 Ad Manager 广告
}

获胜的 Google 出价会报告自己的平台——字符串 'ADMOB''GAM'。你不再需要像处理自定义出价那样,通过 result.platformName 来区分这两个来源。

传入空白的广告单元 ID,出价对象仍会正常构建,不会导致应用崩溃,但它不具备可用的身份信息:既不会被定价,也会被服务器拒绝。

使用 pre-bid ILRD 手动输入价格

部分 AdMob 账户可以在 pre-bid 阶段提供展示级收益数据(ILRD):已加载广告的广告价值在加载时即可获取,早于广告展示。这是一项受账户控制的历史能力,请与你的 Google 客户团队确认你的账户是否已启用。在展示之前就已知的精确单次展示价格,是自行提供价格优于 CloudX 估算值的唯一场景。

将 pre-bid 广告价值作为 manualRevenuePerImpressionUSD 传入,它会覆盖估算值:

const adMobBid = CloudXArbiterBid.adMob({
    adUnitId: adMobAdUnitId,
    manualRevenuePerImpressionUSD: preBidPricePerImpressionUSD,
});

你拿到的数值单位取决于底层的原生 SDK:Google Mobile Ads SDK 在 Android 上以微单位(micros)报告广告价值,在 iOS 上则以货币单位报告,因此请先换算为单次展示的美元金额再传入。

该数值的处理方式:

  • 0.0 是一个真实的价格。它表示该出价价值为零——而不是价格缺失。
  • 负值和非有限值不是有效价格,因此会被视为缺失并记录日志。
  • 空白的广告单元 ID 会导致手动价格被完全丢弃,因为没有身份信息的出价无法通过校验。

manualRevenuePerImpressionUSD 是单次展示的美元收益,而不是 CPM;非美元金额必须先换算为美元。AdMob 广告价值的各平台换算规则请参见 AndroidiOS 页面。

支持的广告格式

arbiter 与广告格式无关:它接受任何已加载的 CloudX 广告,且相同的字段映射适用于任意格式。Banner、MREC、插屏广告和激励视频广告均受支持。

自动刷新会与仲裁冲突:刷新可能会在 arbiter 已选出获胜方之后替换掉该广告。请在 CloudX 控制台中禁用自动刷新,并在 banner 或 MREC 广告上调用 stopAutoRefresh();同时也应禁用其他参与仲裁的广告网络的自动刷新。

CloudXBannerAd.stopAutoRefresh(adUnitId);
// CloudXMRECAd.stopAutoRefresh(adUnitId);

只通过 showAd(adUnitId) 展示获胜出价对应的广告;其余广告应通过 hideAd(adUnitId) 保持隐藏(或从不展示)。

推荐的刷新流程:获胜方展示后,仅从获胜的广告网络加载新的填充;保留已有填充的非获胜广告,只对未填充的网络重新发起请求;待响应返回后重新运行 arbiter。每 20-30 秒刷新一次展示中的广告——间隔过短会降低 CPM 表现。

自定义出价输入

当需要让 Trusted Arbiter 比较 CloudX 与没有专用出价工厂方法的第三方平台时,可以使用 CloudXArbiterBid.custom()

const customBid = CloudXArbiterBid.custom({
    platformName: 'my_mediation_platform',
    networkName: 'winning_demand_source',
    revenuePerImpressionUSD: 0.00125,
    precision: 'EXACT',
    extras: { ad_unit: 'third-party-ad-unit-id' },
});

const result = await CloudX.arbiter({
    bids: [CloudXArbiterBid.cloudX(cloudXAdInfo), customBid],
});

console.log('Selected platform:', result.platform);

当自定义出价胜出时,result.platform'CUSTOM'result.platformName 为出价中传入的 platformNamerevenuePerImpressionUSD 应传入单次展示的美元收益,而不是 CPM。请使用 'EXACT''ESTIMATED''PUBLISHER_DEFINED''UNDEFINED' 作为 precision 描述该收益值的精度。React Native 出价对象要求传入 networkName;如果价格来源没有提供获胜广告网络名称,请传入 ''。如果自定义出价缺少非空的 platformName、收益或精度,该出价会被丢弃并记录警告,不会参与竞争。