總覽

結構化資料檔案 (SDF) 是經過特殊格式化的逗號分隔值 (CSV) 檔案,可用於大量擷取及更新 Display & Video 360 資源的資料。透過 Display & Video 360 API,您可以產生及下載自訂 SDF,並擷取 Display & Video 360 資源的已整理及篩選資料。

本指南說明如何建立 SDF 下載作業、追蹤該作業,以及下載產生的 SDF。

如要瞭解結構化資料檔案格式和版本資訊,請參閱結構化資料檔案參考文件

建立工作

SDF 是由非同步作業 (稱為「sdfdownloadtask」) 產生。建立這項工作時,請定義所需 SDF 的相關參數。這項作業是透過 sdfdownloadtasks.create 方法完成。下列小節說明可設定的參數。

指定版本

結構化資料檔案格式會定期更新,與 Display & Video 360 API 無關,且會發布新版本,並定期淘汰舊版本。因此,一律建議使用者採用最新版本的 SDF

您可以使用要求主體中的 version 欄位,設定所需 SDF 的 SDF 版本。如未設定或設為 SDF_VERSION_UNSPECIFIED,工作會使用廣告主或合作夥伴資源的預設 SDF 版本,做為 SDF 內容的環境。

設定情境

您可以產生包含任何可用資源資料的 SDF,但任何個別 SDF 只能傳回單一合作夥伴或廣告主環境中的內容。這個內容是在要求主體中,透過 partnerIdadvertiserId 欄位定義。必須設定這兩個欄位的其中一個。

只有指定環境中的資源會納入產生的 SDF。如果您嘗試依不屬於指定合作夥伴或廣告主擁有的資源進行篩選,該資源和其下方的內容都不會納入結果。如果只依據這些未納入的資源進行篩選,產生的檔案會是空白。嘗試依指定環境以外的資源進行篩選不會傳回錯誤,因此請務必檢查環境是否正確。

選擇合適的篩選器

除了上述設定的環境外,您還可以指定要產生的檔案類型,以及要納入的特定資源或資源系列,進一步篩選產生的結構化資料檔案範圍。

sdfdownloadtask 提供三種篩選器,分別適用於特定規格類型。您只能為單一 sdfdownloadtask 指派一個。

ParentEntityFilter

ParentEntityFilter 是最廣泛的可用篩選條件。

使用 fileType 欄位,列出要透過工作生成的所有檔案類型。這是必要欄位,如果留空或設為 FILE_TYPE_UNSPECIFIEDsdfdownloadtask 會完成並發生錯誤。

使用 filterTypefilterIds 欄位,可進一步修正結果。filterType 會指定要篩選的資源類型,而 filterIds 則會依據資源的專屬 ID 識別這些資源。產生的 SDF 會包含 fileType 識別的資源,這些資源是 filterTypefilterIds 識別的資源或子項。

IdFilter

IdFilter 會篩選要求,只納入已識別的資源。

IdFilter 包含每個結構化資料檔案類型的欄位,但商品目錄來源除外。每個欄位都是不重複的 ID 清單,可識別您要納入所產生 SDF 的特定資源。提供的 ID 必須位於設定的環境中,但不必直接相關。如要要求廣告活動中的委刊項,不必要求該廣告活動,反之亦然。系統只會產生與 IdFilter 中識別的資源相應的檔案類型。

InventorySourceFilter

InventorySourceFilter 僅允許篩選及下載含有廣告空間來源資源的結構化資料檔案。這是唯一可取得廣告空間來源資源資訊的篩選器。

InventorySourceFilter 具有單一 inventorySourceIds 欄位,可識別要納入 SDF 的廣告空間來源資源專屬 ID。如果提供給 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"])

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 欄位。完成的作業會包含 responseerror 欄位。如果存在,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))

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