Visão geral

Os arquivos de dados estruturados (SDFs) são arquivos de valores separados por vírgula (CSV) com formatação especial usados para recuperar e atualizar dados sobre recursos do Display & Video 360 em massa. Com a API Display & Video 360, é possível gerar e baixar SDFs personalizados, permitindo recuperar dados organizados e filtrados sobre seus recursos do Display & Video 360.

Este guia descreve como criar uma operação de download do SDF, acompanhar essa operação e baixar os SDFs resultantes.

Informações sobre o formato e o controle de versão do SDF podem ser encontradas na documentação de referência do SDF.

Criar uma tarefa

Os SDFs são gerados por uma operação assíncrona, chamada de sdfdownloadtask. Ao criar essa tarefa, você define os parâmetros relacionados aos SDFs desejados. Isso é feito com o método sdfdownloadtasks.create. As subseções a seguir descrevem os parâmetros que podem ser definidos.

Especificar uma versão

O formato de arquivo de dados estruturados é atualizado regularmente, de forma independente da API Display & Video 360. Novas versões são lançadas e as anteriores são descontinuadas regularmente. Por isso, recomendamos sempre que os usuários usem a versão mais recente do SDF.

Defina a versão do SDF desejada usando o campo version no corpo da solicitação. Se não estiver definido ou estiver definido como SDF_VERSION_UNSPECIFIED, a tarefa vai usar a versão padrão do SDF do recurso de anunciante ou parceiro usado como contexto do conteúdo do SDF.

Definir o contexto

É possível gerar um SDF com dados sobre qualquer recurso disponível, mas cada SDF individual só pode retornar conteúdo no contexto de um único parceiro ou anunciante. Esse contexto é definido no corpo da solicitação pelo campo partnerId ou advertiserId. Exatamente um desses dois campos precisa ser definido.

Somente os recursos no contexto especificado serão incluídos no SDF resultante. Se você tentar filtrar por um recurso que não pertence ao parceiro ou anunciante especificado, nem ele nem o conteúdo abaixo dele serão incluídos nos resultados. Se você filtrar apenas por esses recursos não incluídos, os arquivos resultantes vão ficar vazios. Tentar filtrar por recursos fora do contexto especificado não vai retornar um erro. Portanto, verifique se o contexto está correto.

Escolher o filtro certo

Além do contexto definido acima, é possível filtrar ainda mais o escopo dos arquivos de dados estruturados gerados especificando os tipos de arquivo que você quer gerar e os recursos ou família de recursos específicos que você quer incluir.

Há três filtros disponíveis para um sdfdownloadtask, cada um atendendo a um tipo de especificação específico. Só é possível atribuir um para um único sdfdownloadtask.

ParentEntityFilter

ParentEntityFilter é o mais amplo dos filtros disponíveis.

Usando o campo fileType, é possível listar todos os tipos de arquivo desejados que você quer gerar com sua tarefa. Esse campo é obrigatório. Se ficar em branco ou for definido como FILE_TYPE_UNSPECIFIED, o sdfdownloadtask será concluído com um erro.

Usando os campos filterType e filterIds, é possível refinar ainda mais os resultados. filterType especifica o tipo de recursos a serem filtrados, e filterIds identifica esses recursos pelo ID exclusivo deles. Os SDFs resultantes vão incluir os recursos identificados por fileType que são os recursos ou filhos dos recursos identificados por filterType e filterIds.

IdFilter

IdFilter filtra sua solicitação para incluir apenas os recursos identificados.

IdFilter tem um campo para cada tipo de SDF, exceto a origem do inventário. Cada um desses campos é uma lista de IDs exclusivos que identificam os recursos específicos que você quer incluir no SDF gerado. Os IDs fornecidos precisam estar dentro do conjunto de contexto, mas não precisam estar diretamente relacionados. Não é necessário solicitar uma campanha específica para pedir um item de linha que ela contém, e vice-versa. Os únicos tipos de arquivos gerados serão aqueles correspondentes aos recursos identificados no IdFilter.

InventorySourceFilter

O InventorySourceFilter permite apenas a filtragem e o download de SDFs que contêm recursos de origem de inventário. É o único filtro que você pode usar para acessar informações sobre seus recursos de origem do inventário.

