ระหว่างเซิร์ฟเวอร์กับเซิร์ฟเวอร์: คู่มือการตั้งค่าเซิร์ฟเวอร์การประมูลราคา

สื่อกลางโฆษณาภายในองค์กรยังไม่พร้อมให้บริการต่อสาธารณะ

ขณะนี้การประมูลภายในองค์กรด้วย Audience Network เป็นเวอร์ชั่นเบต้าแบบปิดและยังไม่พร้อมให้บริการต่อสาธารณะ โดยเราจะแจ้งข้อมูลอัพเดตเพิ่มเติมหากมีการเปลี่ยนแปลง

คุณสามารถเข้าถึงการประมูลของ Audience Network ผ่านแพลตฟอร์มสื่อกลางโฆษณาที่เราเป็นพาร์ทเนอร์ด้วยแทนได้

คู่มือนี้จะอธิบายถึงวิธีที่คุณสามารถสร้างเซิร์ฟเวอร์การประมูลราคาภายในองค์กรได้ เราจะใช้ตัวอย่างการประมูลโฆษณาคั่นในคู่มือที่ให้คำแนะนำทีละขั้นตอนด้านล่าง ตรวจสอบให้แน่ใจว่าคุณคุ้นเคยกับการใช้โฆษณาคั่นบน Audience Network แล้ว นอกจากนี้ การประมูลยังรองรับรูปแบบเนทีฟ, แบนเนอร์, คั่น, วิดีโอในสตรีม และวิดีโอที่มีรางวัลหลังชมจบอีกด้วย คุณสามารถตรวจสอบรูปแบบโฆษณาที่เรารองรับด้านล่างเพื่อผสานการทำงานรูปแบบโฆษณาประเภทอื่น

ตัวอย่างรหัสที่จัดเตรียมให้มีไว้เพื่อสาธิตวิธีการทำงานของ API การประมูล และสาธิตวิธีการที่คุณสามารถผสานการทำงานเข้ากับเซิร์ฟเวอร์การประมูลราคาภายในองค์กรของคุณเท่านั้น ตัวอย่างเซิร์ฟเวอร์การประมูลราคานั้นเขียนขึ้นด้วยภาษา Python ใน Flask โดยคำนึงถึงความเสถียรและการรักษาความปลอดภัยขั้นต่ำเพื่อทำให้ซอร์สโค้ดไม่ซับซ้อน


ขั้นตอนการตั้งค่าเซิร์ฟเวอร์การประมูลราคา

ขั้นตอนที่ 1: การระบุแพลตฟอร์มบนเซิร์ฟเวอร์ของคุณ

ขั้นตอนที่ 2: การสร้างคำขอ ORTB จากเซิร์ฟเวอร์ของคุณ

ขั้นตอนที่ 3: การดำเนินการตามคำขอ ORTB จากเซิร์ฟเวอร์ของคุณ

ขั้นตอนที่ 4: การดำเนินการประมูลราคาบนเซิร์ฟเวอร์ของคุณ

ขั้นตอนที่ 5: การแจ้งเตือนการชนะ/การแพ้/การหมดเวลา

ขั้นตอนที่ 6: การส่งผู้ชนะการประมูลกลับไปยังฝั่งไคลเอ็นต์ของคุณ

ขั้นตอนการตั้งค่าเซิร์ฟเวอร์การประมูลราคา

ขั้นตอนที่ 1: การระบุแพลตฟอร์มบนเซิร์ฟเวอร์ของคุณ

ช่อง imp.tagid ใน ORTB มีตัวระบุ Audience Network สำหรับสินค้าคงคลัง สินค้าคงคลังจะแสดงใน Audience Network เป็นรูปแบบ ID

คำขอ ORTB ที่ส่งไปยังตำแหน่งข้อมูลของการประมูล Audience Network จะต้องมีทั้งข้อมูลอุปกรณ์และข้อมูลแอพ นี่คือตัวอย่างเพย์โหลดในคำขอ ORTB

{
// Device information from client side
'device': {
'ifa': '${DEVICE_ID}',
'dnt': '0',
'ip': '127.0.0.1'
},
// Application information
'app': {
'ver': '1.0',
'bundle': 'com.facebook.audiencenetwork.AdUnitsSample',
'publisher': {
// For server to server bidding integration, this is your application id on Facebook
'id': '${APP_ID}',
}
},
// Placement information we can store on server
'imp': [
{
'id': 'banner_test_bid_req_id',
// This is the placement id for Audience Network
'tagid': '${PLACEMENT_ID}',
'banner': {
'w': -1,
'h': 50,
},
},
],
// Optional regulations object from client side
'regs': {
'coppa': 0,
},
// In server to server integration, you can use the Facebook app id as platform id here
'ext': {
'platformid': '${PLATFORM_ID}',
// Mediation partner Platform ID or publisher FB app ID, mandatory.
'authentication_id': '${AUTHENTICATION_ID}',   
// Authentication token to validate the originator of the request.
'security_app_id': '${AN_SECURITY_APP_MY_SECURITY_APP_ID}',
// Security app id used to generate authentication_id.
's2s_version': '${VERSION_NUMBER}',
// Version of the integration. Max 16 characters.
},
// buyeruid is the user bidder token generated on client side, using the `getBidderToken` method from the Audience Network SDK. 
// It's constant through out app session so you could cache it on the client side
'user': {
'buyeruid': 'mybuyeruid',
},
// Test mode flag
'test': '1',
// Time out setting we can store on server
'tmax': 1000,
// Request ID we can generate on server
'id': 'banner_test_bid_req_id',
// Auction setting we can store on server
'at': 1,
}
พารามิเตอร์ ประเภท การใช้งาน

