Обзор

Файлы структурированных данных (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 .

РодительскийEntityFilter

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

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

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

ИдФильтер

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

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

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

InventorySourceFilter позволяет фильтровать и загружать только файлы SDF, содержащие ресурсы 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']
);