InventorySourceFilter tem um campo inventorySourceIds singular em que você identifica os IDs exclusivos dos recursos de origem do inventário que quer incluir no SDF. Se a lista fornecida a inventorySourceIds estiver vazia, todas as origens de inventário no contexto definido serão incluídas no SDF gerado.

Fazer uma solicitação

Depois de conhecer os parâmetros do SDF desejado, você pode criar a solicitação e o sdfdownloadtask.

Confira um exemplo de como criar um sdfdownloadtask usando um ParentEntityFilter:

Java

// Create the filter structure
ParentEntityFilter parentEntityFilter = new ParentEntityFilter();
parentEntityFilter.setFileType(sdf-file-type-list);
parentEntityFilter.setFilterType(sdfFilterType);
parentEntityFilter.setFilterIds(filter-id-list);

// Configure the sdfdownloadtasks.create request
Sdfdownloadtasks.Create request =
   service
       .sdfdownloadtasks()
       .create(
           new CreateSdfDownloadTaskRequest()
               .setVersion(sdfVersion)
               .setAdvertiserId(advertiserId)
               .setParentEntityFilter(parentEntityFilter)
       );

// Create the sdfdownloadtask
Operation operationResponse = request.execute();

System.out.printf("Operation %s was created.\n",
   operationResponse.getName());

Python

# Configure the sdfdownloadtasks.create request
createSdfDownloadTaskRequest = {
    'version': sdf-version,
    'advertiserId': advertiser-id,
    'parentEntityFilter': {
        'fileType': sdf-file-type-list,
        'filterType': sdf-filter-type,
        'filterIds': filter-id-list
    }
}

# Create the sdfdownloadtask
operation = service.sdfdownloadtasks().create(
    body=createSdfDownloadTaskRequest).execute();

print("Operation %s was created." % operation["name"])

PHP

// Create the sdfdownloadtasks.create request structure
$createSdfDownloadTaskRequest =
    new Google_Service_DisplayVideo_CreateSdfDownloadTaskRequest();
$createSdfDownloadTaskRequest->setAdvertiserId(advertiser-id);
$createSdfDownloadTaskRequest->setVersion(sdf-version);

// Create and set the parent entity filter
$parentEntityFilter = new Google_Service_DisplayVideo_ParentEntityFilter();
$parentEntityFilter->setFileType(sdf-file-type-list);
$parentEntityFilter->setFilterType(sdf-filter-type);
if (!empty(filter-id-list)) {
    $parentEntityFilter->setFilterIds(filter-id-list);
}
$createSdfDownloadTaskRequest->setParentEntityFilter($parentEntityFilter);

// Call the API, creating the SDF Download Task.
$operation = $this->service->sdfdownloadtasks->create(
    $createSdfDownloadTaskRequest
);

printf('Operation %s was created.\n', $operation->getName());

Verificar sua solicitação e receber o caminho de download

Ao criar um sdfdownloadtask, um objeto operation é retornado. Essa operação representa o status da sua operação assíncrona de geração de SDF no momento da criação. Você pode verificar se a operação foi concluída e está pronta para download ou se gerou um erro usando o método sdfdownloadtasks.operations.get.

Ao terminar, a operação retornada terá um campo done não nulo. A operação concluída vai incluir um campo response ou error. Se presente, o campo error terá um objeto Status contendo um código de erro e uma mensagem, que fornece detalhes do erro ocorrido. Se o campo response estiver presente, ele terá um objeto com um valor resourceName que identifica o arquivo gerado para download.

Confira um exemplo de como verificar sua solicitação usando a espera exponencial:

Java

String operationName = operationResponse.getName();

// Configure the Operations.get request
Sdfdownloadtasks.Operations.Get operationRequest =
   service
       .sdfdownloadtasks()
       .operations()
       .get(operationName);

// Configure exponential backoff for checking the status of our operation
ExponentialBackOff backOff = new ExponentialBackOff.Builder()
   .setInitialIntervalMillis(5000) // setting initial interval to five seconds
   .setMaxIntervalMillis(300000)  // setting max interval to five minutes
   .setMaxElapsedTimeMillis(18000000) // setting max elapsed time to five hours
   .build();

