개요

구조화된 데이터 파일 (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를 만드는 방법을 보여주는 예입니다.

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"])

2,399필리핀

// 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 값이 있는 객체를 갖게 됩니다.

다음은 지수 백오프를 사용하여 요청을 확인하는 방법의 예입니다.

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

2,399필리핀

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