خادم إلى خادم: دليل إعداد خادم المزاد

الخدمة الوسيطة الداخلية ليست متوفرة للعامة

عروض الأسعار الداخلية مع Audience Network متاحة حاليًا في الإصدار التجريبي المغلق وليست متوفرة للعامة. سنقدم المزيد من التحديثات إذا تغير هذا الأمر.

كبديل، يمكنك الوصول إلى عروض أسعار Audience Network من خلال إحدى منصات الخدمات الوسيطة التي تجمعنا معها شراكة.

يوضح هذا الدليل كيفية إنشاء خادم المزاد الداخلي. في الدليل التفصيلي أدناه، سنستخدم مثالاً على عرض الأسعار في إعلان خلالي. وتأكد من أنك بالفعل على دراية باستخدام الإعلانات الخلالية في Audience Network. تدعم عروض الأسعار أيضًا الإعلانات الأصلية وإعلانات البانر والإعلانات الخلالية ومقاطع الفيديو المضمّنة في المحتوى وتنسيقات الفيديو بمكافأة. يمكنك التحقق من التنسيقات الإعلانية المدعومة) أدناه لدمج تنسيق إعلاني مختلف.

يكون نموذج الرمز البرمجي الذي وفرناه مخصصًا فقط لتوضيح كيفية عمل واجهة API عرض الأسعار وكيفية دمجها في خادم المزاد الداخلي الخاص بك. وتتم كتابة نموذج خادم المزاد بلغة Python بإطار Flask بحد أدنى من الثبات والاعتبارات الأمنية لتبسيط مصدر الرمز البرمجي.


خطوات إعداد خادم المزاد

الخطوة الأولى: تحديد المنصات على الخادم

الخطوة الثانية: إنشاء طلبات ORTB من الخادم

الخطوة الثالثة: تنفيذ طلبات ORTB من الخادم

الخطوة الرابعة: تشغيل المزاد على الخادم

الخطوة الخامسة: تشغيل إشعارات تتعلق بالفوز/الخسارة/انتهاء المهلة

الخطوة السادسة: إعادة الفائز إلى جانب العميل

خطوات إعداد خادم المزاد

الخطوة الأولى: تحديد المنصات على الخادم

يحتفظ حقل ORTB imp.tagid بمعرف Audience Network للمخزون. يتم تمثيل المخزون في Audience Network كمعرف.

يجب أن يتضمن طلب 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

إذا كنت شريك خدمة وسيطة، فهذا هو معرف الشريك الذي قدمته جهة اتصال فيسبوك.

إذا كنت ناشرًا تعمل على دمج حل داخلي، فهذا هو معرف التطبيق الذي ترسل طلب عرض الأسعار لأجله. هذا يشكل أول جزء من معرف الموضع، قبل الشرطة السفلية.

${AUTHENTICATION_ID}

string

رمز المصادقة للتحقق من منشئ الطلب. راجع هذه الصفحة.

${AN_SECURITY_APP_MY_SECURITY_APP_ID}

string

معرف تطبيق الأمان المستخدم لإنشاء authentication_id، راجع هذه الصفحة.

${VERSION_NUMBER}

string

إصدار الدمج. بحد أقصى 16 حرفًا، يتم إنشاؤه بواسطة الناشر.

يتطلب Audience Network حمولة البيانات لطلب ORTB أعلاه. وعلى الرغم من ذلك، يمكنك تعريف بعض مواصفات التطبيق في خادم المزاد الخاص بك، مثل معرف التطبيق ومعرف الموضع وبعض المعلمات الأخرى في تكوين الخادم، فمن ثمّ لا يحتاج تطبيقك من جهة العميل إلا إلى إرسال طلب مبسّط. ويمكن أن يبحث الخادم لديك عن معلومات حول الموضع وينشئ طلب 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}

إذا كنت شريك خدمة وسيطة، فهذا هو معرف الشريك الذي قدمته جهة اتصال فيسبوك.

إذا كنت ناشرًا تعمل على دمج حل داخلي، فهذا هو معرف التطبيق الذي ترسل طلب عرض الأسعار لأجله. هذا يشكل أول جزء من معرف الموضع، قبل الشرطة السفلية.

مع إعدادات خادم المزاد أعلاه، يحتاج التطبيق من جانب العميل فقط إلى إرسال طلب مبسّط يتضمن "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}"
    }]
}

الخطوة الثانية: إنشاء طلبات 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 استنادًا إلى معلومات الموضع الكاملة.

يحتفظ حقل ORTB imp.tagid بمعرف Audience Network للمخزون. يتم تمثيل المخزون في Audience Network كمعرف موضع.

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)

تنسيقات الإعلانات المدعومة

ندعم حاليًا أربعة أنواع من الإعلانات التي يمكن طلبها من خلال 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}}

*يمكنك إنشاء بانر أو موضع مستطيل متوسط في مدير الأرباح لتنسيق الإعلان هذا

الخطوة الثالثة: تنفيذ طلبات 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: يُعد معرف الطلب ضروريًا لـ Audience Network لتصحيح أخطاء طلب محدد. ويرجى تسجيله عند طلب الدعم.
  • 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-compressed ثنائي إذا قمت بتوفير عنوان Content-Encoding:gzip في الطلب.

الخطوة الرابعة: تشغيل المزاد على الخادم