${PLATFORM_ID}

string

หากคุณเป็นพาร์ทเนอร์สื่อกลางโฆษณา นี่คือ ID พาร์ทเนอร์ที่ได้รับจากผู้ติดต่อบน Facebook ของคุณ

หากคุณเป็นผู้เผยแพร่ที่ผสานการทำงานโซลูชันภายในองค์กร นี่คือ ID แอพที่คุณส่งคำขอประมูลมาเพื่อรับ โดยสิ่งดังกล่าวประกอบขึ้นเป็นส่วนแรกของ ID ตำแหน่งการจัดวางที่อยู่ก่อนเครื่องหมายขีดล่าง

${AUTHENTICATION_ID}

string

โทเค็นการยืนยันตัวตนเพื่อตรวจสอบความถูกต้องของผู้สร้างคำขอ โปรดอ้างอิงไปยังหน้านี้

${AN_SECURITY_APP_MY_SECURITY_APP_ID}

string

ID แอพการรักษาความปลอดภัยที่ใช้ในการสร้าง authentication_id โปรดอ้างอิงไปยังหน้านี้

${VERSION_NUMBER}

string

เวอร์ชั่นของการผสานการทำงาน สูงสุด 16 อักขระ และสร้างโดยผู้เผยแพร่

เพย์โหลดคำขอ ORTB ข้างต้นเป็นสิ่งจำเป็นสำหรับ Audience Network อย่างไรก็ตาม คุณสามารถระบุข้อกำหนดบางอย่างบนเซิร์ฟเวอร์การประมูลราคาของตนเองให้กับแอพได้ เช่น ID แอพ, ID ตำแหน่งการจัดวาง และพารามิเตอร์อื่นๆ จากในการกำหนดค่าเซิร์ฟเวอร์ จากนั้นแอพทางฝั่งไคลเอ็นต์ของคุณก็เพียงแค่ต้องส่งคำขอที่ซับซ้อนน้อยลงเท่านั้น เซิร์ฟเวอร์ของคุณสามารถวนข้อมูลตำแหน่งการจัดวางซ้ำ และสร้างคำขอ ORTB สุดท้ายได้ ด้านล่างนี้คือตัวอย่างการตั้งค่าเซิร์ฟเวอร์การประมูลราคา

{
"bidding_source_platforms": [
{
"platform_name": "audience_network",
"end_point": "https://an.facebook.com/${PLATFORM_ID}/placementbid.ortb",
"timeout": 1000,
"timeout_notification_url": "https://www.facebook.com/audiencenetwork/nurl/?partner=${PARTNER_FBID}&app=${APP_FBID}&auction=${AUCTION_ID}&ortb_loss_code=2"
}
],
"apps": [
{
"app_id": "101",
"app_name": "My example app",
"placements": [
{
"placement_id": "1",
"placement_name": "My example placement",
"ad_format": "interstitial",
"bidding_source_placement_ids":[
{
"platform_name": "audience_network",
"platform_app_id": "${APP_ID}",
"platform_placement_id": "${PLACEMENT_ID}"
}
]
}
]
}
]
}
พารามิเตอร์ การใช้งาน

${PLATFORM_ID}

หากคุณเป็นพาร์ทเนอร์สื่อกลางโฆษณา นี่คือ ID พาร์ทเนอร์ที่ได้รับจากผู้ติดต่อบน Facebook ของคุณ

หากคุณเป็นผู้เผยแพร่ที่ผสานการทำงานโซลูชันภายในองค์กร นี่คือ ID แอพที่คุณส่งคำขอประมูลมาเพื่อรับ โดยสิ่งดังกล่าวประกอบขึ้นเป็นส่วนแรกของ ID ตำแหน่งการจัดวางที่อยู่ก่อนเครื่องหมายขีดล่าง

