De servidor para servidor: guia de configuração do servidor de leilão

A mediação interna não está disponível publicamente

No momento, os lances internos com o Audience Network estão na versão beta fechada e não estão disponíveis publicamente. Compartilharemos atualizações se isso mudar.

Como alternativa, você pode acessar os lances do Audience Network usando uma das nossas plataformas parceiras de mediação.

Este guia ensina a criar um servidor de leilão interno. No guia passo a passo abaixo, usamos o exemplo de lances em um anúncio intersticial. É preciso que você já esteja familiarizado com o uso de anúncios intersticiais do Audience Network. Os lances também são compatíveis com os formatos de anúncios nativos, intersticiais, de vídeo in-stream e de vídeo com incentivo. Consulte os formatos de anúncio compatíveis abaixo para integrar um formato de anúncio diferente.

Pré-requisitos

O exemplo de código que oferecemos tem apenas o intuito de demonstrar como a API de lances funciona e como você pode integrá-la ao seu servidor de leilão interno. O servidor de leilão de exemplo foi escrito em Python com Flask, com considerações mínimas de estabilidade e segurança pela simplicidade do código-fonte.


Etapas de configuração do servidor de leilão

Etapa 1: definir as plataformas no servidor

Etapa 2: gerar solicitações ORTB no servidor

Etapa 3: executar solicitações ORTB no servidor

Etapa 4: executar o leilão no servidor

Etapa 5: disparar notificações de ganho/perda/tempo-limite

Etapa 6: retornar o ganhador para seu cliente

Etapas de configuração do servidor de leilão

Etapa 1: definir as plataformas no servidor

O imp.tagid do campo ORTB detém o identificador do Audience Network para o inventário. O inventário é representado no Audience Network como o ID.

A solicitação ORTB enviada ao ponto de extremidade de lances do Audience Network precisa conter informações do dispositivo e do app. Veja aqui um exemplo de carga da solicitação 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,
}
Parâmetro Tipo Uso

${PLATFORM_ID}

string

Se você for um parceiro de mediação, esta é a identificação do parceiro fornecida pelo seu contato do Facebook.

Se você for um publisher e estiver integrando uma solução interna, este é o ID do app para enviar a solicitação de lance. Isso constitui a primeira parte do ID de posicionamento, antes do sublinhado.

${AUTHENTICATION_ID}

string

Token de autenticação para validar o originador da solicitação. Consulte esta página.

${AN_SECURITY_APP_MY_SECURITY_APP_ID}

string

O ID do app de segurança usado para gerar o authentication_id. Consulte esta página.

${VERSION_NUMBER}

string

Versão da integração. Máximo de 16 caracteres, gerada pelo publisher.

A carga da solicitação ORTB acima é exigida pelo Audience Network. No entanto, no seu próprio servidor de leilão, você pode definir algumas especificações do app, como ID do app, ID do posicionamento, bem como alguns outros parâmetros na configuração do servidor. Depois, o app do cliente só precisará enviar a solicitação simplificada. Seu servidor pode criar um loop com as informações de posicionamento e construir a solicitação ORTB final. Veja abaixo o exemplo de configuração do servidor de leilão:

{
"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}"
}
]
}
]
}
]
}
Parâmetro Uso

${PLATFORM_ID}

Se você for um parceiro de mediação, esta é a identificação do parceiro fornecida pelo seu contato do Facebook.

Se você for um publisher e estiver integrando uma solução interna, este é o ID do app para enviar a solicitação de lance. Isso constitui a primeira parte do ID de posicionamento, antes do sublinhado.

Com as configurações de servidor de leilão descritas acima, o app do cliente só precisa enviar uma solicitação simplificada com "app_id":"101" e "placement_id":"1" para seu servidor; depois, seu servidor poderá procurar informações completas de posicionamento (como placement_id, ad_format, platform_name, entre outros). Veja aqui um exemplo de carga da solicitação simplificada do app do cliente:

{
// 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',
},
}

Assim que a solicitação simplificada for enviada para seu servidor de leilão, você poderá procurar informações completas de posicionamento, dispositivo e app por app_id e placement_id nas configurações do seu servidor de leilão. Veja aqui um exemplo de resultado da consulta:

{
    "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}"
    }]
}

Etapa 2: gerar solicitações ORTB no servidor