حصلنا الآن على الاستجابات الخاصة بعرض الأسعار من منصة مختلفة (الشبكة). في 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 أعلى من دولار واحد، فإننا نستجيب كما لو أن Audience Network فازت بعرض الأسعار، وبخلاف ذلك، يتم التعامل معها على أنها خسرت المزاد.

الخطوة الخامسة: تشغيل إشعارات تتعلق بالفوز/الخسارة/الفوترة/انتهاء المهلة

نطلب إشعارات الفوز والخسارة والفوترة وانتهاء المهلة مع الرموز البرمجية الصحيحة للخسارة كما هو محدد في 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}: يجب استبدال هذا السعر بـسعر التسوية الخاص بالمزاد في الوحدة نفسها الموجودة في عرض الأسعار الخاص بنا (على سبيل المثال، الدولار الأمريكي على أساس التكلفة لكل ألف ظهور).

إشعار الخسارة

يحتوي lurl الخاص بالخسارة لدينا على علامتين تحتاج إلى ملئهم:

"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}: يجب استبدال هذا بـسعر المسح للمزاد في الوحدة نفسها كعرض الأسعار الخاص بنا (على سبيل المثال الدولار على أساس التكلفة لكل ألف ظهور).

فيما يلي قائمة بمختلف الرموز البرمجية للخسارة وأسباب الخسارة المطابقة.

سبب الخسارةالوصفالرمز البرمجي للخسارة الخاص بـ ORTB بالإصدار 2.5

استجابة عرض الأسعار غير صالحة

عرض الأسعار غير صالح (لكن في الوقت المحدد، ولا ينقصه عرض الأسعار، وصالح بما فيه الكفاية بحيث يمكنك استخراج nurl)

3

انتهاء مهلة عرض الأسعار *

تم تلقي استجابة عرض الأسعار، ولكن متأخرًا جدًا عن موعد انتهاء المزاد

2

لا يوجد عرض أسعار

يُشار إلى عدم وجود عروض أسعار على أنه HTTP 204 (على سبيل المثال، لا يوجد nurl لاستدعائه)، ولكن قد تفسر الاستجابة الخاصة بنا على أنها عدم وجود عرض أسعار (قد تكون مشكلة تكامل). وقد يمكنك أيضًا طلب عروض أسعار للعديد من مرات الظهور، وسنقدم عرض أسعار لبعض مرات الظهور وليس جميعها.

9

ليس أعلى مُقدم عرض أسعار RTB

تغلّب علينا مُقدم عرض أسعار آخر بما في ذلك عروض الأسعار الصناعية (على سبيل المثال، التبادلات بخلاف RTB)، إذا تم إدخالها في المزاد نفسه.

102

لم يتحقق المخزون

فاز عرض الأسعار الخاص بنا بالمزاد، ولكن لم يتحقق عدد مرات الظهور (على سبيل المثال، لم تكن الصفحة طويلة بما يكفي لتضمين هذه الفتحة، أو خرج المستخدم من التطبيق قبل استخدام الإعلان الذي تم تخزينه مؤقتًا.) ولا يمكن لجميع الشركاء توفير ذلك (ليس حدثًا)، لذلك سنستنتجه إذا لم يتم تقديمه.

4902

تم إرساله إلى خادم الإعلان

أرسل هذا في حالة قيام نقطة الاتصال الأخيرة لديك متضمنة عملية اتخاذ القرار بإرسال عرض الأسعار العالي الخاص بنا إلى خادم الإعلان. وقد يظل عدد مرات الظهور مفقودًا عن طريق عناصر السطر المفقودة أو خادم الإعلان الذي يلغي المزاد أو عدم تحقيق المخزون.

4900

لم يتم اختيار فائز RTB بواسطة خادم الإعلان

فزنا بمزاد RTB، ولكن خادم الإعلان ألغى المزاد (على سبيل المثال، مزاد مباشر).

4903

الفوز

فزنا بشجرة القرار الكاملة وتم وضع إشارة على الصفحة (الويب) أو تخزين كائن الإعلان مؤقتًا (التطبيق). وقد يستمر عدم إنتاج عدد مرات الظهور القابل للعرض.

0

إشعار الفوترة

نطلب إشعار الفوترة في حالة استدعاء عدد مرات الظهور الذي تم تشغيله في مجموعة Audience Network SDK. تحتاج إلى ملء سعر التسوية في 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}: يجب استبدال هذا بـسعر المسح للمزاد في الوحدة نفسها كعرض الأسعار الخاص بنا (على سبيل المثال الدولار على أساس التكلفة لكل ألف ظهور).

إشعار انتهاء المهلة

في حالة انتهاء مهلة عرض الأسعار، نقدم لك مسار الإبلاغ البديل. وهذا هو 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

Int (عدد صحيح)

معرف خادم المزاد الإعلاني الصادر عن فيسبوك. واستخدم معرف تطبيقك هنا إذا لم يكن لديك شريك مخصص للمزاد الإعلاني.

APP_FBID

عدد صحيح

معرف صادر عن فيسبوك للتطبيق/النشاط التجاري الذي بدأ مزادًا.

AUCTION_ID

String (سلسلة)

معرف أنشأه العميل للمزاد الذي استخدمته لإصدار طلب عرض أسعار.

الخطوة السادسة: إعادة الفائز إلى جانب العميل

بعد تشغيل المزاد، ننشئ كائن الاستجابة ونقوم بإرجاعها إلى تطبيق العميل. فيما يلي الأسلوب في العينة في 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
}