ด้วยการตั้งค่าเซิร์ฟเวอร์การประมูลราคาแบบข้างต้น แอพฝั่งไคลเอ็นต์เพียงแค่ต้องส่งคำขอที่ซับซ้อนน้อยลงอันประกอบด้วย "app_id":"101" และ "placement_id":"1" ไปยังเซิร์ฟเวอร์ของคุณ จากนั้นเซิร์ฟเวอร์ดังกล่าวจะสามารถค้นหาข้อมูลตำแหน่งการจัดวางแบบเต็มรูปแบบได้ เช่น placement_id, ad_format, platform_name เป็นต้น ต่อไปนี้คือเพย์โหลดตัวอย่างคำขอที่ซับซ้อนน้อยลงจากฝั่งไคลเอ็นต์ของคุณ

{
// App ID and placement ID are used to look up settings from
// server settings
'app_id': '101',
'placement_id': '1',

'bundle': 'com.facebook.samples.s2sbiddingclient',
'bundle_version': '1.0',

// Device specifics
'ifa': '${DEVICE_ID}',
'coppa': 0,
'dnt': 0,

// buyer_tokens are the user tokens required for different networks
'buyer_tokens': {
// Token for audience network from BidderTokenProvider.getBidderToken(context)
// This can be cached for the same app session
'audience_network': 'my-buyeruid',
},
}

เมื่อมีการส่งคำขอที่ซับซ้อนน้อยลงไปยังเซิร์ฟเวอร์การประมูลราคาของคุณแล้ว คุณควรจะสามารถค้นหาข้อมูลตำแหน่งการจัดวาง ข้อมูลอุปกรณ์ และข้อมูลแอพได้อย่างเต็มรูปแบบผ่าน app_id และ placement_id ในการตั้งค่าเซิร์ฟเวอร์การประมูลราคาของตนเอง นี่คือผลลัพธ์ตัวอย่างการค้นหา

{
"placement_id": "1",
"placement_name": "My example placement",
"ad_format": "interstitial",
"bidding_source_placement_ids":[
{
"platform_name": "audience_network",
"platform_app_id": "${APP_ID}",
"platform_placement_id": "${PLACEMENT_ID}"
}
]
}

ขั้นตอนที่ 2: การสร้างคำขอ ORTB จากเซิร์ฟเวอร์ของคุณ

หลังจากที่เซิร์ฟเวอร์การประมูลราคาได้รับคำขอการประมูลราคาแล้ว เซิร์ฟเวอร์จะต้องสร้างคำขอประมูลให้กับแหล่งที่มาของความต้องการแต่ละแห่ง ต่อไปนี้คือตำแหน่งข้อมูลใน app.py เพื่อรับคำขอการประมูลราคา

@app.route('/get_bid', methods=['POST'])
def get_bid():
'''
The actual endpoint that expects a ClientRequest in the parameters
'''
# Initialize the server settings
ServerSettings.initialize(
app.config['bidding_source_platforms'],
app.config['apps']
)

request_params = request.get_json(force=True)

# See the code sample below for this function in `bid_manager.py`
(code, response) = get_bid_response(
request.remote_addr,
request.user_agent.string,
request_params)

app.logger.debug('server response: {0} {1}'.format(code, response))
return Response(
json.dumps(response),
status=code,
mimetype='application/json'
)

ใน bid_manager.py คำขอการประมูลราคาจากไคลเอ็นต์จะประกอบด้วย app_id และ placement_id ซึ่งใช้เพื่อค้นหาข้อมูลตำแหน่งการจัดวางแบบเต็มรูปแบบในการตั้งค่าเซิร์ฟเวอร์

# Return Auction Result - Winner - back to client side
def get_bid_response(ip, user_agent, request_params):
"""Get the winner bid response for the current request"""
try:
app_id = request_params['app_id']
placement_id = request_params['placement_id']
auction_id = get_auction_id()
...
# Find placement in the settings
placement = ServerSettings.get_placement(app_id, placement_id)

# Collect bid requests for different platforms
bid_requests = get_bid_requests(
ip,
user_agent,
auction_id,
placement,
request_params)

except Exception as e:
raise ParameterError("Error in request parameters: {}".format(str(e)))
...
return final_response

# Get all bid requests for different platforms
def get_bid_requests(ip, user_agent, auction_id, placement, request_params):
"""Create bid requests based on the internal placement setting"""

...

(end_point, data, timeout_notification_url) = get_bid_request(
ip,
user_agent,
auction_id,
platform_name,
platform_app_id,
platform_placement_id,
ad_format,
request_params)

if data is not None:
results.append({
'platform_name': platform_name,
'end_point': end_point,
'data': data,
'timeout_notification_url': timeout_notification_url,
})

# current_app.logger.debug("requests: {}".format(results))
return results

# Get bid request for each platform
def get_bid_request(
ip,
user_agent,
auction_id,
platform_name,
platform_app_id,
platform_placement_id,
ad_format,
request_params
):
"""Create bid request for a specific platform"""
if platform_name == 'audience_network':

return audience_network.get_bid_request(
ip,
user_agent,
auction_id,
platform_app_id,
platform_placement_id,
ad_format,
request_params)