Depois de receber a solicitação, o servidor de leilão precisará construir as solicitações de lance para cada uma das fontes de demanda. Este é o ponto de extremidade no app.py para receber a solicitação de leilão:

@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'
)

Em bid_manager.py, a solicitação de leilão no cliente contém o app_id e o placement_id que serão utilizados para procurar as informações completas de posicionamento nas configurações do servidor.

# 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)

Depois em audience_network. py, a função get_bid_request gerará uma solicitação ORTB final para o Audience Network com base em informações completas de posicionamento.

O imp.tagid do campo ORTB detém o identificador do Audience Network para o inventário. O inventário é representado no Audience Network como o ID do posicionamento.

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)

Formatos de anúncios compatíveis

No momento, há quatro tipos de anúncios compatíveis que podem ser solicitados por meio de OpenRTB: em banner, nativo (nativo ou em banner nativo), de vídeo (com incentivo ou vídeo in-stream) e intersticial. Nota: os objetos de banner, nativo e vídeo se excluem mutuamente, mas um deles é necessário.

Veja aqui uma lista dos formatos de anúncio compatíveis na solicitação de lance:

Formato do anúncio Parâmetros da solicitação de lance

Nativo

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

Banner nativo

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

Intersticial

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

Vídeo com incentivo

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

Banner - Altura: 50

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

Banner - Altura: 250

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

Vídeo In-stream

{'id': ${AUCTION_ID}, 'video': { 'h': 0, 'w': 0, 'linearity': 1 }, 'tagid': ${PLACEMENT_ID}}

Etapa 3: executar solicitações ORTB no servidor

Depois que o objeto de solicitação ORTB for criado acima, podemos enviar a solicitação ao ponto de extremidade do Audience Network em https://an.facebook.com /${PLATFORM_ID}/placementbid. ortb usando a solicitação HTTP, post e Content-Type: app/json.

Em bid_manager. py, depois que coletar todas as solicitações de lance para cada plataforma, ele chamará exec_bid_requests para cada plataforma:

# 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))

Os cabeçalhos HTTP a seguir (em lances e não lances) contendo informações úteis para solução de problemas na resposta serão definidos e deverão ser registrados no servidor de leilão:

  • X-FB-AN-Request-ID: o ID da solicitação é necessário para que o Audience Network depure uma solicitação específica. Você deverá capturá-lo sempre que solicitar suporte.
  • X-FB-AN-Errors: uma lista de erros encontrados, que é útil para compreender os motivos para não ter lances.
  • X-FB-Debug: algumas informações de depuração sobre esta solicitação que podem ser enviadas para solução de problemas junto ao seu representante de conta no Audience Network.

Observação: para minimizar a latência, é obrigatório adicionar o cabeçalho X-FB-Pool-Routing-Token à solicitação de lance.

  • X-FB-Pool-Routing-Token: este token é usado para encaminhar a solicitação ao nosso data center mais próximo, e seu valor é o mesmo que user.buyeruid.

Em audience_network. py, a solicitação ORTB será enviada ao Audience Network, e a resposta de lance correspondente será entregue ao servidor de leilão:

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)

Se você fornecer um cabeçalho Content-Encoding:gzip na solicitação, será possível enviar um corpo de solicitação binário e compactado em gzip.

Etapa 4: executar o leilão no servidor

Agora, já temos respostas de lances de diferentes plataformas (rede). Em bid_manager. py, a função get_bid_response será responsável por comparar as respostas de lance preenchidas e decidir qual será o lance mais alto (vencedor).

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

Como o Audience Network é o único licitante no nosso exemplo, o método de execução do leilão apenas compara o lance retornado a algum valor de preço para decidir se ele vence o leilão. Como resultado, se o lance retornado do Audience Network for mais alto que US$ 1, responderemos que o Audience Network venceu o leilão. Caso contrário, trataremos o lance como tendo perdido o leilão.

Etapa 5: disparar notificações de ganho/perda/faturável/tempo-limite

Nós exigimos notificações de ganhos, perdas, passível de cobrança e tempo limite com os códigos de perda apropriados conforme definido no ORTB. O nurl, lurl e burl do ORTB são oferecidos na resposta do lance. Consulte a seção anterior para ver um exemplo de resposta de lance. Caso o lance atinja o tempo limite, ofereceremos uma rota de geração de relatórios alternativa.

