Обзор

Файлы структурированных данных (SDF) — это файлы со значениями, разделёнными запятыми (CSV), специально отформатированные для массового извлечения и обновления данных о ресурсах Display & Video 360. С помощью API Display & Video 360 вы можете создавать и загружать настраиваемые SDF-файлы, позволяющие извлекать упорядоченные, отфильтрованные данные о ваших ресурсах Display & Video 360.

В этом руководстве описывается, как создать операцию загрузки SDF-файла, отслеживать эту операцию и загружать полученные SDF-файлы.

Информацию о формате SDF и управлении версиями можно найти в справочной документации SDF .

Создать задачу

SDF-файлы генерируются асинхронной операцией, называемой sdfdownloadtask . При создании этой задачи вы определяете параметры желаемых SDF-файлов. Это делается с помощью метода sdfdownloadtasks.create . В следующих подразделах описаны доступные для настройки параметры.

Укажите версию

Формат структурированного файла данных регулярно обновляется независимо от API Display & Video 360: новые версии регулярно выпускаются, а старые версии прекращают поддержку . Поэтому пользователям всегда рекомендуется использовать самую последнюю версию SDF .

Версию SDF-файла нужного вам SDF-файла можно задать с помощью поля version в теле запроса. Если значение не задано или установлено значение SDF_VERSION_UNSPECIFIED , задача будет использовать версию SDF-файла по умолчанию ресурса рекламодателя или партнера, используемого в качестве контекста SDF-контента.

Установите контекст

Вы можете создать SDF-файл, содержащий данные о любых доступных вам ресурсах, но любой отдельный SDF-файл может возвращать контент только в контексте одного партнёра или рекламодателя. Этот контекст определяется в теле запроса полем partnerId или advertiserId . Необходимо указать только одно из этих двух полей.

В результирующий SDF-файл будут включены только ресурсы, относящиеся к заданному контексту. При попытке фильтрации по ресурсу, не принадлежащему указанному партнеру или рекламодателю, ни он сам, ни его содержимое не будут включены в результаты. При фильтрации только по этим невключенным ресурсам полученные файлы будут пустыми. Попытка фильтрации по ресурсам вне заданного контекста не приведет к ошибке , поэтому убедитесь, что ваш контекст указан правильно.

Выберите правильный фильтр

Помимо контекста, заданного выше, вы можете дополнительно фильтровать область создаваемых вами структурированных файлов данных, указав типы файлов, которые вы хотите создать, а также конкретные ресурсы или семейства ресурсов, которые вы хотите включить.

Для задачи sdfdownloadtask доступны три фильтра, каждый из которых соответствует определённому типу спецификации. Для одной задачи sdfdownloadtask можно назначить только один фильтр.

ParentEntityFilter

ParentEntityFilter — самый широкий из доступных фильтров.

В поле fileType можно указать все типы файлов , которые вы хотите создать в рамках своей задачи. Это обязательное поле. Если оставить его пустым или указать значение FILE_TYPE_UNSPECIFIED , задача sdfdownloadtask завершится с ошибкой.

Используя поля filterType и filterIds , вы можете дополнительно уточнить результаты. filterType определяет тип ресурсов для фильтрации, а filterIds идентифицирует эти ресурсы по их уникальным идентификаторам. Результирующие SDF-файлы будут включать ресурсы, определяемые fileType , которые являются либо ресурсами, либо дочерними ресурсами ресурсов, определяемых filterType и filterIds .

IdFilter

IdFilter фильтрует ваш запрос, включая только идентифицированные ресурсы.

IdFilter есть поле для каждого типа SDF, за исключением источника инвентаря. Каждое из этих полей представляет собой список уникальных идентификаторов, идентифицирующих конкретные ресурсы, которые вы хотите включить в сгенерированный SDF. Указанные идентификаторы должны соответствовать заданному контексту, но не обязательно быть напрямую связаны. Вам не нужно запрашивать конкретную кампанию, чтобы запросить содержащуюся в ней позицию, и наоборот. Будут сгенерированы только те типы файлов, которые соответствуют ресурсам, указанным в IdFilter .

Фильтр источника инвентаря

InventorySourceFilter позволяет фильтровать и загружать только SDF-файлы, содержащие ресурсы Inventory Source. Это единственный фильтр, который можно использовать для получения информации о ресурсах Inventory Source.

InventorySourceFilter имеет единственное поле inventorySourceIds , в котором указываются уникальные идентификаторы ресурсов источников инвентаря, которые вы хотите включить в свой SDF. Если список, предоставленный inventorySourceIds , пуст, все источники инвентаря в заданном контексте будут включены в сгенерированный SDF.

Сделать запрос

Узнав параметры желаемого SDF, вы можете составить запрос и создать задачу sdfdownloadtask .

Вот пример того, как создать sdfdownloadtask с использованием ParentEntityFilter :

Ява

// 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());

Питон

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

Проверьте свой запрос и получите путь для загрузки

При создании задачи sdfdownloadtask возвращается объект операции . Эта операция отображает состояние асинхронной операции генерации SDF-файла на момент создания. Вы можете проверить, завершена ли операция и готова ли она к загрузке, или выдала ошибку, с помощью метода sdfdownloadtasks.operations.get .

После завершения возвращаемая операция будет иметь ненулевое поле done . Завершенная операция будет включать либо поле response , либо поле error . Поле error , если оно присутствует, будет содержать объект Status , содержащий код ошибки и сообщение , содержащее подробную информацию о произошедшей ошибке. Поле response , если оно присутствует, будет содержать объект со значением resourceName , идентифицирующим сгенерированный файл для загрузки.

Вот пример того, как проверить ваш запрос с использованием экспоненциальной задержки:

Ява

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());

Питон

# 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']
);