# 1. RTB接口

# 1.1. 通信方式

交易平台和DSP之间的基础通信协议采用HTTP协议,使用POST方法发送BidRequest消息。使用GET方法发送Win Notice消息。

# 1.2. HTTP请求头

Content-Type:application/x-protobuf

# 1.3. HTTP状态码

正常出价响应包的返回状态码为HTTP 200 OK,不出价的则为204 no content。其余情况均认为不正常。

# 1.4. 响应耗时

响应时间要求:

平均时长 < 最大120ms

# 1.5. 对DSP的要求

# 2. 竞价请求

# 2.1. Bid Request涉及的结构

支持两种类型的广告,分别为:框内广告和页面广告

框内广告包括:贴片、暂停、通用浮层、触点广告 video对象

页面广告包括:信息流、开机图、猜你喜欢、视频关联位、触点广告、焦点图、巨幕 banner对象

触点广告 出现位置:前贴、中贴、短视频频道后贴

# 2.2. BidRequest对象详细字段及含义

字段名 修饰符 数据类型 参数说明
id optional string 每次请求的唯一标识
user optional User Object 用户信息
site optional Site Object 站点频道信息
device optional Device Object 描述用户的设备信息
imp repeated Impression Object 广告位曝光Imp对象列表
source_id optional int32 渠道ID 0:爱奇艺
m_id optional string 合作方ID

# 2.3. Impression Object

字段名 修饰符 数据类型 参数说明
id optional string 广告返回时的Bid.impid应该对应此id(一次session中唯一),表示竞价此曝光机会
banner optional Banner Object 页面广告曝光机会相关信息
video optional Video Object 贴片广告曝光机会相关信息
floor_price repeated FloorPrice Object 不同行业设置不同底价。暂不下发
bidfloor optional int32 CPM底价,单位:分。当在floor_price找不到所需行业的底价的时候,就用bidfloor作为当前的流量的底价。此部分适用于通用浮层类、信息流、猜你喜欢广告投放类型。
campaign_id optional int32 交易ID, 暂无。
blocked_ad_tag optional int32 标签过滤,暂不下发。
blocked_ad_attribute repeated int32 属性过滤,暂不下发。
is_pmp optional bool 用于区分PDB和RTB流量,仅在PDB流量中有此字段,true为PDB流量,暂无。
extended_ads_position optional int32 是否支持5秒广告。0代表不支持,1代表支持正一,2代表支持倒一,3代表正一和倒一都支持。
impression_date optional int32 开机屏预计曝光时间,存在两种情况 1.请求中有该字段:开机屏为预加载请求,同时适用于移动端开机屏和部分OTT端开机屏;2.请求中无该字段:开机屏为实时请求,进适用于OTT端开机屏的部分请求。如:20211119
max_skippable_roll_ads optional int32 最多可投放的可跳过贴片数量 用于判断是否可以投放触点广告-RTB
skippable_roll_bidfloor optional int32 无参考行业时的Trueview广告的参考底价,单位:分
info_stream_max_bids_allowed optional int32 信息流广告单次请求可允许投放的最大广告数,当大于1时可返回多个广告。
width optional int32 广告位宽,爱奇艺渠道暂不支持下发
height optional int32 广告位高,爱奇艺渠道暂不支持下发

# 2.4. FloorPrice Object

字段名 修饰符 数据类型 参数说明
industry optional int64 行业
price optional int32 底价
skippable_roll_price optional int32 Trueview广告底价,非贴片曝光机会无此字段

bidfloor ,skippable_roll_bidfloor和 floor_price 组合的三种情况:

情况一,bidrequest中只传送了bidfloor和skippable_roll_bidfloor,此时bidfloor是无参考行业时普通贴片底价,skippable_roll_bidfloor是无参考行业时Trueview广告底价;

情况二,bidrequest中同时传送了包括了全部行业(共六个)的floor_price数组(包括price和skippable_roll_price),此时以显示出来不同行业的price和skippable_roll_price的数值为准;

情况三,bidrequest中只传送部分行业的floor_price数组、bidfloor和skippable_roll_bidfloor,此时已显示出来的行业以floor_price数组为准,没有显示的行业以bidfloor和skippable_roll_bidfloor为准。

举例如下:

floor_price {`

 `industry: 600000000`

 `price: 1000000`

 `skippable_roll_price: 1500000`

`}`

`bidfloor: 5000`

`skippable_roll_bidfloor: 10000

此时的含义代表600000000这个行业的普通贴片底价是1000000,Trueview广告底价为1500000,其他行业的普通贴片底价都是5000,Trueview广告底价都是10000。

# 2.5. Video Object

字段名 修饰符 数据类型 参数说明
ad_zone_id optional string 广告位id,ad_zone_id字典表见附录五
linearity optional int32 是否是串行在正片中的广告,1表示是,2不是
ad_type optional int32 广告类型,ad_type字典表见附录十一
minduration optional int32 广告最小时长
maxduration optional int32 广告最大时长
protocol optional int32 协议版本号
startdelay optional int32 本次广告自第几秒开始。
is_entire_roll optional bool 本次曝光机会是否为完整流量
video_startdelay optional int32 播放进度(单位:秒)