else:
return (None, None, None)

จากนั้นใน audience_network.py ฟังก์ชัน get_bid_request จะสร้างคำขอ ORTB ขั้นสุดท้ายให้กับ Audience Network ตามข้อมูลตำแหน่งการจัดวางแบบเต็มรูปแบบ

ช่อง imp.tagid ใน ORTB มีตัวระบุ Audience Network สำหรับสินค้าคงคลัง สินค้าคงคลังจะแสดงใน Audience Network เป็นรูปแบบ ID ตำแหน่งการจัดวาง

def get_bid_request(
ip,
user_agent,
auction_id,
platform_app_id,
platform_placement_id,
ad_format,
request_params
):
'''
Gather the required bid request parameters for networks. The parameters
consist of platform settings like app id, placement ids, ad sizes etc., and
client side information such as device information, user agent etc. We use
the `settings.json` file to store platform specific settings, and the
client request to retrieve the clietn specific information.
'''
platform = ServerSettings.get_platform('audience_network')
end_point = platform['end_point']
timeout = platform['timeout']
timeout_notification_url = platform['timeout_notification_url']

timeout_notification_url.replace('${PARTNER_FBID}', platform_app_id)
timeout_notification_url.replace('${APP_FBID}', platform_app_id)
timeout_notification_url.replace('${AUCTION_ID}', auction_id)

imp = []
if ad_format == 'native':
imp.append({
'id': auction_id,
'native': {
'w': -1,
'h': -1,
},
'tagid': platform_placement_id,
})
elif ad_format == 'banner':
imp.append({
'id': auction_id,
'banner': {
'w': -1,
'h': 50,
},
'tagid': platform_placement_id,
})
elif ad_format == 'interstitial':
imp.append({
'id': auction_id,
'banner': {
'w': 0,
'h': 0,
},
'tagid': platform_placement_id,
'instl': 1,
})
elif ad_format == 'rewarded_video':
imp.append({
'id': auction_id,
'video': {
'w': 0,
'h': 0,
'linearity': 2,
},
'tagid': platform_placement_id,
})
elif ad_format == 'instream_video':
imp.append({
'id': auction_id,
'video': {
'w': 0,
'h': 0,
'linearity': 1,
},
'tagid': platform_placement_id,
})
else:
raise ParameterError("Incorrect ad format")

typed_ip = ipaddress.ip_address(ip)
device = {
'ifa': request_params['ifa'],
'ua': user_agent,
'dnt': request_params['dnt'],
}
if type(typed_ip) is ipaddress.IPv6Address:
device['ipv6'] = ip
else:
device['ip'] = ip

# Construct the ORTB request
request = {
'id': auction_id,
'imp': imp,
'app': {
'bundle': request_params['bundle'],
'ver': request_params['bundle_version'],
'publisher': {
'id': platform_app_id,
}
},
'device': device,
'regs': {
'coppa': request_params['coppa'],
},
'user': {
'buyeruid': request_params['buyer_tokens']['audience_network'],
},
'ext': {
'
': platform_app_id,
},
'at': 1,
'tmax': timeout,
'test': request_params['test'],
}

return (end_point, request, timeout_notification_url)

รูปแบบโฆษณาที่รองรับ

ปัจจุบันเรารองรับโฆษณา 4 ประเภทที่สามารถขอผ่าน OpenRTB ได้ ได้แก่ แบนเนอร์ เนทีฟ (เนทีฟหรือแบนเนอร์เนทีฟ) วิดีโอ (วิดีโอที่มีรางวัลหลังชมจบหรือวิดีโอในสตรีม) และโฆษณาคั่น หมายเหตุ: คุณจะใช้อ็อบเจ็กต์แบนเนอร์ เนทีฟ และวิดีโอร่วมกันไม่ได้ แต่จำเป็นต้องมีรูปแบบใดรูปแบบหนึ่ง

รายการต่อไปนี้คือรูปแบบโฆษณาที่รองรับในคำขอประมูล

รูปแบบโฆษณา พารามิเตอร์ในคำขอประมูล

เนทีฟ

{'id': ${AUCTION_ID}, 'native': { 'h': -1, 'w': -1 }, 'tagid': ${PLACEMENT_ID}}

แบนเนอร์เนทีฟ

{'id': ${AUCTION_ID}, 'native': { 'h': -1, 'w': -1 }, 'tagid': ${PLACEMENT_ID}}

โฆษณาคั่น

{'id': ${AUCTION_ID}, 'banner': { 'h': 0, 'w': 0 }, 'tagid': ${PLACEMENT_ID}, 'instl': 1}

วิดีโอที่มีรางวัลหลังชมจบ

{'id': ${AUCTION_ID}, 'video': { 'h': 0, 'w': 0, 'ext': { 'videotype': 'rewarded' } }, 'tagid': ${PLACEMENT_ID}}

