개요

구조화된 데이터 파일 (SDF)은 Display & Video 360 리소스에 관한 데이터를 일괄적으로 검색하고 업데이트하는 데 사용되는 특수 형식의 쉼표로 구분된 값 (CSV) 파일입니다. Display & Video 360 API를 통해 맞춤설정된 SDF를 생성하고 다운로드하여 Display & Video 360 리소스에서 정리되고 필터링된 데이터를 검색할 수 있습니다.

이 가이드에서는 SDF 다운로드 작업을 만들고, 이 작업을 추적하고, 결과 SDF를 다운로드하는 방법을 설명합니다.

SDF 형식 및 버전 관리에 관한 정보는 SDF 참조 문서를 참고하세요.

할 일 만들기

SDF는 sdfdownloadtask라고 하는 비동기 작업에 의해 생성됩니다. 이 태스크를 만들 때 원하는 SDF와 관련된 매개변수를 정의합니다. sdfdownloadtasks.create 메서드를 통해 수행됩니다. 다음 하위 섹션에서는 설정할 수 있는 매개변수를 설명합니다.

버전 지정

구조화된 데이터 파일 형식은 Display & Video 360 API와는 별개로 정기적으로 업데이트되며, 새 버전이 출시되고 이전 버전은 정기적으로 지원 중단됩니다. 따라서 항상 최신 버전의 SDF를 사용하는 것이 좋습니다.

요청 본문의 version 필드를 사용하여 원하는 SDF의 SDF 버전을 설정합니다. 설정하지 않거나 SDF_VERSION_UNSPECIFIED로 설정하면 태스크는 SDF 콘텐츠의 컨텍스트로 사용되는 광고주 또는 파트너 리소스의 기본 SDF 버전을 사용합니다.

컨텍스트 설정

사용 가능한 모든 리소스에 관한 데이터가 포함된 SDF를 생성할 수 있지만 개별 SDF는 단일 파트너 또는 광고주의 컨텍스트 내에서만 콘텐츠를 반환할 수 있습니다. 이 컨텍스트는 요청 본문에서 partnerId 또는 advertiserId 필드로 정의됩니다. 이 두 필드 중 하나는 정확히 하나만 설정해야 합니다.

지정된 컨텍스트 내의 리소스만 결과 SDF에 포함됩니다. 지정된 파트너 또는 광고주가 소유하지 않은 리소스로 필터링하려고 하면 해당 리소스와 그 아래의 콘텐츠가 결과에 포함되지 않습니다. 이러한 포함되지 않은 리소스로만 필터링하면 결과 파일이 비어 있게 됩니다. 지정된 컨텍스트 외부의 리소스로 필터링하려고 해도 오류가 반환되지 않으므로 컨텍스트가 올바른지 확인하세요.

적절한 필터 선택

위에서 설정한 컨텍스트 외에도 생성하려는 파일 유형과 포함하려는 특정 리소스 또는 리소스 패밀리를 지정하여 생성된 구조화된 데이터 파일의 범위를 추가로 필터링할 수 있습니다.

sdfdownloadtask에는 세 가지 필터가 있으며, 각각 특정 사양 유형을 지원합니다. sdfdownloadtask 하나에 하나만 할당할 수 있습니다.

ParentEntityFilter

ParentEntityFilter는 사용 가능한 필터 중 가장 광범위합니다.

fileType 필드를 사용하면 작업으로 생성하려는 모든 파일 형식을 나열할 수 있습니다. 이 필드는 필수 항목이며 비워 두거나 FILE_TYPE_UNSPECIFIED로 설정하면 sdfdownloadtask가 오류로 완료됩니다.

filterTypefilterIds 필드를 사용하여 결과를 더욱 세분화할 수 있습니다. filterType는 필터링할 리소스 유형을 지정하고 filterIds는 고유 ID로 이러한 리소스를 식별합니다. 결과 SDF에는 filterTypefilterIds로 식별된 리소스의 리소스 또는 하위 요소인 fileType로 식별된 리소스가 포함됩니다.

IdFilter

IdFilter: 식별된 리소스만 포함하도록 요청을 필터링합니다.

IdFilter에는 인벤토리 소스를 제외한 모든 SDF 유형의 필드가 있습니다. 이러한 각 필드는 생성된 SDF에 포함할 특정 리소스를 식별하는 고유 ID 목록입니다. 제공된 ID는 컨텍스트 세트 내에 있어야 하지만 직접적으로 관련이 있을 필요는 없습니다. 특정 캠페인을 포함하는 광고 항목을 요청하기 위해 해당 캠페인을 요청할 필요는 없으며 그 반대의 경우도 마찬가지입니다. 생성되는 파일 유형은 IdFilter에 식별된 리소스에 해당하는 유형만 됩니다.

InventorySourceFilter

InventorySourceFilter에서는 인벤토리 소스 리소스가 포함된 SDF의 필터링 및 다운로드만 허용됩니다. 인벤토리 소스 리소스에 대한 정보를 가져오는 데 사용할 수 있는 유일한 필터입니다.

InventorySourceFilter에는 SDF에 포함할 인벤토리 소스 리소스의 고유 ID를 식별하는 단일 inventorySourceIds 필드가 있습니다. inventorySourceIds에 제공된 목록이 비어 있으면 설정된 컨텍스트 아래의 모든 인벤토리 소스가 생성된 SDF에 포함됩니다.

요청하기

원하는 SDF의 매개변수를 알면 요청을 구성하고 sdfdownloadtask를 만들 수 있습니다.

다음은 ParentEntityFilter를 사용하여 sdfdownloadtask를 만드는 방법의 예입니다.

자바

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

요청 확인 및 다운로드 경로 가져오기

sdfdownloadtask를 만들면 작업 객체가 반환됩니다. 이 작업은 생성 시 비동기 SDF 생성 작업의 상태를 나타냅니다. sdfdownloadtasks.operations.get 메서드를 사용하여 작업이 완료되어 다운로드할 준비가 되었는지 또는 오류가 발생했는지 확인할 수 있습니다.

완료되면 반환된 작업에 null이 아닌 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());

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