# 2.6. Banner Object

字段名 修饰符 数据类型 参数说明
ad_zone_id optional string 广告位id,ad_zone_id字典表见附录五
ad_type optional int32 广告类型,ad_type字典表见附录十一

# 2.7. User Object

字段名 修饰符 数据类型 参数说明
id optional string 用户ID,详细命名规则见附录一
is_privacy_protected optional bool 标识当前用户的隐私应被保护

# 2.8. Site Object

字段名 修饰符 数据类型 参数说明
id optional int32 站点ID
content optional Content Object 网站内容(也用作视频内容)

# 2.9. Content Object

字段名 修饰符 数据类型 参数说明
title optional string 标题
url optional string 网址
keyword repeated string 关键字
len optional int32 视频时长
album_id optional int64 剧目信息
channel_id optional int64 频道信息,channel_id字典表见附录十
tag repeated string 标签信息,通用浮层(创可贴)【即场景广告】专用识别字段
video_tag repeated int64 视频定向标签。
video_clip_id optional string 用户标识该次流量请求的点位。通用浮层(创可贴)【即场景广告】专用识别字段

# 2.10. Device Object

字段名 修饰符 数据类型 参数说明
ua optional string User agent,app流量不支持传输此字段
ip optional string 设备ip地址,使用广协ip库
geo optional Geo Object 地理信息
connection_type optional int32 网络接入字段,connection_type字典表见附录十二
platform_id optional int32 平台信息,platform_id字典表见附录八
android_id optional string Android设备的专用id信息,非必须发送字段
model optional string 型号,如“vivoX6”,“iPhone 15.1”
os optional string 操作系统,取值如下:iOS,Windows,Android,UWP
os_version optional string 操作系统版本号,如“5.1.1”
app_version optional string App版本,如7.9
ipv6 optional string 设备ipv6地址,使用广协ipv6库。
idfa optional string IOS设备idfa,默认不发送
openudid optional string IOS设备OpenUDID,默认不发送
imei optional string Android设备imei,MD5后值,默认不发送
mac optional string Mac地址,去掉“:”后MD5值
oaid optional string 安卓Q设备ID,取原值,未取到则此字段为空。
screen_width optional int32 设备的屏幕分辨率的宽度,单位是像素。
screen_height optional int32 设备的屏幕分辨率的高度,单位是像素。
manufacturer optional string 设备的制造厂商名称。如“huawei","xiaomi"。
carrier_name optional string 运营商名称,UTF8编码。如”中国移动“。目前该字段只IOS系统有值。
idfv optional string IOS设备idfv。目前该字段只IOS系统有值。
local_timezone optional string 设备本地时区。如”Asia/Shanghai“。目前该字段只IOS系统有值。
os_update_time optional int64 设备系统更新时间,单位微秒,从1970年1月1日起的时间戳。目前该字段只IOS系统有值。
startup_time optional int64 设备开机时间,单位微秒,从1970年1月1日起的时间戳。目前该字段只IOS系统有值。
cpu_num optional int32 设备CPU数目,获取错误为0。目前该字段只IOS系统有值。
disk_total optional int64 设备总磁盘总空间,单位字节。目前该字段只IOS系统有值。
mem_total optional int64 设备总内存空间,单位字节。目前该字段只IOS系统有值。
auth_status optional int32 设备⼴告标识授权情况。目前该字段只IOS系统有值。-1无法获取 0未弹出弹窗之前 1被限制 2拒绝 3授权

# 2.11. Geo Object

字段名 修饰符 数据类型 参数说明
country optional int32 国家信息,使用广协ip库表,最新广协地域编码表及IP类型地址库见文件夹中excel文件
metro optional int32 省份信息,使用广协ip库,最新更新时间:2019年12月份
city optional int32 城市信息,使用广协ip库,最新更新时间:2019年12月份
geohash optional string LBS地理位置信息,geohash加密后的数据,例经度116.396262,纬度39.885565,加密后wx4fbsv

# 3. 竞价返回

# 3.1. BidResponse对象详细字段及含义

字段名 修饰符 数据类型 参数说明
id required string response id,一般和request id相同,可以关联对应的请求,dsp必填
seatbid repeated Seatbid Object Seatbid对象列表,每个Seatbid里可包含若干Bid

注意事项:DSP需要根据bid request里impression信息返回相应的bid response。如不能返回超出impression时长的素材;不能返回类型不匹配的素材;不能返回离线素材等。

# 3.2 Seatbid Object

字段名 修饰符 数据类型 参数说明
Bid repeated Bid Object 和impression对应;

# 3.3. Bid Object