โฆษณาคั่นที่มีรางวัลหลังชมจบ

{'id': ${AUCTION_ID}, 'video': { 'h': 0, 'w': 0, 'ext': { 'videotype': 'rewarded_interstitial' } }, 'tagid': ${PLACEMENT_ID}}

แบนเนอร์ - ความสูง: 50

{'id': ${AUCTION_ID}, 'banner': { 'h': 50, 'w': -1 }, 'tagid': ${PLACEMENT_ID}}

แบนเนอร์ - ความสูง: 250*

{'id': ${AUCTION_ID}, 'banner': { 'h': 250, 'w': -1 }, 'tagid': ${PLACEMENT_ID}}

*คุณสามารถสร้างแบนเนอร์หรือตำแหน่งการจัดวางแบบสี่เหลี่ยมผืนผ้าขนาดกลางได้ในตัวจัดการการสร้างรายได้สำหรับรูปแบบโฆษณานี้

ขั้นตอนที่ 3: การดำเนินการตามคำขอ ORTB จากเซิร์ฟเวอร์ของคุณ

หลังจากที่สร้างอ็อบเจ็กต์คำขอ ORTB ด้านบนแล้ว เราสามารถส่งคำขอไปยังตำแหน่งข้อมูล Audience Network ได้ที่ https://an.facebook.com/${PLATFORM_ID}/placementbid.ortb โดยใช้คำขอ HTTP ซึ่งใช้ post และ Content-Type: application/json

ใน bid_manager.py เมื่อระบบเก็บคำขอประมูลทั้งหมดจากแต่ละแพลตฟอร์มแล้ว ระบบจะเรียกใช้ exec_bid_requests ในแต่ละแพลตฟอร์ม

# Return Auction Result - Winner - back to client side
def get_bid_response(ip, user_agent, request_params):
"""Get the winner bid response for the current request"""
...
# Execute bid requests by network
bid_responses = []
for bid_request in bid_requests:
(code, response) = exec_bid_request(
bid_request['platform_name'],
bid_request['end_point'],
bid_request['data'],
bid_request['timeout_notification_url'])

bid_responses.append({
'platform_name': bid_request['platform_name'],
'code': code,
'response': response,
})

final_response = run_auction(bid_responses, placement)
return final_response

# Execute bid request for different platform (network)
def exec_bid_request(
platform_name,
end_point,
request_params,
timeout_notification_url
):
'''
Actually run the bid requests for the networks.
'''
if platform_name == 'audience_network':
return audience_network.exec_bid_request(
end_point,
request_params,
timeout_notification_url,
)
else:
raise InternalError("Invalid platform: {}".format(platform_name))

ส่วนหัว HTTP ต่อไปนี้ (ทั้งในที่เสนอราคาประมูลและไม่เสนอราคาประมูล) ในการตอบกลับจะเป็นกลุ่มย่อยซึ่งมีข้อมูลที่เป็นประโยชน์สำหรับการแก้ปัญหา และควรบันทึกไว้ในเซิร์ฟเวอร์การประมูลราคา

  • X-FB-AN-Request-ID: ID คำขอเป็นสิ่งจำเป็นสำหรับ Audience Network ในการแก้ไขจุดบกพร่องของคำขอนั้นๆ โปรดบันทึก ID ไว้ทุกครั้งที่ขอความช่วยเหลือ
  • X-FB-AN-Errors: รายการข้อผิดพลาดที่พบ ซึ่งมีประโยชน์ในการทำความเข้าใจถึงสาเหตุของการไม่เสนอราคา
  • X-FB-Debug: ข้อมูลการแก้ไขจุดบกพร่องบางประการเกี่ยวกับคำขอนี้ ซึ่งคุณสามารถส่งไปยังตัวแทนบัญชีของตนเองที่ Audience Network เพื่อแก้ปัญหา

หมายเหตุ: เพื่อลดเวลาในการตอบกลับให้สั้นลง คุณจำเป็นต้องเพิ่มส่วนหัว X-FB-Pool-Routing-Token ลงในคำขอประมูลของคุณ

  • X-FB-Pool-Routing-Token: โทเค็นนี้ใช้สำหรับการกำหนดเส้นทางคำขอไปยังศูนย์ข้อมูลที่ใกล้ที่สุด และมีค่าเหมือนกับ user.buyeruid

ใน audience_network.py คำขอ ORTB จะถูกส่งไปยัง Audience Network และการตอบกลับราคาประมูลจะถูกส่งไปยังเซิร์ฟเวอร์การประมูลราคาตามลำดับ

def exec_bid_request(
end_point,
request_params,
timeout_notification_url
):
try:
platform = ServerSettings.get_platform('audience_network')
headers = {
'Content-Type': 'application/json; charset=utf-8',
'X-FB-Pool-Routing-Token': request_params['user']['buyeruid'],
}
timeout = platform['timeout']
r = requests.post(
end_point,
json=request_params,
headers=headers,
# Timeout in settings.json in ms
timeout=(timeout / 1000),
)
except Exception as e:
current_app.logger.error(BID_TIMEOUT)