Notificação do vencedor

O nurl de vitória será oferecido na resposta do lance. É necessário popular o preço de venda no 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}: Deve ser substituído pelo preço de venda do leilão na mesma unidade do lance (ou seja, em dólares ou CPM).

Notificação de perda

Nossa lurl de perda contém dois sinalizadores que você deve preencher:

"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}: Deve ser substituído pelo código de perda do ORTB.
  • ${AUCTION_PRICE}: Deve ser substituído pelo preço de venda do leilão na mesma unidade do lance (ou seja, em dólares ou CPM).

Veja abaixo uma lista com diferentes códigos de perda e os motivos de perda correspondentes.

Motivo de perdaDescriçãoCódigo de perda ORTB v2.5

Resposta de lance inválida.

O lance é inválido (mas feito a tempo, não é um não lance e é válido o suficiente para extrair o nurl)

3

Tempo limite do lance *

Resposta de lance recebida, mas não a tempo de interromper o leilão

2

Não lance

Não lances são indicados como HTTP 204 (ou seja, sem nurl para chamar), mas você pode interpretar nossa resposta como um não lance (provavelmente um problema de integração). Você também pode solicitar lances para várias impressões, e nós faremos lances em alguns, mas não todos.

9

Não é o licitante RTB mais alto

Outro licitante nos superou, incluindo lances sintéticos (como trocas não RTB) se inseridas no mesmo leilão.

102

O inventário não se materializou

Nosso lance venceu o leilão, mas a impressão não se materializou (por exemplo, a página não era longa o bastante para incluir esse espaço, ou o usuário saiu do aplicativo antes que o anúncio armazenado em cache fosse usado). Nem todos os parceiros podem oferecer isso (é um não evento); por isso, o inferiremos caso ele não seja oferecido.

4902

Enviado para o servidor de anúncios

Envie isso se o último ponto de contato com o processo de decisão estiver enviando nosso lance alto ao servidor de anúncios. A impressão poderá continuar perdida por meio da perda dos itens de linha, do servidor de anúncios se sobrepondo ao leilão ou do inventário não se materializando.

4900

Vencedor do RTB não escolhido pelo servidor de anúncios

Vencemos o leilão do RTB, mas o servidor de anúncios se sobrepôs ao leilão (por exemplo, diretamente).

4903

Vitória

Vencemos a árvore de decisão completa, e a tag foi posicionada na página (Web) ou o objeto de anúncio foi armazenado em ache (aplicativo). Ainda assim, a impressão visualizável pode não resultar.

0

Notificação de passível de cobrança

Nós exigimos uma notificação de passível de cobrança caso um retorno de chamada de impressão seja acionado no SDK do Audience Network. É necessário popular o preço de venda no 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}: Deve ser substituído pelo preço de venda do leilão na mesma unidade do lance (ou seja, em dólares ou CPM).

Notificação de tempo limite

Caso o lance atinja o tempo limite, ofereceremos uma rota de geração de relatórios alternativa. No nurl genérico que pode ser chamado sem a necessidade de esperar pela chegada do lance. O formato é o seguinte:

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

Nota:${PARTNER_FBID}, ${APP_FBID} e ${AUCTION_ID} devem ser preenchidos com os valores adequados. A tabela abaixo oferece uma explicação sobre esses valores.

ParâmetroTipoDescrição

PARTNER_FBID

Int

ID do servidor de leilão de anúncios emitido pelo Facebook. Use o ID do aplicativo aqui caso não tenha um parceiro dedicado de leilão de anúncios.

APP_FBID

Int

ID emitido pelo Facebook do aplicativo ou da empresa que iniciou um leilão.

AUCTION_ID

cadeia de caracteres

ID do leilão gerado pelo cliente que você usou para emitir uma solicitação de lance.

Etapa 6: retornar o ganhador para seu cliente

Depois de executar o leilão, criamos o objeto de resposta e o retornamos ao app do cliente. Veja a seguir o método na amostra em bid_manager. py que cria a resposta final do servidor de leilão:

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,
})

Por fim, nosso servidor de exemplo pode criar esta resposta para o cliente para notificar qual plataforma deverá ser usada:

{
'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
}