개요

구조화된 데이터 파일 (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에는 fileType로 식별된 리소스가 포함됩니다. 이러한 리소스는 filterTypefilterIds로 식별된 리소스 또는 해당 리소스의 하위 요소입니다.

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