# Send time out notification
r = requests.get(timeout_notification_url, timeout)
return (500, BID_TIMEOUT)

if r.status_code == requests.codes.ok:
try:
data = json.loads(r.text)
current_app.logger.debug('Audience Network response: {}'.format(
data
))
# Parse response from Audience Network with the ORTBResponse
ortb_response = ORTBResponse(data)
except Exception as e:
current_app.logger.error(
PARSE_ERROR + "{}".format(e)
)
return (500, PARSE_ERROR + "{}".format(e))

return (r.status_code, ortb_response)

else:
# The error message is stored in the X-FB-AN-Errors header
error_header = r.headers.get('x-fb-an-errors')
debug_header = r.headers.get('x-fb-debug')
bid_request_id = r.headers.get('x-fb-an-request-id')

if r.status_code == 400:
error_message = INVALID_BID + error_header + INVALID_BID_ADVICE
elif r.status_code == 204:
error_message = NO_BID + error_header
else:
error_message = UNEXPECTED_ERROR

# Log error information for debugging
error = {
'bid_request_id': bid_request_id,
'debug_header': debug_header,
'error_message': error_message,
}
current_app.logger.error(error)

# Respond error status code to client
return (r.status_code, error_message)

คุณสามารถส่งเนื้อความของคำขอที่บีบอัดในรูปแบบ gzip แบบไบนารีได้ หากคุณระบุส่วนหัว Content-Encoding:gzip ให้กับคำขอของคุณ

ขั้นตอนที่ 4: การดำเนินการประมูลราคาบนเซิร์ฟเวอร์ของคุณ

ตอนนี้เรามีการตอบกลับราคาประมูลจากแพลตฟอร์ม (เครือข่าย) ที่แตกต่างกันแล้ว ใน bid_manager.py ฟังก์ชัน get_bid_response จะรับผิดชอบในการเปรียบเทียบการตอบกลับราคาประมูลที่กรอกมา และตัดสินว่าราคาประมูลใดมีราคาสูงสุด และให้ผู้นั้นเป็นผู้ชนะ

def get_bid_response(ip, user_agent, request_params):
"""Get the winner bid response for the current request"""
...
final_response = run_auction(bid_responses, placement)
return final_response

def run_auction(bid_responses, placement):
"""Run auction based on raw responses and create the response object"""
other_bid = 1
response = (204, None)  # default is 204 no fill

for bid_response in bid_responses:
if bid_response['platform_name'] == 'audience_network':
if bid_response['code'] == 200:
ortb_response = bid_response['response']
if ortb_response.price > other_bid:
response = create_response(bid_response, placement)
current_app.logger.debug(
'Audience Network bid: {} won!'.format(
ortb_response.price
)
)
notify_result(bid_response)
else:
current_app.logger.debug(
'Audience Network bid: {} lost!'.format(
ortb_response.price
)
)
notify_result(bid_response, 102)
else:
current_app.logger.debug(bid_response['response'])

return response

เนื่องจาก Audience Network เป็นผู้เสนอราคาประมูลเพียงรายเดียวในตัวอย่างของเรา วิธีการประมูลที่ใช้จะเปรียบเทียบราคาประมูลที่ส่งกลับมากับมูลค่าราคาบางส่วน แล้วตัดสินใจว่าจะชนะการประมูลหรือไม่ ผลก็คือ หากราคาประมูลที่ส่งกลับมาจาก Audience Network สูงกว่า 1 ดอลลาร์ เราจะตอบกลับเนื่องจาก Audience Network ชนะการประมูล มิเช่นนั้นเราจะถือว่าราคาประมูลนั้นแพ้การประมูลไป

ขั้นตอนที่ 5: การแจ้งเตือนการชนะ/การแพ้/การหมดเวลา

เราต้องการการแจ้งเตือนการชนะ, การพ่ายแพ้, การเรียกเก็บเงิน และการหมดเวลา พร้อมโค้ดการพ่ายแพ้ที่เหมาะสมที่กำหนดไว้ใน ORTB ระบบจะแสดง nurl, lurl และ burl ของ ORTB ในการตอบกลับราคาประมูล โปรดตรวจสอบตัวอย่างการตอบกลับราคาประมูลที่ส่วนก่อนหน้านี้ ในกรณีของการหมดเวลาราคาประมูล เราจะระบุเส้นทางการรายงานทางเลือกแก่คุณ

การแจ้งเตือนการชนะ

ระบบจะระบุ nurl ผู้ชนะในการตอบกลับราคาประมูล คุณต้องเพิ่มจำนวนราคาที่เป็นดุลยภาพใน nurl:

"https://www.facebook.com/audiencenetwork/nurl/?partner=${PARTNER_FBID}&app=${APP_FBID}&placement=${PLACEMENT_FBID}&auction=${AUCTION_ID}&impression=${IMPRESSION_ID}&request=${BID_REQUEST_ID}&bid=${BID_ID}&ortb_loss_code=0&clearing_price=${AUCTION_PRICE}"
  • ${AUCTION_PRICE}: ซึ่งควรจะแทนที่ด้วยราคาที่เป็นดุลยภาพสำหรับการประมูลราคาในหน่วยเดียวกันกับราคาประมูลของเรา (เช่น USD ต่อ CPM)

การแจ้งเตือนการพ่ายแพ้

lurl การพ่ายแพ้ของเราจะมีตัวบ่งชี้ 2 รายการที่คุณต้องเพิ่มจำนวน:

"https://www.facebook.com/audiencenetwork/nurl/?partner=${PARTNER_FBID}&app=${APP_FBID}&placement=${PLACEMENT_FBID}&auction=${AUCTION_ID}&impression=${IMPRESSION_ID}&request=${BID_REQUEST_ID}&bid=${BID_ID}&ortb_loss_code=${AUCTION_LOSS}&clearing_price=${AUCTION_PRICE}"
  • ${AUCTION_LOSS} ซึ่งควรจะแทนที่ด้วย โค้ดการพ่ายแพ้ ของ ORTB
  • ${AUCTION_PRICE}: ซึ่งควรจะแทนที่ด้วยราคาที่เป็นดุลยภาพสำหรับการประมูลราคาในหน่วยเดียวกันกับราคาประมูลของเรา (เช่น USD ต่อ CPM)

ด้านล่างนี้เป็นรายการของโค้ดการพ่ายแพ้ที่แตกต่างกันและเหตุผลการพ่ายแพ้ที่สอดคล้องกัน

เหตุผลของการพ่ายแพ้คำอธิบายโค้ดการพ่ายแพ้เวอร์ชั่น 2.5 ของ ORTB

การตอบกลับราคาประมูลที่ไม่ถูกต้อง

ราคาประมูลไม่ถูกต้อง (แต่ตรงเวลา, ไม่ใช่การไม่มีราคาประมูล และถูกต้องเพียงพอที่คุณจะสามารถดึง nurl ได้)

3

การหมดเวลาราคาประมูล *

ได้รับการตอบกลับราคาประมูล แต่ช้าเกินไปสำหรับการตัดยอดประมูลราคา

2

ไม่มีราคาประมูล

ระบบจะแสดงการไม่มีราคาประมูลเป็น HTTP 204 (เช่น ไม่มี nurl ให้เรียก) แต่คุณอาจตีความการตอบกลับของเราเป็นการไม่มีราคาประมูล (อาจเป็นปัญหาเกี่ยวกับการผสานการทำงาน) คุณยังอาจส่งคำขอราคาประมูลสำหรับอิมเพรสชั่นหลายครั้ง และเราจะร่วมประมูลบางส่วนแต่ไม่ใช่ทั้งหมด

9

ไม่ใช่ผู้ประมูล RTB สูงสุด

มีผู้ประมูลรายอื่นที่เอาชนะคุณได้รวมถึงราคาประมูลแบบสังเคราะห์ (เช่น การแลกเปลี่ยนที่ไม่ใช่ RTB) หากผู้ประมูลเหล่านี้เข้าร่วมการประมูลราคาเดียวกัน

102

พื้นที่โฆษณาไม่ปรากฏ

ราคาประมูลของเราชนะการประมูลราคา แต่อิมเพรสชั่นไม่ปรากฏ (เช่น หน้ายาวไม่พอที่จะรวมในช่องนี้ หรือผู้ใช้ออกจากแอพก่อนที่จะใช้โฆษณาที่แคชไว้) พาร์ทเนอร์บางรายไม่สามารถระบุได้ (ไม่ใช่เหตุการณ์) ดังนั้นเราจะอนุมานได้หากไม่ได้ระบุไว้

4902

ส่งไปยังเซิร์ฟเวอร์โฆษณาแล้ว

ส่งข้อความนี้หากทัชพอยท์ที่คุณมีส่วนกับกระบวนการตัดสินใจได้ส่งราคาประมูลที่สูงของเราไปยังเซิร์ฟเวอร์โฆษณา อิมเพรสชั่นอาจสูญหายไประหว่างรายการโฆษณาที่ขาดหายไป เซิร์ฟเวอร์โฆษณาล้มเลิกการประมูลราคา หรือพื้นที่โฆษณาไม่ปรากฏ

4900

เซิร์ฟเวอร์โฆษณาไม่ได้เลือกผู้ชนะ RTB

เราชนะการประมูลราคา RTB แต่เซิร์ฟเวอร์โฆษณาล้มเลิกการประมูลราคา (เช่น โดยตรง)

4903

การชนะ