字段名 修饰符 数据类型 参数说明
id required string 竞拍者生成的竞价id,用于记录日志或者行为追踪
impid required string 与request中的imp.id对应,且保持一致,表示竞价该impression id的曝光机会
price required int32 出价价格,单位分/CPM
adm required Adm Object 物料数据,保存曝光、点击、跳转链接等
startdelay optional int32 指定广告的播放时间,贴片广告有效.当一个曝光机会的开始时间是X时,如果希望获得更多曝光机会,不要设置该字段
deeplink_url optional string (原生唤醒必填字段)用于指定deeplink url,采用原生唤醒形式时返回
universal_link_url optional string 用于指定universal link url,采用universal link唤醒形式时返回。只对IOS端有效
apk_ name optional string 走厂商应用商店下载时必填,用于走厂商应用商店下载时指定要下载的应用程序包名。
creative_content optional string 创意内容。
feed_back_info optional string 广告反馈信息。
download_from_store optional bool app是否走厂商应用商店下载。
mini_app_name optional string 微信小程序唤醒必填字段)微信小程序原始id
mini_app_path optional string (微信小程序唤醒必填字段)微信小程序页面路径
img_url optional string 素材图片地址
video_url optional string 素材视频地址 
width optional string 素材宽
height optional string 素材高

# 3.4 Adm Object

字段名 修饰符 数据类型 参数说明
native_title optional string 标题
native_desc optional string 描述
win_notice_url required string dsp侧广告曝光监测链接;建议DSP必填,其中可选添加价格宏,不支持https
ck_monitior_url required string dsp侧广告点击监测链接,建议DSP必填。
pmo repeated string 第三方曝光监测链接列表,最多3个,超出的监测不会收到请求
cmo repeated string 第三方点击监测链接列表,最多3个,超出的监测不会收到请求
duration optional int64 视频播放时长
click_throughs required ClickThroughs Object 落地页信息
icon optional string dsp LOGO要求:25*25像素尺寸的PNG格式文件,背景色透明、图片清晰、识别度高
tracking_events optional Events Object 广告跟踪信息
version optional string 协议版本号
adid required string dsp侧创意ID
dsp_info optional DspInfo Object dsp名称

# 3.5. ClickThroughs Object

字段名 修饰符 数据类型 参数说明
click_type required string 广告点击类型 0:默认类型,4:app下载,11:app直接下载不会弹出 14:原生唤醒15:universalLink 67:小程序
url required string 送审模式下跳转地址使用送审时填充的click_url字段的值,不使用实时返回的跳转地址

A:Android端下载类广告(click type 4、11、15),采取“按钮点击”方式;

B:Android端非下载类广告(click type 0)及IOS所有广告,采用“按钮+全屏点击”方式;

# 3.6. Events Object

字段名 修饰符 数据类型 参数说明
event optional Enum TrackingEvent见下方说明
percent optional double 播放进度,例如:0.25,0.5,0.75,1分别代表播放25%,50%,75%,100%。
tracking_url optional string 事件监控URL
enum TrackingEvent {
    firstQuartile = 0;   // "播放25%"   只对贴片有效
    midpoint = 1; // "播放50%"  				只对贴片有效
    thirdQuartile = 2;  // "播放75% "   只对贴片有效
    complete = 3;  // "播放100%结束"     只对贴片有效
    downloadStart = 4;  // 下载开始
    downloaded = 5;  // 下载结束
    installed = 6;  // 安装
}

# 3.7. DspInfo Object

字段名 修饰符 数据类型 参数说明
version optional string dsp api version
name optional string dsp name

# 4. 数据监测

麦晗方目前对竞价成功的DSP由服务端触发发送win notice url,为了节省空间,dsp可以只对监测参数敏感数据进行base64加密。

参数 描述
price ${SETTLEMENT} 最终成交价格,对象类型,单位分cpc竞价表示分/每次点击cpm竞价表示分/每千次曝光
message Settlement { 
		// Algorithm for price and auth. 
		optional uint32 version = 1; 
		// Encrypted price. 
		required bytes price = 2; 
		// Authentication information for bidid and price. 
		optional bytes auth = 3; 
}

# 4.1. 成交价加密方法

1:每个DSP有一个唯一的解密密钥, 密钥是长度为32个字符的字符串.

2:加密算法 aes 256位的ecb模式,padding方式为 PKCS5。

3:需要明确加解密是针对price进行的

4:返回url参数中必须携带 ${SETTLEMENT} 宏

5:竞价成功后${SETTLEMENT} 宏 会被(settlement 的结构体 经过proto序列化,再经过base64编码后的字符串替换)

需要注意的是我们使用的base64 编码字典是自己定制的 和常用的不一致,字典表如下 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_- (填充字符是!,不是=)

# 4.2 解密举例

价格明文:"123456.78"

key: "aab087fcbbff83e231562c73fa3ec789"

经过base64编码过得settlement : "EhAdwiU_BJLKOs8QUtAQWrex"

解码出来message中的price是:1dc2253e0492ca3acf1052d0105ab7b1 (hex string 后)

此值再经过解密可得到 价格明文:"123456.78"

注: 上面的key为测试用例,为了统一规范,token可同时用于上传和价格解密,测试和正式价格解密token不一样,联调或投放时请联系产品提供。

解密函数示例(go语言)

