結構化資料檔案 (SDF) 是經過特殊格式化的半形逗號分隔值 (CSV) 檔案,可用於大量擷取及更新 Display & Video 360 資源的資料。您可以透過 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
就會完成錯誤。
您可以使用 filterType
和 filterIds
欄位進一步調整結果。filterType
可指定要篩選的資源類型,而 filterIds
則會根據專屬 ID 識別這些資源。產生的 SDF 會包含 fileType
所識別的資源,這些資源可能是 filterType
和 filterIds
所識別的資源或子項。
IdFilter
IdFilter
會篩選您的要求,只包含已識別的資源。
IdFilter
有每種 SDF 類型的欄位,但不包含商品目錄來源。每個欄位都是一組專屬 ID 清單,用於識別您要在產生的 SDF 中納入的特定資源。提供的 ID 必須位於內容組合中,但不必直接相關。您不必要求特定廣告活動,即可要求其中包含的委刊項,反之亦然。系統只會產生與 IdFilter
中所識別的資源相對應的檔案類型。
InventorySourceFilter
InventorySourceFilter
只允許篩選及下載含有廣告空間來源資源的 SDF。這是唯一可用於取得廣告空間來源資源資訊的篩選器。
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
時,系統會傳回 operation 物件。這項作業代表非同步 SDF 產生作業在建立時的狀態。您可以使用 sdfdownloadtasks.operations.get
方法,檢查作業是否已完成並可供下載,或是發生錯誤。
完成後,傳回的作業會具有非空值的 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))
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'] );