เราชนะต้นไม้ตัดสินใจทั้งหมด และวางแท็กบนหน้า (เว็บ) หรือแคชอ็อบเจ็กต์โฆษณาไว้ (แอพ) อิมเพรสชั่นที่มีการเห็นจริงอาจยังไม่ระบุผลลัพธ์

0

การแจ้งเตือนการเรียกเก็บเงิน

เราต้องการการแจ้งเตือนการเรียกเก็บเงินในกรณีที่ระบบกระตุ้นการเรียกกลับอิมเพรสชั่นใน SDK ของ Audience Network คุณต้องเพิ่มจำนวนราคาที่เป็นดุลยภาพใน burl:

"https://www.facebook.com/audiencenetwork/burl/?partner=${PARTNER_FBID}&app=${APP_FBID}&placement=${PLACEMENT_FBID}&auction=${AUCTION_ID}&impression=${IMPRESSION_ID}&request=${BID_REQUEST_ID}&bid=${BID_ID}&ortb_loss_code=0&clearing_price=${AUCTION_PRICE}"
  • ${AUCTION_PRICE}: ซึ่งควรจะแทนที่ด้วยราคาที่เป็นดุลยภาพสำหรับการประมูลราคาในหน่วยเดียวกันกับราคาประมูลของเรา (เช่น USD ต่อ CPM)

การแจ้งเตือนการหมดเวลา

สำหรับกรณีของการหมดเวลาราคาประมูล เราจะระบุเส้นทางการรายงานทางเลือกแก่คุณ โดยจะเป็น nurl ทั่วไปที่อาจเรียกได้โดยไม่ต้องรอให้การเสนอราคาประมูลมาถึง รูปแบบเป็นดังนี้:

"https://www.facebook.com/audiencenetwork/nurl/?partner=${PARTNER_FBID}&app=${APP_FBID}&auction=${AUCTION_ID}&ortb_loss_code=2"

หมายเหตุ: ควรเพิ่มจำนวน ${PARTNER_FBID}, ${APP_FBID} และ ${AUCTION_ID} ด้วยค่าที่เหมาะสม ตารางด้านล่างนี้ให้คำอธิบายเกี่ยวกับค่าเหล่านี้

พารามิเตอร์ประเภทคำอธิบาย

PARTNER_FBID

จำนวนเต็ม

ID ของเซิร์ฟเวอร์การประมูลโฆษณาที่ออกโดย Facebook ใช้ ID ของแอพที่นี่หากคุณไม่มีพาร์ทเนอร์การประมูลโฆษณาโดยเฉพาะ

APP_FBID

จำนวนเต็ม

ID ที่ Facebook ออกให้ของแอพพลิเคชั่น/ธุรกิจที่จะเริ่มต้นดำเนินการประมูลราคา

AUCTION_ID

สตริง

ID ที่ไคลเอ็นต์สร้างขึ้นของการประมูลราคาที่คุณใช้เพื่อส่งคำขอประมูล

ขั้นตอนที่ 6: การส่งผู้ชนะการประมูลกลับไปยังฝั่งไคลเอ็นต์ของคุณ

หลังจากดำเนินการประมูลราคาแล้ว เราจะสร้างอ็อบเจ็กต์การตอบกลับ แล้วส่งคืนกลับไปยังแอพไคลเอ็นต์ ต่อไปนี้เป็นวิธีการในตัวอย่างของ bid_manager.py ที่สร้างการตอบกลับขั้นสุดท้ายของเซิร์ฟเวอร์การประมูลราคา

def create_response(bid_response, placement):
"""Create response object based on the auction result"""
ad_format = placement['ad_format']
platform_name = bid_response['platform_name']
platform_placement_id = None

for bidding_source_placement_id in placement[
'bidding_source_placement_ids'
]:
if bidding_source_placement_id['platform_name'] == platform_name:
platform_placement_id = bidding_source_placement_id[
'platform_placement_id'
]

if platform_placement_id is None:
raise InternalError("Platform placement ID not found!")

bid_payload = None
if platform_name == 'audience_network':
bid_payload = bid_response['response'].adm
else:
raise InternalError("Invalid platform")

return (200, {
'placement_id': placement['placement_id'],
'ad_format': ad_format,
'platform_name': platform_name,
'platform_placement_id': platform_placement_id,
'bid_payload': bid_payload,
})

ท้ายสุด เซิร์ฟเวอร์ตัวอย่างของเราสามารถสร้างการตอบกลับนี้ให้กับไคลเอ็นต์เพื่อแจ้งให้ใช้แพลตฟอร์มใด

{
'placement_id': string, // Placement identifier for the auction server
'ad_format': string, // Format of the placement
'platform_name': string, // Which platform won the auction, for example 'audience_network'
'platform_placement_id': string, // Placement ID for the platform, for example the placement ID for Audience network
'bid_payload': string, // The JSON string payload for the platform SDK to load the final ad
}