func Decrypt(cipher, ekey, ikey []byte, args ...interface{}) (float64, error) {
    debase, err := b64Decode(string(cipher), '!')
    if err != nil {
      return 0, err
    }

    settlement := &qax.Settlement{}
    err = proto.Unmarshal(debase, settlement)
    if err != nil {
      return 0, err
    }

    price, err := aesECBModeDecrypt(settlement.Price, ekey)
    if err != nil {
      return 0, err
    }
    length := len(price)
    pad := int(price[length-1])
    oprice := price[:(length - pad)]
    return strconv.ParseFloat(string(oprice), 64)
}
func b64Decode(s string, pad rune) ([]byte, error) {
    base64str := strings.Map(func(r rune) rune {
      switch r {
      case '-':
        return '/'
      case '_':
        return '+'
      case pad:
        return '='
      }
      return r
    }, s)
    return base64.StdEncoding.DecodeString(base64str)
}

func aesECBModeDecrypt(cipher, ekey []byte) ([]byte, error) {
	if len(cipher)%aes.BlockSize != 0 {
		return nil, errInvalidCipherLen
	}
	//decode block by block
	b, err := aes.NewCipher(ekey)
	if err != nil {
		return nil, err
	}
	var plain []byte
	for len(cipher) > 0 {
		text := make([]byte, aes.BlockSize)
		b.Decrypt(text, cipher)
		cipher = cipher[aes.BlockSize:]
		plain = append(plain, text...)
	}
	return plain, nil
}

解密示例(java) 报错参考: https://blog.csdn.net/dafeige8/article/details/76019911

package utils;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import myhayo.Myhayo;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;


public class price {


