스크립트 기반 알고리즘은 기본 Python 문법을 사용하는 스크립트로 정의됩니다. 텍스트 파일을 통해 스크립트를 Display & Video 360에 업로드합니다.
규칙 기반 알고리즘을 사용하는 경우 규칙 업로드 페이지로 이동합니다.
스크립트 작성
스크립트 기반 맞춤 입찰 알고리즘은 사용자가 제공한 스크립트를 사용하여 노출의 가치를 평가합니다. 샘플 스크립트 및 필드 목록은 Display & Video 360 고객센터를 참고하세요.
Display & Video 360 UI에서 스크립트를 실행하여 실적을 테스트할 수 있습니다. 샘플링된 노출의 점수 분포를 제공합니다.
스크립트를 TXT 파일로 로컬에 저장합니다.
스크립트 참조 객체 생성
참조 객체는 업로드된 파일을 스크립트와 연결하는 데 사용됩니다. uploadScript 요청을 사용하여 algorithm 아래에 참조 객체를 생성합니다.
스크립트 참조 객체를 생성하는 방법은 다음과 같습니다.
자바
// Provide the ID of the advertiser that owns the algorithm. long advertiserId = advertiser-id; // Provide the ID of the algorithm. long customBiddingAlgorithmId = algorithm-id; // Generate the custom bidding script reference object. CustomBiddingScriptRef response = service .customBiddingAlgorithms() .uploadScript(customBiddingAlgorithmId) .setAdvertiserId(advertiserId) .execute(); // Display the generated resource path. System.out.printf( "The generated script reference object provided the following resource path: %s.", response.getResourceName());
Python
# Provide the ID of the advertiser that owns the algorithm. advertiser_id = advertiser-id # Provide the ID of the algorithm. algorithm_id = algorithm-id # Generate a script reference object under the algorithm. custom_bidding_script_ref = ( service.customBiddingAlgorithms() .uploadScript( customBiddingAlgorithmId=algorithm_id, advertiserId=advertiser_id ) .execute() ) # Print the resource path provided in the generated script reference object. print( "The generated script reference object provided the following resource" " path: " f'{custom_bidding_script_ref["resourceName"]}.' )
PHP
// Provide the ID of the advertiser that owns the algorithm. $advertiserId = advertiser-id; // Provide the ID of the algorithm. $algorithmId = algorithm-id; $uploadScriptOptParams = array( 'advertiserId' => $advertiserId ); try { // Retrieve a usable custom bidding script reference. $scriptRefResponse = $this->service->customBiddingAlgorithms->uploadScript( $customBiddingAlgorithmId, $uploadScriptOptParams ); } catch (\Exception $e) { $this->renderError($e); return; } // Print the retrieved resource path. printf( '<p>The generated script reference object provided the following ' . 'resource path: %s</p>', $scriptRefResponse->getResourceName() );
스크립트 파일 업로드
미디어 upload 요청을 사용하여 스크립트 파일을 참조 객체의 리소스 경로에 업로드합니다. 쿼리 매개변수 uploadType=media를 사용하여 간단한 업로드를 사용합니다.
스크립트 파일을 업로드하는 방법은 다음과 같습니다.
자바
// Provide the local path to the script file to upload. String scriptPath = script-path; // Provide the resource path to upload the script file to. String resourcePath = resource-path; // Create media object. GoogleBytestreamMedia media = new GoogleBytestreamMedia(); media.setResourceName(resourcePath); // Create input stream for the script file. InputStreamContent scriptFileStream = new InputStreamContent(null, new FileInputStream(scriptPath)); // Create media.upload request. Media.Upload uploadRequest = service.media().upload(resourcePath, media, scriptFileStream); // Retrieve uploader from the request and set it to us a simple upload // request. MediaHttpUploader uploader = uploadRequest.getMediaHttpUploader(); uploader.setDirectUploadEnabled(true); // Execute the upload using an Upload URL with the destination resource // name. uploader.upload( new GenericUrl("https://displayvideo.googleapis.com/upload/media/" + resourcePath));
Python
# Import HTTP objects used for file upload. from apiclient.http import HttpRequest from apiclient.http import MediaFileUpload # Provide the local path to the script file to upload. script_path = script-path # Provide the resource path to upload the script file to. resource_path = resource-path # Create a media upload object. media = MediaFileUpload(script_path) # Create upload request. upload_request = service.media().upload( resourceName=resource_path, media_body=media ) # Override response handler to expect null response. upload_request.postproc = HttpRequest.null_postproc # Upload script to given resource path. upload_request.execute()
PHP
// Provide the local path to the script file to upload. $scriptPath = script-path; // Provide the resource path to upload the script file to. $resourcePath = resource-path; // Create the media body. $mediaBody = new Google_Service_DisplayVideo_GoogleBytestreamMedia(); $mediaBody->setResourceName($resourceName); // Build params array for the upload request. $mediaUploadOptParams = array( 'data' => file_get_contents($scriptPath), 'uploadType' => 'media', 'resourceName' => $resourceName ); try { // Call the API, uploading the script file to Display & Video 360. $this->service->media->upload( $resourceName, $mediaBody, $mediaUploadOptParams ); } catch (\Exception $e) { $this->renderError($e); }
스크립트 객체 만들기
create 요청을 사용하여 algorithm 아래에 스크립트 객체를 만듭니다.
스크립트 파일에 구문 오류가 있으면 create 요청이 실패합니다. 응답에는 오류에 관한 세부정보가 포함됩니다. 스크립트를 수정하고 새 참조 객체를 생성하여 프로세스를 다시 시작합니다.
스크립트 객체를 만드는 방법은 다음과 같습니다.
자바
// Provide the ID of the advertiser that owns the parent algorithm. long advertiserId = advertiser-id; // Provide the ID of the parent algorithm. long algorithmId = algorithm-id; // Provide the resource path the script file was uploaded to. String resourcePath = resource-path; // Create the custom bidding script structure. CustomBiddingScript customBiddingScript = new CustomBiddingScript() .setScript(new CustomBiddingScriptRef().setResourceName(resourcePath)); // Create the custom bidding script. CustomBiddingScript response = service .customBiddingAlgorithms() .scripts() .create(customBiddingAlgorithmId, customBiddingScript) .setAdvertiserId(advertiserId) .execute(); // Print ID of new custom bidding script. System.out.printf("Script was created with ID %s.", response.getCustomBiddingScriptId());
Python
# Provide the ID of the advertiser that owns the parent algorithm. advertiser_id = advertiser-id # Provide the ID of the parent algorithm. algorithm_id = algorithm-id # Provide the resource path the script file was uploaded to. resource_path = resource-path # Build script object. script_obj = {"script": {"resourceName": resource_path}} # Build and execute request. script_response = ( service.customBiddingAlgorithms() .scripts() .create( customBiddingAlgorithmId=algorithm_id, advertiserId=advertiser_id, body=script_obj, ) .execute() ) # Print ID of new custom bidding algorithm. print( f'Script was created with ID {script_response["customBiddingScriptId"]}.' )
PHP
// Provide the ID of the advertiser that owns the parent algorithm. $advertiserId = advertiser-id; // Provide the ID of the parent algorithm. $algorithmId = algorithm-id; // Provide the resource path the script file was uploaded to. $resourcePath = resource-path; // Build Script object. $customBiddingScript = new Google_Service_DisplayVideo_CustomBiddingScript(); $scriptRef = new Google_Service_DisplayVideo_CustomBiddingScriptRef(); $scriptRef->setResourceName($resourcePath); $customBiddingScript->setScript($scriptRef); $createScriptOptParams = array( 'advertiserId' => $advertiserId ); // Call the API, creating the custom bidding script using the script // file and under the advertiser and custom bidding algorithm given. try { $result = $this->service->customBiddingAlgorithms_scripts->create( $customBiddingAlgorithmId, $algorithmId, $createScriptOptParams ); } catch (\Exception $e) { $this->renderError($e); return; } // Print ID of new custom bidding script. printf('<p>Script was created with ID %s.</p>', $result['customBiddingScriptId']);
스크립트 상태 폴링
Display & Video 360에서는 스크립트가 생성된 후 스크립트를 처리합니다. 그런 다음 Display & Video 360에서 스크립트를 수락하여 노출을 점수화하거나 거부합니다.
스크립트를 만든 후에는 스크립트가 승인되었는지 확인합니다. 결과로 생성된 스크립트의 state 필드를 확인합니다.
PENDING이면 스크립트를 계속 폴링합니다.ACCEPTED인 경우 스크립트가 유효합니다. 알고리즘이 준비되었는지 확인으로 계속 진행합니다.REJECTED인 경우 스크립트에 오류가 있습니다.errors필드에서 검색하여 스크립트에서 발견된 특정 오류 목록을 가져옵니다. 오류를 해결하고 수정된 스크립트 파일을 업로드하기 위해 새 스크립트 참조 객체를 생성하여 이 프로세스를 다시 시작합니다.
지수 백오프를 사용하여 스크립트 상태를 폴링하는 방법은 다음과 같습니다.
자바
// Provide the ID of the advertiser that owns the parent algorithm. long advertiserId = advertiser-id; // Provide the ID of the parent algorithm. long algorithmId = algorithm-id; // Provide the ID of the script. long scriptId = script-id; // Configure the Operations.get request. Scripts.Get scriptRequest = service .customBiddingAlgorithms() .scripts() .get(algorithmId, scriptId) .setAdvertiserId(advertiserId); // 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(); long backoffMillis = 0; CustomBiddingScript script = null; do { // Sleep before retrieving operation again. Thread.sleep(backoffMillis); // Retrieve script. script = scriptRequest.execute(); // If operation is not done, calculate next sleep period. if (script.getState() == null || script.getState().equals("PENDING")) { backoffMillis = backOff.nextBackOffMillis(); if (backoffMillis == ExponentialBackOff.STOP) { System.out.printf("Polling deadline exceeded.%n"); break; } System.out.printf( "Script with ID %s is still pending, sleeping for %s milliseconds.%n", scriptId, backoffMillis); } } while (script.getState() == null || script.getState().equals("PENDING")); // Check whether operation finished with an error, or is completed and ready to download. if (script.getState().equals("ACCEPTED")) { System.out.printf("Script with ID %s has been accepted.%n", scriptId); } else { System.out.printf("Script with ID %s has been rejected.%n", scriptId); if (script.getErrors() != null && script.getErrors().size() > 0) { System.out.println("The following errors were identified:"); for (ScriptError error : script.getErrors()) { System.out.printf( "Line %s, Column %s (%s): %s%n", error.getLine(), error.getColumn(), error.getErrorCode(), error.getErrorMessage()); } } else { System.out.println("No specific errors were identified."); } }
Python
# Provide the ID of the advertiser that owns the parent algorithm. advertiser_id = advertiser-id # Provide the ID of the parent algorithm. algorithm_id = algorithm-id # Provide the ID of the script. script_id = script-id # Set the following values that control retry behavior while the script is # being processed. # 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 # Generate the next sleep interval using exponential backoff logic. 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)) # Configure the script GET request. get_request = ( service.customBiddingAlgorithms() .scripts() .get( customBiddingAlgorithmId=algorithm_id, customBiddingScriptId=script_id, advertiserId=advertiser_id, ) ) # Poll the script until the script is finished being processed or the max # time has fully elapsed. sleep = 0 start_time = time.time() while True: # Get current status of the script. script = get_request.execute() # Check whether script was accepted or rejected and print any relevant # errors. if script["state"] == "ACCEPTED": print(f"Script with ID {script_id} has been accepted.") break elif script["state"] == "REJECTED": print(f"Script with ID {script_id} has been rejected.") if "errors" in script and len(script["errors"]) > 0: print("The following errors were identified:") for err in script["errors"]: print( f'Line {err["line"]}, Column' f' {err["column"]} ({err["errorCode"]}): {err["errorMessage"]}' ) else: print("No specific errors were identified.") break elif time.time() - start_time > max_retry_elapsed_time: print("Polling deadline exceeded.") break sleep = next_sleep_interval(sleep) print( f"Script with ID {script_id} is still pending, sleeping for" f" {sleep} seconds." ) time.sleep(sleep)
PHP
// Provide the ID of the advertiser that owns the parent algorithm. $advertiserId = advertiser-id; // Provide the ID of the parent algorithm. $algorithmId = algorithm-id; // Provide the ID of the script. $scriptId = script-id; // 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; $sleep = 0; $startTime = time(); $getScriptOptParams = array( 'advertiserId' => $advertiserId ); do { try { // Call the API, retrieving the script. $script = $this->service->customBiddingAlgorithms_scripts->get( $algorithmId, $scriptId, $getScriptOptParams ); } catch (\Exception $e) { $this->renderError($e); return; } if ($script->getState() == "ACCEPTED") { printf("<p>Script with ID %s has been accepted.</p>", $scriptId); break; } elseif ($script->getState() == "REJECTED") { printf("Script with ID %s has been rejected.", $scriptId); if ($script->getErrors() !== null) { print("<p>The following errors were identified:</p><ul>"); $errors = $script->getErrors(); foreach ($errors as $error) { printf( "<li>Line %s, Column %s (%s): %s</li>", $error->getLine(), $error->getColumn(), $error->getErrorCode(), $error->getErrorMessage()); } print("</ul>"); } else { print("<p>No specific errors were identified.</p>"); } break; } elseif (time() - $startTime > $maxRetryElapsedTime) { print '<p>Script polling deadline exceeded.</p>'; break; } // Generate next sleep interval. $minInterval = max($minRetryInterval, $sleep); $maxInterval = max( $minRetryInterval, $sleep * 3 ); $sleep = min($maxRetryInterval, rand($minInterval, $maxInterval)); printf( '<p>Script with ID %s is still pending, sleeping for %d seconds</p>', $scriptId, $sleep ); sleep($sleep); } while (true);