while (operationResponse.getDone() == null) {
 long backoffMillis = backOff.nextBackOffMillis();
 if (backoffMillis == ExponentialBackOff.STOP) {
   System.out.printf("The operation has taken more than five hours to
       complete.\n");
   return;
 }
 Thread.sleep(backoffMillis);

 // Get current status of operation
 operationResponse = operationRequest.execute();
}

// Check if the operation finished with an error and return
if (operationResponse.getError() != null) {
 System.out.printf("The operation finished in error with code %s: %s\n",
     operationResponse.getError().getCode(), operationResponse.getError()
         .getMessage());
 return;
}

System.out.printf(
    "The operation completed successfully. Resource %s was created.\n",
    operationResponse.getResponse().get("resourceName").toString());

Python

# The following values control retry behavior while
# the report is processing.
# Minimum amount of time between polling requests. Defaults to 5 seconds.
min_retry_interval = 5
# Maximum amount of time between polling requests. Defaults to 5 minutes.
max_retry_interval = 5 * 60
# Maximum amount of time to spend polling. Defaults to 5 hours.
max_retry_elapsed_time = 5 * 60 * 60

# Configure the Operations.get request
get_request = service.sdfdownloadtasks().operations().get(
  name=operation["name"]
)

sleep = 0
start_time = time.time()
while True:
  # Get current status of operation
  operation = get_request.execute()

  if "done" in operation:
    if "error" in operation:
      print("The operation finished in error with code %s: %s" % (
            operation["error"]["code"],
            operation["error"]["message"]))
    else:
      print("The operation completed successfully. Resource %s was created."
            % operation["response"]["resourceName"])
    break
  elif time.time() - start_time > max_retry_elapsed_time:
    print("Generation deadline exceeded.")

  sleep = next_sleep_interval(sleep)
  print("Operation still running, sleeping for %d seconds." % sleep)
  time.sleep(sleep)

def next_sleep_interval(previous_sleep_interval):
  """Calculates the next sleep interval based on the previous."""
  min_interval = previous_sleep_interval or min_retry_interval
  max_interval = previous_sleep_interval * 3 or min_retry_interval
  return min(max_retry_interval, random.randint(min_interval, max_interval))

PHP

// The following values control retry behavior
// while the task is processing.
// Minimum amount of time between polling requests. Defaults to 5 seconds.
$minRetryInterval = 5;
// Maximum amount of time between polling requests. Defaults to 5 minutes.
$maxRetryInterval = 300;
// Maximum amount of time to spend polling. Defaults to 5 hours.
$maxRetryElapsedTime = 18000;

$operationName = $operation->getName();

$sleepInterval = 0;
$startTime = time();

while (!$operation->getDone()) {
    if ($sleepInterval != 0) {
        printf(
            'The operation is still running, sleeping for %d seconds\n',
            $sleepInterval
        );
    }

    // Sleep before retrieving the SDF Download Task again.
    sleep($sleepInterval);

    // Call the API, retrieving the SDF Download Task.
    $operation = $this->service->sdfdownloadtasks_operations->get(
        $operation->getName()
    );

    // If the operation has exceeded the set deadline, throw an exception.
    if (time() - $startTime > $maxRetryElapsedTime) {
        printf('SDF download task processing deadline exceeded\n');
        throw new Exception(
            'Long-running operation processing deadline exceeded'
        );
    }

    // Generate the next sleep interval using exponential backoff logic.
    $sleepInterval = min(
        $maxRetryInterval,
        rand(
            max($minRetryInterval, $previousSleepInterval),
            max($minRetryInterval, $previousSleepInterval * 3)
        )
    );
}

// If the operation finished with an error, throw an exception.
if($operation->getError() !== null) {
    $error = $operation->getError();
    printf(
        'The operation finished in error with code %s: %s\n',
        $error->getCode(),
        $error->getMessage()
    );
    throw new Exception($error->getMessage());
}

// Print successfully generated resource.
$response = $operation->getResponse();
printf(
    'The operation completed successfully. Resource %s was '
        . 'created. Ready to download.\n',
    $response['resourceName']
);