    public static String decryptBytes3(byte[] encrypted, byte[] key) {
        try {
            // 判断Key是否正确
            if (key == null) {
                return null;
            }
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            try {
                byte[] original = cipher.doFinal(encrypted);
                return new String(original, "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } catch (Exception ex) {
            return null;
        }
    }


    public static void main(String[] args) throws InvalidProtocolBufferException, UnsupportedEncodingException {

        String priceEncode="EhAdwiU_BJLKOs8QUtAQWrex";
        String demoToken = "aab087fcbbff83e231562c73fa3ec789";
        byte[] priceDecodeBase64 = MyBase64.decodeBase64(priceEncode.getBytes("UTF-8"));
        Myhayo.Settlement settlement = Myhayo.Settlement.parseFrom(priceDecodeBase64);
        ByteString encodedPrice = settlement.getPrice();
        String price = AESUtil.decryptBytes3(encodedPrice.toByteArray(), demoToken.getBytes());
        System.out.println("price:" + price);

    }

}

# 5. 样例

贴片位置的请求和返回样例

# 5.1. 请求数据样例

{
	"id": "08b89281c1e421fd1c87964c4d97a58b",
	"user": {
		"id": "f3aeb7621afc4872"
	},
	"site": {
		"id": 1,
		"content": {
			"url": "www.pps.tv",
			"channel_id": 1
		}
	},
	"device": {
		"ua": "Cupid/5.45.003;NetType/wifi",
		"ip": "171.121.60.175",
		"geo": {
			"country": 86,
			"metro": 8614,
			"city": 861411,
			"geohash": "7zzzzzz"
		},
		"connection_type": 2,
		"platform_id": 33,
		"android_id": "f3aeb7621afc4872",
		"model": "Dalvik/2.1.0 (Linux; U; Android 11; V2066A Build/RP1A.200720.012)",
		"os": "android",
		"os_version": "11",
		"mac": "e639e9de0757a6eec668c6274cbdbbd8",
		"oaid": "377aa22dac3b470e0eb3950f898d0765728a091a04f1e54c3aacdd1c4e22f640"
	},
	"imp": [{
		"id": "1b",
		"video": {
			"ad_zone_id": 30002,
			"linearity": 1,
			"ad_type": 1,
			"minduration": 15,
			"maxduration": 60,
			"protocol": 3,
			"startdelay": 0,
			"is_entire_roll": true
		},
		"bidfloor": 400,
		"blocked_ad_attribute": [12, 101],
		"extended_ads_position": 0,
		"max_skippable_roll_ads": 3,
		"skippable_roll_bidfloor": 100
	}]
}

# 5.2. 返回数据样例

{
	"id": "08b89281c1e421fd1c87964c4d97a58b",
	"seatbid": [{
		"bid": [{
			"id": "1b",
			"impid": "1b",
			"price": 640,
			"adm": {
				"native_title": "",
				"native_desc": "",
				"win_notice_url": "http://tyaqy.m.cn.miaozhen.com/x/k=2252923\u0026p=7viJ9\u0026dx=__IPDX__\u0026rt=2\u0026pro=s\u0026ns=__IP__\u0026ni=__IESID__\u0026v=__LOC__\u0026xa=__ADPLATFORM__\u0026tr=__REQUESTID__\u0026vg=__AUTOPLAY__\u0026nh=__AUTOREFRESH__\u0026mo=__OS__\u0026m0=__OPENUDID__\u0026m0a=__DUID__\u0026m1=__ANDROIDID1__\u0026m1a=__ANDROIDID__\u0026m2=__IMEI__\u0026m4=__AAID__\u0026m5=__IDFA__\u0026m6=__MAC1__\u0026m6a=__MAC__\u0026m11=__OAID__\u0026m14=__CAID__\u0026m5a=__IDFV__\u0026mn=__ANAME__\u0026o=",
				"ck_monitior_url": "http://cktest.optaim.com/c?info=CmsKLTA4Yjg5MjgxYzFlNDIxZmQxYzg3OTY0YzRkOTdhNThiXzFiXzIzNTg0MjkyNRINMTAwMDAwMDAwMDM4MRjyqwgglYHmASjAsGgwsGdAgApI0AVQAljHCWCAgPqIBmjExYSJBnDEov-IBhIDcWF4GI2j04wGIhgIARCgBhj0AygBMAE4oAZ5AAAAAAAAiUAqQAgDEiAxODk2MzFiNTE1YTZlZWY3YjIwMjVmNzgwYWMyZGVlNhgIIgdhbmRyb2lkKgE5OgZQREJNMDBAAVAFWAIwYzoZZGV2X2Rldk1hY2hpbmUuZG9tYWluLmNvbUABShRodHRwOi8vd3d3LmlxaXlpLmNvbVAAYABpAAAAAAAA8D9wmvswggEBMYoBATCiAQczYjIxMDkzwgEAyAEC0gERCAEVAACAPx0AAAAAJQAAAADaAQDiAQoxMTU2NDIwNTAw6AEE-gEAlQIAAIA_ogIBMbICAOICAA%3D%3D\u0026isPb=1",
				"pmo": ["http://tyaqy.m.cn.miaozhen.com/x/k=2252657\u0026p=7vX8P\u0026dx=__IPDX__\u0026rt=2\u0026pro=s\u0026ns=__IP__\u0026ni=__IESID__\u0026v=__LOC__\u0026xa=__ADPLATFORM__\u0026tr=__REQUESTID__\u0026vg=__AUTOPLAY__\u0026nh=__AUTOREFRESH__\u0026mo=__OS__\u0026m0=__OPENUDID__\u0026m0a=__DUID__\u0026m1=__ANDROIDID1__\u0026m1a=__ANDROIDID__\u0026m2=__IMEI__\u0026m4=__AAID__\u0026m5=__IDFA__\u0026m6=__MAC1__\u0026m6a=__MAC__\u0026m11=__OAID__\u0026m14=__CAID__\u0026m5a=__IDFV__\u0026mn=__ANAME__\u0026o=", "http://tyaqy.m.cn.miaozhen.com/x/k=2252923\u0026p=7viJ9\u0026dx=__IPDX__\u0026rt=2\u0026pro=s\u0026ns=__IP__\u0026ni=__IESID__\u0026v=__LOC__\u0026xa=__ADPLATFORM__\u0026tr=__REQUESTID__\u0026vg=__AUTOPLAY__\u0026nh=__AUTOREFRESH__\u0026mo=__OS__\u0026m0=__OPENUDID__\u0026m0a=__DUID__\u0026m1=__ANDROIDID1__\u0026m1a=__ANDROIDID__\u0026m2=__IMEI__\u0026m4=__AAID__\u0026m5=__IDFA__\u0026m6=__MAC1__\u0026m6a=__MAC__\u0026m11=__OAID__\u0026m14=__CAID__\u0026m5a=__IDFV__\u0026mn=__ANAME__\u0026o="],
				"duration": 30,
				"click_throughs": {
					"click_type": "0",
					"url": "http://tyaqy.m.cn.miaozhen.com/r/k=2252657\u0026p=7vX8P\u0026dx=__IPDX__\u0026rt=2\u0026pro=s\u0026ns=__IP__\u0026ni=__IESID__\u0026v=__LOC__\u0026xa=__ADPLATFORM__\u0026tr=__REQUESTID__\u0026mo=__OS__\u0026m0=__OPENUDID__\u0026m0a=__DUID__\u0026m1=__ANDROIDID1__\u0026m1a=__ANDROIDID__\u0026m2=__IMEI__\u0026m4=__AAID__\u0026m5=__IDFA__\u0026m6=__MAC1__\u0026m6a=__MAC__\u0026m11=__OAID__\u0026m14=__CAID__\u0026m5a=__IDFV__\u0026mn=__ANAME__\u0026o=https://tyaqy.m.cn.miaozhen.com/r/k=2252923\u0026p=7viJ9\u0026dx=__IPDX__\u0026rt=2\u0026pro=s\u0026ns=__IP__\u0026ni=__IESID__\u0026v=__LOC__\u0026xa=__ADPLATFORM__\u0026tr=__REQUESTID__\u0026mo=__OS__\u0026m0=__OPENUDID__\u0026m0a=__DUID__\u0026m1=__ANDROIDID1__\u0026m1a=__ANDROIDID__\u0026m2=__IMEI__\u0026m4=__AAID__\u0026m5=__IDFA__\u0026m6=__MAC1__\u0026m6a=__MAC__\u0026m11=__OAID__\u0026m14=__CAID__\u0026m5a=__IDFV__\u0026mn=__ANAME__\u0026o=https://www.dyk.com.cn/vehicles/sportage-ace/?utm_source=1570059\u0026utm_content=patch-30"
				},
				"adid": "136690"
			},
			"startdelay": 0,
			"download_from_store": false
		}]
	}]
}

# 6. proto内容

syntax = "proto2";

package myhayo;

message FloorPrice {
    optional int64 industry = 1;
    optional int32 price = 2;
    optional int32 skippable_roll_price = 3;
}

message UserFeature {
    optional string key = 1;
    optional string value = 2;
}

message UserSession {
    repeated uint64 delivered_creative_numeralization_value = 2;
}

message Banner {
    // 广告位ID
    optional int64 ad_zone_id = 4;
    // 广告类型
    optional int32 ad_type = 12;

    repeated int64 creative_template = 13;
    extensions 100 to max;
}

message Video {
    optional int64 ad_zone_id = 1;
    optional int32 linearity = 3;

    optional int32 ad_type = 13;

    optional int32 minduration = 4;

    optional int32 maxduration = 5;

    optional int32 protocol = 6;

    optional int32 startdelay = 9;

    optional bool is_entire_roll = 14 [default = false];

    optional int32 video_startdelay = 15;
}

message Impression {
    optional string id = 1;

    optional Banner banner = 2;
    optional Video video = 3;

    repeated FloorPrice floor_price = 9;
    optional int32 bidfloor = 4 [default = 0];

    optional int32 campaign_id = 5;

    repeated int32 blocked_ad_tag = 6;

    repeated int32 blocked_ad_attribute = 7;

    optional bool is_pmp = 8 [default = false];

    optional int32 extended_ads_position = 10 [default = 0];

    optional int32 impression_date = 11;

    optional int32 max_skippable_roll_ads = 12;

    optional int32 skippable_roll_bidfloor = 13;

    optional int32 info_stream_max_bids_allowed = 15;

    optional int32 width = 16;
    optional int32 height = 17;
    extensions 100 to max;
}

message Site {
    optional int32 id = 1;
    optional string app_bundle_id = 2;
    optional Content content = 11;
}

message Content {
    optional string title = 3;

    optional string url = 6;

    repeated string keyword = 9;

    optional int32 len = 16;

    optional int64 album_id = 20;

    optional int64 channel_id = 22;

    repeated string region = 23;

    repeated string category = 24;

    optional string release_date = 25;

    repeated string starring = 26;

    repeated string video_quality = 27;

    repeated string tag = 28;

    repeated int64 video_tag = 29;

    optional string video_clip_id = 31;
}

message Device {
    optional string ua = 2;

    optional string ip = 3;

    optional Geo geo = 4;

    optional int32 connection_type = 15;

    optional int32 platform_id = 18;

    repeated int64 feature = 19;

    optional string android_id = 20;

    optional string model = 21;

    optional string os = 22;

    optional string os_version = 23;

    optional string app_version = 24;

    optional string ipv6 = 25;

    optional string idfa = 26;

    optional string openudid = 27;

    optional string imei = 28;

    optional string mac = 29;

    optional string oaid = 30;

    optional int32 screen_height = 32;
    optional int32 screen_width = 33;

    repeated int64 installed_app = 34;

    optional string manufacturer = 35;

    optional string carrier_name = 36;

    optional string idfv = 37;

    optional string local_timezone = 38;

    optional int64 os_update_time = 39;

    optional int64 startup_time = 40;

    optional int32 cpu_num = 41;

    optional int64 disk_total = 42;

    optional int64 mem_total = 43;

    // -1 Not Supported
    // 0 Not Determined
    // 1 Restricted
    // 2 Denied
    // 3 Authorized
    optional int32 auth_status = 44;
}

message Geo {
    optional int32 country = 3;
    optional int32 metro = 5;
    optional int32 city = 6;
    optional double longitude = 7;
    optional double latitude = 8;
    optional string geohash = 9;
}

message ViewingHistory {
  optional string video_title = 1;
  repeated string video_tag = 2;
  repeated int64 multi_publish_channel_ids = 3;
}

message User {
    // The unique identifier of this user on the exchange.
    // For IOS, this is IDFA, UDID or MAC address.
    // For Android, this is IMEI, AndroidID or MAC address.
    optional string id = 1;

    //This field will be set true if the privacy of the current user should be protected.
    optional bool is_privacy_protected = 2 [default = false];

    repeated int32 dmp_id = 4;

    // Each UserFeature contains key and value fields.
    // For example,
    // UserFeature {
    //   key: "f1",
    //   value: "10"
    // }
    repeated UserFeature feature = 5;

    optional UserSession session = 6;

    // This field indicates viewing histories of the user ordered by date.
    repeated ViewingHistory viewing_history = 7;

    repeated string interest_tag = 8;
}

message BidRequest {
    // Note, the value of this field is not unique.
    optional string id = 1;

    optional User user = 2;
    optional Site site = 3;
    optional Device device = 5;

    // The list of impression objects. Multiple impression auctions may be
    // specified in a single bid request. At least one impression is required
    // for a valid bid request.
    repeated Impression imp = 8;

    optional bool is_test = 9 [default = false];

    optional bool is_ping = 10 [default = false];
    optional int32 source_id = 11;
    optional string m_id = 12;
    extensions 100 to max;
}

message Settlement {
    optional uint32 version = 1;
    required bytes price = 2;
    optional bytes auth = 3;
}

message Bid {
    required string id = 1;

    required string impid = 2;

    required int32 price = 3;

    required Adm adm = 4;

    optional int32 startdelay = 5;

    optional string deeplink_url = 6;
    optional string apk_name = 7;

    optional string creative_content = 8;

    optional string universal_link_url = 9;

    optional string feed_back_info = 10;

    optional bool download_from_store = 11;
    // gender and so on, this field should be set to true.
    optional bool is_precision_advertising = 12 [default = false];
    optional string mini_app_name = 13;     // 微信小程序唤醒必填字段)微信小程序原始id,参数值需要进行URL encode
    optional string mini_app_path = 14;     // (微信小程序唤醒必填字段)微信小程序页面路径,参数值需要进行URL encode
    optional string img_url = 15; // sourceid=1时必填 贴片选填
    optional string video_url = 16;  // sourceid=1时必填 贴片必填
    optional string width = 17;  // sourceid=1时必填
    optional string height = 18;  // sourceid=1时必填
    extensions 100 to max;
}

message Adm {
    // The list of adm objects. describing the advertisement of this bid.
    optional string native_title = 1;   // 广告标题
    optional string native_desc = 2;    // 广告描述
    required string win_notice_url = 3;     // 竞价胜出反馈的url,其中可选添加宏${SETTLEMENT},会替换为结算价格(解密方式见“曝光监测接口与解密方式”,不支持https), 也可以当作曝光监测来计数,但与im_monitior_url不能重复曝光计数。
    required string ck_monitior_url = 4;    // dsp侧 点击监测
    repeated string pmo = 5;        // 第三方曝光监测
    repeated string cmo = 6;        // 第三方点击监测
    optional int64  duration = 7;   // 视频播放时长 单位:秒
    optional ClickThroughs click_throughs = 8;  // 落地页
    optional string icon = 9;       // dsp logo图
    repeated Events tracking_events = 10; // 追踪事件
    optional string version = 11; // 协议版本号
    required string adid = 12; // dsp侧创意ID
    optional DspInfo dsp_info= 13; // dsp名称
    repeated string win_notice_list = 14;    // dsp侧 曝光监测
}

message DspInfo {
    optional string version = 1;    //
    optional string name = 2;   // dsp name
}
message Events {
    // 落地页类型
    enum TrackingEvent {
        firstQuartile = 0;   // "播放25%"  只对贴片有效
        midpoint = 1; // "播放50%"  只对贴片有效
        thirdQuartile = 2;  // "播放75% "   只对贴片有效
        complete = 3;  // "播放100%结束"   只对贴片有效
        downloadStart = 4;  // 下载开始
        downloaded = 5;  // 下载结束
        installed = 6;  // 安装
    }
    optional TrackingEvent event = 1;
    optional double percent = 2;
    optional string tracking_url = 3;
}

message ClickThroughs {
    // 落地页类型
    optional string click_type = 1;         //  67:小程序  88:广点通下载
    optional string url = 2;    // 落地页
}

message Seatbid {
    // The list of bid objects. Each bid object should be related to an impression
    // object in the bid request.
    repeated Bid bid = 1;
}

message BidResponse {
    // This id should be the same as the id of the corresponding BidRequest.
    required string id = 1;

    // The list of seatbid objects.
    repeated Seatbid seatbid = 2;

    extensions 100 to max;
}

# 附录一:【user id】命名规则

平台 取值规则
PC网页端/PC客户端/IphoneH5/IpadH5/ Android手机H5 cookie
Iphone/Ipad客户端 idfa/openudid/ mac_address
Android手机端/Android平板客户端/ 智能音箱 Imei/android id/ mac_address
电视(android端) mac_address
UWP Phone/ UWP Pad/ UWP Xbox Advertising Id/Guid/ASHWID

# 附录二: 【设备ID】取值顺序

平台 取值规则 名词解释 备注
iOS 优先使用 IDFA 如果 IDFA 不可用,使用IDFV,如果IDFV不可用,使用openUDID 如果 openUDID 不可用,使用 MAC 地址 IDFA: 广告标识符 ,128位(16个字节), 示例: 1E2DFA89-496A-47FD-9941-DF1FC4E6484A OpenUDID: 由40个字母和数字的组合组成,示例: 0d943976b24c85900c764dd9f75ce054dc5986ff Mac Address: MAC地址共48位( 6个字节),ios7 以后禁用, ios7及以后的版本调用接口返回的都是02:00:00:00:00:00 IDFA 使用原始值 openUDID使用原始值 MAC 地址格式:去分隔符,转大写,然后 MD5
Android 优先使用 IMEI 如果 IMEI 不可用,使用AndroidID 如果 AndroidID 不可用,使用 MAC 地址 IMEI: 15位纯数字,示例: 357071052902590, 注意:获取此值时需要动态检查一下权限, 部分手机返回的不是15位数字,例如某些小米手机上返回的是14位数字, GSM和WCDMA制式手机会使用此id MEID: 14个十六进制字符标识表示,例如:A000005EE4634D, CDMA制式手机会使用此id ESN: 不同设备不一样,示例:47QDU16C11000573, CDMA制式手机可能会使用此id,部分pad上没有IMEI和MEID时会使用此id Android Id: ANDROID_ID是Android系统第一次启动时产生的一个64bit数,示例: 63cfb1479595ab56, 注意:获取此值时需要动态检查一下权限 Mac Address: MAC地址共48位(6个字节),十六进制,示例: 34:23:BA:96:D3:E9, 注意:Android 6.0 以后返回的都 是02:00:00:00:00:00 其中,标准的15位和非标准的14位IMEI(不包含MEID、ESN)都会切换成MD5 后的值,小写。如果是其他位数的IMEI则会传原始值;MEID传原始值 IMEI 值有三种形式:IMEI、MEID、ESN,其中 GSM 和WCDMA制式手机会返回IMEI,CDMA 制式手机会返回 MEID或ESN,具体取值格式见左侧“名词解释” AndroidID使用原始值 MAC 地址格式:去分隔符,转大写,然后 MD5
UWP 优先使用 Advertising Id 如果 Advertising Id不可用,使用Guid 如果 Guid 不可用,使用 ASHWID 地址 Advertising Id: 广告标识符,每设备唯一用户可以关闭、重置此ID,由字母和数字组成,示例:898af4c74d13338a8bdca5b9c9c5968a;用户关闭时,返回空字符串 Guid: 本地设备的标识符(16个字节),每一设备每一应用唯一,示例:1042e226-be06-828e-bbf5-240823d40d49; ASHWID: 硬件Id,每一设备每一应用唯一,此ID字符长度不固定,示例:05-00-DB-48-06-00-01-00-04-00-69-25-01-00-24-12-02-00-7E-7B-09-00-FE-92

# 附录三:第三方监测说明补充信息

  1. 移动客户端回传设备 id 取值规则: 同附录一1.2

  2. 默认使用API上报

  3. 移动客户端操作系统标志值

    • 0表示Android

    • 1表示iOS

    • 2表示Windows

    • 3表示其他

  4. MMA API 监测宏替换定义:

  • __OS__:操作系统,替换值见附录3
  • __IMEI__:MD5 加密
  • __MAC__:去分隔符“:”,转大写,然后 MD5 加密
  • __MAC1__:保留分隔符“:”,转大写,然后 MD5 加密
  • __IDFA__:取原值
  • __OPENUDID__:取原值
  • __ANDROIDID__:MD5 加密
  • __IP__:取原值
  • __TS__:UTC 时间戳,自1970年起的毫秒数
  • _OAID_: Android Q及更高版本的设备号,取原值

# 附录四:TrackingEvents(监测事件)节点使用规则:

  1. 支持 firstQuartile(四分之一)、midpoint(二分之一)、thirdQuartile(四分之三)、complete(完成)、close(关闭或跳过广告) 这5个监测事件,只对贴片广告有效

  2. 每个事件支持多个 Tracking 节点,比如:若需要对 firstQuartile 事件添加多条监测 URL,可以通过添加多个 event="firstQuartile" 的 Tracking 节点实现,条数没有上限,请按照需要添加相应的监测事件节点,比如:若只需要监测 firstQuartile事件,则只添加 event=" firstQuartile " 的 Tracking 节点即可

  3. 相应事件的监测 URL 请填写到 tracking_url 里

  4. 在Android平台下,和11(APP直接下载)的下载方式时,支持下载时间点的监测。

    具体添加方式:监测下载开始事件,需要添加event="downloaded",监测下载完成

  5. Android端支持监控广告点击下载后的APP安装情况,交互场景为通过广告下载app后进行了app安装,安装完成回传该字段

     具体添加方式:监测下载安装时需添加 event="installed"
    
  6. 若没有任何事件监测需求,可以没有 TrackingEvents 节点

  7. miaozhen.com、admaster.com.cn、cr-nielsen.com、mma.ctrmi.com 的点击监测都默认由MMA SDK发送

# 附录五:广告位ID列表

请联系运营。

# 附录六: 行业

请联系运营。

# 附录七: 模版ID

请联系运营

# 附录八: Platform_id 说明

平台id(Platform_id) 说明
11 PC网页端
12 PC客户端
13 Mac客户端(不支持RTB)
21 IPad H5(贴片可点击)
22 iPad客户端
23 Android平板客户端
25 win平板客户端(不支持RTB)
32 iPhone客户端
33 Android手机端
35 win手机客户端(不支持RTB)
311 Android手机H5
312 iPhoneH5(贴片不可点击)
5201 电视(android端)
61 UWP Phone(不支持RTB)
62 UWP Pad(不支持RTB)
63 UWP Xbox(不支持RTB)
27 Android平板H5
28 智能音箱 (不支持RTB)

# 附录十: 频道ID

请联系运营。

# 附录十一: 广告类型 id

广告类型 id(ad_type_id)
页面 0
前贴 1
中贴 2
后贴 3
暂停 6
通用浮层 10

# 附录十二: 网络接入字段

网络接入字段(connection_id) 说明
0 Unknown
1 Ethernet
2 Wifi
3 Cellular date-2G
4 Cellular date-3G
5 Cellular date-4G
6 Cellular date-5G