实时竞价
场景介绍
实时竞价是指用户在访问媒体产生曝光机会时,众多家DSP(Demand Side Platform,需求方平台)根据曝光的上下文以及用户属性实时地评估曝光价值并给出报价,出价最高的DSP胜出,赢得此次曝光机会。
约束与限制
支持Phone、Tablet、PC/2in1设备。
使用PC/2in1设备时,需要确保设备上智慧营销服务或广告服务的版本在8.4.80.300及以上,版本号可通过选择“设置> 应用和元服务 > 更多应用”查看。
支持场景
- 原生广告
- 激励广告
- 插屏广告
- 开屏广告
- 贴片广告
接口说明
| 接口名 | 描述 |
|---|---|
| loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void | 请求单广告位广告,通过AdRequestParams、AdOptions进行广告请求参数设置,通过AdLoadListener监听广告请求回调。 |
| loadAdWithMultiSlots(adParams: AdRequestParams[], adOptions: AdOptions, listener: MultiSlotsAdLoadListener): void | 请求多广告位广告,通过AdRequestParams[]、AdOptions进行广告请求参数设置,通过MultiSlotsAdLoadListener监听广告请求回调。 |
开发步骤
添加竞价参数
开发者需要在广告请求参数AdRequestParams中添加实时竞价相关参数。
实时竞价关键参数如下所示:
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| tMax | number | 否 | 交易的最大超时时间(包含网络延迟),单位ms。 |
| cur | string | 否 | 竞价请求支持的币种,支持传多个,用英文逗号分隔。当前支持五种货币: 1. CNY(单位:元)。 2. USD(单位:美元)。 3. EUR(单位:欧元)。 4. GBP(单位:英镑)。 5. JPY(单位:日元)。 不填默认是CNY。 |
| bidFloor | number | 否 | 竞价广告位的底价。当前支持五种货币: 1. CNY(单位:元)。 2. USD(单位:美元)。 3. EUR(单位:欧元)。 4. GBP(单位:英镑)。 5. JPY(单位:日元)。 不填默认是CNY。 |
| bidFloorCur | string | 否 | 竞价广告位底价使用的币种。如果bidFloor非空,则bidFloorCur也非空。当前只支持五种货币中的一种: 1. CNY(单位:元)。 2. USD(单位:美元)。 3. EUR(单位:欧元)。 4. GBP(单位:英镑)。 5. JPY(单位:日元)。 不填默认是CNY。 |
| bpkgName | string | 否 | 广告位竞投的APP包名,支持传多个,用英文逗号分隔。 |
示例代码如下所示:
import { advertising } from '@kit.AdsKit';
const adRequestParams: advertising.AdRequestParams = {
// 'h8asowxwhq'为测试专用的广告位ID,暂无竞价信息,App正式发布时需要改为正式的广告位ID
adId: 'h8asowxwhq',
// 广告类型
adType: 3,
// 交易的最大超时时间
tMax: 100,
// 竞价请求支持的币种,多个用英文逗号分隔
cur: 'CNY',
// 竞价广告位的底价
bidFloor: 6.66,
// 竞价广告位底价使用的币种
bidFloorCur: 'CNY',
// 广告位竞投的APP包名,多个用英文逗号分隔
bpkgName: 'com.huawei.baidu,com.huawei.music'
};
处理竞价结果
开发者需要在广告请求成功后的回调AdLoadListener.onAdLoadSuccess或MultiSlotsAdLoadListener.onAdLoadSuccess中,处理广告返回的实时竞价结果Advertisement.biddingInfo。
实时竞价结果信息如下所示:
回传竞价结果,需要申请使用Internet网络权限ohos.permission.INTERNET。详细申请权限流程请参考开发准备。
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| price | number | 是 | 本条广告的eCPM(Effective Cost Per Mille,每一千次展示可以获得的广告收入)。 |
| cur | string | 是 | 本条广告的价格币种。支持币种:CNY(单位:元)、USD(单位:美元)、EUR(单位:欧元)、GBP(单位:英镑)、JPY(单位:日元)。 |
| nurl | string | 是 | 媒体回传竞价成功结果的URL。 |
| lurl | string | 是 | 媒体回传竞价失败结果的URL。 |
-
若广告竞胜,开发者需要替换nurl中的宏,并回传竞胜结果。
宏说明如下:
宏 说明 SECOND_PRICE 竞胜时,其他DSP最高出价。样例:3.6。 AUCTION_CURRENCY 价格币种。支持币种:CNY(单位:元)、USD(单位:美元)、EUR(单位:欧元)、GBP(单位:英镑)、JPY(单位:日元)。 -
若广告竞败,开发者需要替换lurl中的宏,并回传竞败结果。
宏说明如下:
宏 说明 AUCTION_PRICE 竞败时,其他DSP最高出价。样例:3.6。 AUCTION_LOSS 竞价结果,如果没有走到参竞环节也需要回调,并替换具体过滤结果码。 枚举: 102:竞价失败。 103:底价过滤。 104:包名过滤。 105:其他原因过滤。 4005:超时未返回。 AUCTION_CURRENCY 价格币种。支持币种:CNY(单位:元)、USD(单位:美元)、EUR(单位:欧元)、GBP(单位:英镑)、JPY(单位:日元)。 AUCTION_APP_PKG 竞败时,竞胜DSP推广的App包名。 AUCTION_APP_NAME 竞败时,竞胜DSP推广的App名称。 AUCTION_CP_ID 竞败时,竞胜DSP的编号: 1:广点通 2:穿山甲 3:百青藤 4:快手联盟 5:爱奇艺 6:阿里 7:VIVO 8:OPPO 9:小米 10:京东 11:拼多多 100:其他
示例代码如下所示:
import { advertising } from '@kit.AdsKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { rcp } from '@kit.RemoteCommunicationKit';
interface BiddingInfo {
// 本条广告的eCPM(每一千次展示可以获得的广告收入)
price: number;
// 本条广告的价格币种
cur: string;
// 媒体回传竞价成功结果的URL
nurl: string;
// 媒体回传竞价失败结果的URL
lurl: string;
}
const adLoaderListener: advertising.AdLoadListener = {
// 广告请求失败回调
onAdLoadFailure: (errorCode: number, errorMsg: string) => {
hilog.error(0x0000, 'testTag', `Failed to load ad. Code is ${errorCode}, message is ${errorMsg}`);
},
// 广告请求成功回调
onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
hilog.info(0x0000, 'testTag', 'Succeeded in loading ad');
// 期望的底价
const bidFloor: number = 6;
const biddingSuccessAds: Array<advertising.Advertisement> = [];
for (const ad of ads) {
const biddingInfo: BiddingInfo = ad.biddingInfo as BiddingInfo;
if (!biddingInfo) {
continue;
}
if (biddingInfo.cur === 'CNY' && biddingInfo.price >= bidFloor) {
hilog.info(0x0000, 'testTag', 'Petal Ads wins.');
if (biddingInfo.nurl) {
const url: string = biddingInfo.nurl
// 竞胜时,其他DSP最高出价
.replace('SECOND_PRICE', '3.6')
// 价格币种
.replace('AUCTION_CURRENCY', 'CNY');
void sendBiddingResult(url).catch((error: BusinessError) => {
hilog.error(0x0000, 'testTag',
`Failed to sendBiddingResult. Code is ${error.code}, message is ${error.message}`);
});
}
biddingSuccessAds.push(ad);
} else {
hilog.info(0x0000, 'testTag', 'Petal Ads loses.');
if (biddingInfo.lurl) {
const url: string = biddingInfo.lurl
// 竞败时,其他DSP最高出价
.replace('AUCTION_PRICE', '3.6')
// 竞价结果
.replace('AUCTION_LOSS', '102')
// 价格币种
.replace('AUCTION_CURRENCY', 'CNY')
// 竞败时,竞胜DSP推广的App包名
.replace('AUCTION_APP_PKG', 'com.huawei.music')
// 竞败时,竞胜DSP推广的App名称
.replace('AUCTION_APP_NAME', 'music')
// 竞败时,竞胜DSP的编号
.replace('AUCTION_CP_ID', '100')
void sendBiddingResult(url).catch((error: BusinessError) => {
hilog.error(0x0000, 'testTag',
`Failed to sendBiddingResult. Code is ${error.code}, message is ${error.message}`);
});
}
}
}
// ...此处省略展示广告的逻辑
}
};
async function sendBiddingResult(url: string): Promise<void> {
let session: rcp.Session | undefined = undefined;
try {
session = rcp.createSession();
await session.get(url);
} catch (e) {
hilog.error(0x0000, 'testTag', `Failed to send bidding result. Code is ${e.code}, message is ${e.message}`);
} finally {
session?.close();
}
}