Usage flow

The steps for using batch processing are as follows:

Create a new batch job

To create a BatchJob resource, call MutateBatchJob .

Java

 private 
  
 String 
  
 createBatchJob 
 ( 
 BatchJobServiceClient 
  
 batchJobServiceClient 
 , 
  
 long 
  
 customerId 
 ) 
  
 { 
  
 BatchJobOperation 
  
 operation 
  
 = 
  
 BatchJobOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 BatchJob 
 . 
 newBuilder 
 (). 
 build 
 ()). 
 build 
 (); 
  
 String 
  
 batchJobResourceName 
  
 = 
  
 batchJobServiceClient 
  
 . 
 mutateBatchJob 
 ( 
 Long 
 . 
 toString 
 ( 
 customerId 
 ), 
  
 operation 
 ) 
  
 . 
 getResult 
 () 
  
 . 
 getResourceName 
 (); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Created a mutate job with resource name: '%s'.%n" 
 , 
  
 batchJobResourceName 
 ); 
  
 return 
  
 batchJobResourceName 
 ; 
 } 
  
  

C#

 private 
  
 static 
  
 string 
  
 CreateBatchJob 
 ( 
 BatchJobServiceClient 
  
 batchJobService 
 , 
  
 long 
  
 customerId 
 ) 
 { 
  
 BatchJobOperation 
  
 operation 
  
 = 
  
 new 
  
 BatchJobOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 new 
  
 BatchJob 
 () 
  
 { 
  
 } 
  
 }; 
  
 string 
  
 batchJobResourceName 
  
 = 
  
 batchJobService 
 . 
 MutateBatchJob 
 ( 
 customerId 
 . 
 ToString 
 (), 
  
 operation 
 ) 
  
 . 
 Result 
 . 
 ResourceName 
 ; 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Created a batch job with resource name: " 
  
 + 
  
 $"'{batchJobResourceName}'." 
 ); 
  
 return 
  
 batchJobResourceName 
 ; 
 } 
  
  

PHP

 private static function createBatchJob( 
 BatchJobServiceClient $batchJobServiceClient, 
 int $customerId 
 ): string { 
 // Creates a batch job operation to create a new batch job. 
 $batchJobOperation = new BatchJobOperation(); 
 $batchJobOperation->setCreate(new BatchJob()); 
 // Issues a request to the API and get the batch job's resource name. 
 $batchJobResourceName = $batchJobServiceClient->mutateBatchJob( 
 MutateBatchJobRequest::build($customerId, $batchJobOperation) 
 )->getResult()->getResourceName(); 
 printf( 
 "Created a batch job with resource name: '%s'.%s", 
 $batchJobResourceName, 
 PHP_EOL 
 ); 
 return $batchJobResourceName; 
 }  
 

Python

 def 
  
 create_batch_job 
 ( 
 batch_job_service 
 : 
 BatchJobServiceClient 
 , 
 customer_id 
 : 
 str 
 , 
 batch_job_operation 
 : 
 BatchJobOperation 
 , 
 ) 
 - 
> str 
 : 
  
 """Creates a batch job for the specified customer ID. 
 Args: 
 batch_job_service: an instance of the BatchJobService message class. 
 customer_id: a str of a customer ID. 
 batch_job_operation: a BatchJobOperation instance set to "create" 
 Returns: a str of a resource name for a batch job. 
 """ 
 try 
 : 
 response 
 : 
 MutateBatchJobResponse 
 = 
 batch_job_service 
 . 
 mutate_batch_job 
 ( 
 customer_id 
 = 
 customer_id 
 , 
 operation 
 = 
 batch_job_operation 
 ) 
 resource_name 
 : 
 str 
 = 
 response 
 . 
 result 
 . 
 resource_name 
 print 
 ( 
 f 
 'Created a batch job with resource name " 
 { 
 resource_name 
 } 
 "' 
 ) 
 return 
 resource_name 
 except 
 GoogleAdsException 
 as 
 exception 
 : 
 handle_googleads_exception 
 ( 
 exception 
 ) 
 # This line will likely not be reached due to sys.exit(1) in handle_googleads_exception 
 # but to satisfy the type checker, we add a return statement. 
 return 
 "" 
 # Or raise an exception  
 

Ruby

 def 
  
 create_batch_job 
 ( 
 client 
 , 
  
 batch_job_service 
 , 
  
 customer_id 
 ) 
  
 # Creates a batch job operation to create a new batch job. 
  
 operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 batch_job 
  
 # Issues a request to the API and get the batch job's resource name. 
  
 response 
  
 = 
  
 batch_job_service 
 . 
 mutate_batch_job 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 operation 
 : 
  
 operation 
  
 ) 
  
 batch_job_resource_name 
  
 = 
  
 response 
 . 
 result 
 . 
 resource_name 
  
 puts 
  
 "Created a batch job with resource name: ' 
 #{ 
 batch_job_resource_name 
 } 
 '" 
  
 batch_job_resource_name 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 create_batch_job 
  
 { 
  
 my 
  
 ( 
 $batch_job_service 
 , 
  
 $customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Create a batch job operation. 
  
 my 
  
 $batch_job_operation 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::BatchJobService:: 
 BatchJobOperation 
 - 
>  
 new 
 ({ 
 create 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 BatchJob 
 - 
> new 
 ({})}); 
  
 my 
  
 $batch_job_resource_name 
  
 = 
  
 $batch_job_service 
 - 
> mutate 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 operation 
  
 = 
>  
 $batch_job_operation 
  
 }) 
 - 
> { 
 result 
 }{ 
 resourceName 
 }; 
  
 printf 
  
 "Created a batch job with resource name: '%s'.\n" 
 , 
  
 $batch_job_resource_name 
 ; 
  
 return 
  
 $batch_job_resource_name 
 ; 
 } 
  
  

curl

 # 
Creates  
a  
batch  
job. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. curl -f --request POST \ 
 "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/batchJobs:mutate" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ 
 --data @- <<EOF 
 { 
 "operation": { 
 "create": {} 
 } 
 } 
 EOF  
 
  

At this point in the process, the status of the job is PENDING .

Add one or more mutate operations to the batch job

Add one or more MutateOperation to the batch job created in the previous step by calling AddBatchJobOperations . The response then contains the following:

  • Total number of operations added so far for this job
  • Sequence token to be used when calling this method to add more operations

When you call AddBatchJobOperations again to add more operations, ensure you specify the previously obtained sequence token in the sequence_token field of a request . If you call the method using any sequence token other than the previously obtained one, it results in an error.

sequence_token is also available as next_add_sequence_token of BatchJob , which you can retrieve later.

If you're creating dependent objects such as a complete campaign consisting of a new campaign and corresponding ad groups, ads, and keywords, you can use temporary IDs to specify a resource name.

Java

 private 
  
 void 
  
 addAllBatchJobOperations 
 ( 
  
 BatchJobServiceClient 
  
 batchJobServiceClient 
 , 
  
 long 
  
 customerId 
 , 
  
 String 
  
 batchJobResourceName 
 ) 
  
 { 
  
 AddBatchJobOperationsResponse 
  
 response 
  
 = 
  
 batchJobServiceClient 
 . 
 addBatchJobOperations 
 ( 
  
 AddBatchJobOperationsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 batchJobResourceName 
 ) 
  
 . 
 addAllMutateOperations 
 ( 
 buildAllOperations 
 ( 
 customerId 
 )) 
  
 . 
 build 
 ()); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "%d mutate operations have been added so far.%n" 
 , 
  
 response 
 . 
 getTotalOperations 
 ()); 
  
 // You can use this next sequence token for calling addBatchJobOperations() next time. 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Next sequence token for adding next operations is '%s'.%n" 
 , 
  
 response 
 . 
 getNextSequenceToken 
 ()); 
 } 
  
  

C#

 private 
  
 static 
  
 void 
  
 AddAllBatchJobOperations 
 ( 
 BatchJobServiceClient 
  
 batchJobService 
 , 
  
 long 
  
 customerId 
 , 
  
 string 
  
 batchJobResourceName 
 ) 
 { 
  
 AddBatchJobOperationsResponse 
  
 response 
  
 = 
  
 batchJobService 
 . 
 AddBatchJobOperations 
 ( 
  
 new 
  
 AddBatchJobOperationsRequest 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 batchJobResourceName 
 , 
  
 MutateOperations 
  
 = 
  
 { 
  
 BuildAllOperations 
 ( 
 customerId 
 ) 
  
 } 
  
 }); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"{response.TotalOperations} mutate operations have been added" 
  
 + 
  
 $" so far." 
 ); 
  
 // You can use this next sequence token for calling AddBatchJobOperations() next time. 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Next sequence token for adding next operations is " 
  
 + 
  
 $"'{response.NextSequenceToken}'." 
 ); 
 } 
  
  

PHP

 private static function addAllBatchJobOperations( 
 BatchJobServiceClient $batchJobServiceClient, 
 int $customerId, 
 string $batchJobResourceName 
 ): void { 
 $response = $batchJobServiceClient->addBatchJobOperations( 
 AddBatchJobOperationsRequest::build( 
 $batchJobResourceName, 
 '', 
 self::buildAllOperations($customerId) 
 ) 
 ); 
 printf( 
 "%d mutate operations have been added so far.%s", 
 $response->getTotalOperations(), 
 PHP_EOL 
 ); 
 // You can use this next sequence token for calling addBatchJobOperations() next time. 
 printf( 
 "Next sequence token for adding next operations is '%s'.%s", 
 $response->getNextSequenceToken(), 
 PHP_EOL 
 ); 
 }  
 

Python

 def 
  
 add_all_batch_job_operations 
 ( 
 batch_job_service 
 : 
 BatchJobServiceClient 
 , 
 operations 
 : 
 List 
 [ 
 MutateOperation 
 ], 
 resource_name 
 : 
 str 
 , 
 ) 
 - 
> None 
 : 
  
 """Adds all mutate operations to the batch job. 
 As this is the first time for this batch job, we pass null as a sequence 
 token. The response will contain the next sequence token that we can use 
 to upload more operations in the future. 
 Args: 
 batch_job_service: an instance of the BatchJobService message class. 
 operations: a list of a mutate operations. 
 resource_name: a str of a resource name for a batch job. 
 """ 
 try 
 : 
 response 
 : 
 AddBatchJobOperationsResponse 
 = 
 ( 
 batch_job_service 
 . 
 add_batch_job_operations 
 ( 
 resource_name 
 = 
 resource_name 
 , 
 sequence_token 
 = 
 None 
 , 
 # type: ignore 
 mutate_operations 
 = 
 operations 
 , 
 ) 
 ) 
 print 
 ( 
 f 
 " 
 { 
 response 
 . 
 total_operations 
 } 
 mutate operations have been " 
 "added so far." 
 ) 
 # You can use this next sequence token for calling 
 # add_batch_job_operations() next time. 
 print 
 ( 
 "Next sequence token for adding next operations is " 
 f 
 " 
 { 
 response 
 . 
 next_sequence_token 
 } 
 " 
 ) 
 except 
 GoogleAdsException 
 as 
 exception 
 : 
 handle_googleads_exception 
 ( 
 exception 
 ) 
  

Ruby

 def 
  
 add_all_batch_job_operations 
 ( 
  
 client 
 , 
  
 batch_job_service 
 , 
  
 customer_id 
 , 
  
 batch_job_resource_name 
 ) 
  
 response 
  
 = 
  
 batch_job_service 
 . 
 add_batch_job_operations 
 ( 
  
 resource_name 
 : 
  
 batch_job_resource_name 
 , 
  
 mutate_operations 
 : 
  
 build_all_operations 
 ( 
 client 
 , 
  
 customer_id 
 ), 
  
 ) 
  
 puts 
  
 " 
 #{ 
 response 
 . 
 total_operations 
 } 
 mutate operations have been added so far." 
  
 # You can use this next sequence token for calling 
  
 # add_all_batch_job_operations() next time 
  
 puts 
  
 "Next sequence token for adding next operations is " 
  
 \ 
  
 "' 
 #{ 
 response 
 . 
 next_sequence_token 
 } 
 '" 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 add_all_batch_job_operations 
  
 { 
  
 my 
  
 ( 
 $batch_job_service 
 , 
  
 $customer_id 
 , 
  
 $batch_job_resource_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $add_batch_job_operations_response 
  
 = 
  
 $batch_job_service 
 - 
> add_operations 
 ({ 
  
 resourceName 
  
 = 
>  
 $batch_job_resource_name 
 , 
  
 sequenceToken 
  
 = 
>  
 undef 
 , 
  
 mutateOperations 
  
 = 
>  
 build_all_operations 
 ( 
 $customer_id 
 )}); 
  
 printf 
  
 "%d batch operations have been added so far.\n" 
 , 
  
 $add_batch_job_operations_response 
 - 
> { 
 totalOperations 
 }; 
  
 # You can use this next sequence token for calling add_operations() next time. 
  
 printf 
  
 "Next sequence token for adding next operations is '%s'.\n" 
 , 
  
 $add_batch_job_operations_response 
 - 
> { 
 nextSequenceToken 
 }; 
 } 
  
  

curl

 # 
Adds  
operations  
to  
a  
batch  
job. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. # 
BATCH_JOB_RESOURCE_NAME: # 
The  
resource  
name  
of  
the  
batch  
job  
to  
which  
the  
operations  
should  
be  
added # 
as  
returned  
by  
the  
previous  
step. curl -f --request POST \ 
 "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_RESOURCE_NAME}:addOperations" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ 
 --data @- <<EOF 
 { 
 "mutateOperations": [ 
 { 
 "campaignBudgetOperation": { 
 "create": { 
 "resourceName": "customers/${CUSTOMER_ID}/campaignBudgets/-1", 
 "name": "batch job budget #${RANDOM}", 
 "deliveryMethod": "STANDARD", 
 "amountMicros": 5000000 
 } 
 } 
 }, 
 { 
 "campaignOperation": { 
 "create": { 
 "advertisingChannelType": "SEARCH", 
 "status": "PAUSED", 
 "name": "batch job campaign #${RANDOM}", 
 "campaignBudget": "customers/${CUSTOMER_ID}/campaignBudgets/-1", 
 "resourceName": "customers/${CUSTOMER_ID}/campaigns/-2", 
 "manualCpc": { 
 } 
 } 
 }, 
 } 
 ] 
 } 
 EOF  
 
  

Click to see the content of the build operations function in GitHub for your client library:

Run the batch job

After adding all your operations, you can request the Google Ads API to run the batch job by calling RunBatchJob on the uploaded operations.

Java

 private 
  
 OperationFuture 
  
 runBatchJob 
 ( 
  
 BatchJobServiceClient 
  
 batchJobServiceClient 
 , 
  
 String 
  
 batchJobResourceName 
 ) 
  
 { 
  
 OperationFuture 
  
 operationResponse 
  
 = 
  
 batchJobServiceClient 
 . 
 runBatchJobAsync 
 ( 
 batchJobResourceName 
 ); 
  
 // BEWARE! The above call returns an OperationFuture. The execution of that future depends on 
  
 // the thread pool which is owned by batchJobServiceClient. If you use this future, you *must* 
  
 // keep the service client in scope too. 
  
 // See https://developers.google.com/google-ads/api/docs/client-libs/java/lro for more detail. 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Mutate job with resource name '%s' has been executed.%n" 
 , 
  
 batchJobResourceName 
 ); 
  
 return 
  
 operationResponse 
 ; 
 } 
  
  

C#

 private 
  
 Operation<Empty 
 , 
  
 BatchJobMetadata 
>  
 RunBatchJob 
 ( 
  
 BatchJobServiceClient 
  
 batchJobService 
 , 
  
 string 
  
 batchJobResourceName 
 ) 
 { 
  
 Operation<Empty 
 , 
  
 BatchJobMetadata 
>  
 operationResponse 
  
 = 
  
 batchJobService 
 . 
 RunBatchJob 
 ( 
 batchJobResourceName 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Batch job with resource name '{batchJobResourceName}' has been " 
  
 + 
  
 $"executed." 
 ); 
  
 return 
  
 operationResponse 
 ; 
 } 
  
  

PHP

 private static function runBatchJob( 
 BatchJobServiceClient $batchJobServiceClient, 
 string $batchJobResourceName 
 ): OperationResponse { 
 $operationResponse = 
 $batchJobServiceClient->runBatchJob(RunBatchJobRequest::build($batchJobResourceName)); 
 printf( 
 "Batch job with resource name '%s' has been executed.%s", 
 $batchJobResourceName, 
 PHP_EOL 
 ); 
 return $operationResponse; 
 }  
 

Python

 def 
  
 run_batch_job 
 ( 
 batch_job_service 
 : 
 BatchJobServiceClient 
 , 
 resource_name 
 : 
 str 
 ) 
 - 
> Operation 
 : 
  
 """Runs the batch job for executing all uploaded mutate operations. 
 Args: 
 batch_job_service: an instance of the BatchJobService message class. 
 resource_name: a str of a resource name for a batch job. 
 Returns: a google.api_core.operation.Operation instance. 
 """ 
 try 
 : 
 response 
 : 
 Operation 
 = 
 batch_job_service 
 . 
 run_batch_job 
 ( 
 resource_name 
 = 
 resource_name 
 ) 
 print 
 ( 
 f 
 'Batch job with resource name " 
 { 
 resource_name 
 } 
 " has been ' 
 "executed." 
 ) 
 return 
 response 
 except 
 GoogleAdsException 
 as 
 exception 
 : 
 handle_googleads_exception 
 ( 
 exception 
 ) 
 # This line will likely not be reached due to sys.exit(1) in handle_googleads_exception 
 # but to satisfy the type checker, we add a return statement. 
 # In a real application, you might want to return a dummy Operation or raise an error. 
 return 
 Operation 
 ( 
 op_type_name 
 = 
 "type.googleapis.com/google.protobuf.Empty" 
 , 
 complete 
 = 
 True 
 , 
 done_callbacks 
 = 
 [], 
 metadata_type 
 = 
 None 
 , 
 result_type 
 = 
 None 
 , 
 ) 
 # type: ignore  
 

Ruby

 def 
  
 run_batch_job 
 ( 
 batch_job_service 
 , 
  
 batch_job_resource_name 
 ) 
  
 operation_response 
  
 = 
  
 batch_job_service 
 . 
 run_batch_job 
 ( 
  
 resource_name 
 : 
  
 batch_job_resource_name 
 , 
  
 ) 
  
 puts 
  
 "Batch job with resource name ' 
 #{ 
 batch_job_resource_name 
 } 
 ' " 
  
 \ 
  
 "has been executed." 
  
 operation_response 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 run_batch_job 
  
 { 
  
 my 
  
 ( 
 $batch_job_service 
 , 
  
 $batch_job_resource_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 my 
  
 $batch_job_lro 
  
 = 
  
 $batch_job_service 
 - 
> run 
 ({ 
 resourceName 
  
 = 
>  
 $batch_job_resource_name 
 }); 
  
 printf 
  
 "Batch job with resource name '%s' has been executed.\n" 
 , 
  
 $batch_job_resource_name 
 ; 
  
 return 
  
 $batch_job_lro 
 ; 
 } 
  
  

curl

 # 
Runs  
a  
batch  
job. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. # 
BATCH_JOB_RESOURCE_NAME: # 
The  
resource  
name  
of  
the  
batch  
job  
to  
run  
as  
returned  
by  
the  
previous  
step. curl -f --request POST \ 
 "https://googleads.googleapis.com/v19/${BATCH_JOB_RESOURCE_NAME}:run" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ 
 --data @- <<EOF 
 {} 
 EOF 
  
  

The returned response is an object of a long-running Operation (LRO) . The LRO contains the metadata of your batch job along with the information about the job status.

Poll the status of the batch job until it's done

The next step is to poll the status of the batch job using the LRO's GetOperation until the LRO's done value is true .

Java

 private 
  
 void 
  
 pollBatchJob 
 ( 
 OperationFuture 
  
 operationResponse 
 ) 
  
 { 
  
 try 
  
 { 
  
 operationResponse 
 . 
 get 
 ( 
 MAX_TOTAL_POLL_INTERVAL_SECONDS 
 , 
  
 TimeUnit 
 . 
 SECONDS 
 ); 
  
 } 
  
 catch 
  
 ( 
 InterruptedException 
  
 | 
  
 ExecutionException 
  
 | 
  
 TimeoutException 
  
 e 
 ) 
  
 { 
  
 System 
 . 
 err 
 . 
 printf 
 ( 
 "Failed polling the mutate job. Exception: %s%n" 
 , 
  
 e 
 ); 
  
 System 
 . 
 exit 
 ( 
 1 
 ); 
  
 } 
 } 
  
  

C#

 private 
  
 static 
  
 void 
  
 PollBatchJob 
 ( 
 Operation<Empty 
 , 
  
 BatchJobMetadata 
>  
 operationResponse 
 ) 
 { 
  
 PollSettings 
  
 pollSettings 
  
 = 
  
 new 
  
 PollSettings 
 ( 
  
 Expiration 
 . 
 FromTimeout 
 ( 
 TimeSpan 
 . 
 FromSeconds 
 ( 
 MAX_TOTAL_POLL_INTERVAL_SECONDS 
 )), 
  
 TimeSpan 
 . 
 FromSeconds 
 ( 
 1 
 )); 
  
 operationResponse 
 . 
 PollUntilCompleted 
 ( 
 pollSettings 
 ); 
 } 
  
  

PHP

 private static function pollBatchJob(OperationResponse $operationResponse): void 
 { 
 $operationResponse->pollUntilComplete([ 
 'initialPollDelayMillis' => self::POLL_FREQUENCY_SECONDS * 1000, 
 'totalPollTimeoutMillis' => self::MAX_TOTAL_POLL_INTERVAL_SECONDS * 1000 
 ]); 
 }  
 

Python

 def 
  
 poll_batch_job 
 ( 
 operations_response 
 : 
 Operation 
 , 
 event 
 : 
 asyncio 
 . 
 Event 
 ) 
 - 
> None 
 : 
  
 """Polls the server until the batch job execution finishes. 
 Sets the initial poll delay time and the total time to wait before time-out. 
 Args: 
 operations_response: a google.api_core.operation.Operation instance. 
 event: an instance of asyncio.Event to invoke once the operations have 
 completed, alerting the awaiting calling code that it can proceed. 
 """ 
 loop 
 : 
 asyncio 
 . 
 AbstractEventLoop 
 = 
 asyncio 
 . 
 get_event_loop 
 () 
 def 
  
 done_callback 
 ( 
 future 
 : 
 Coroutine 
 [ 
 Any 
 , 
 Any 
 , 
 Any 
 ]) 
 - 
> None 
 : 
 # The operations_response object will call callbacks from a daemon 
 # thread so we must use a threadsafe method of setting the event here 
 # otherwise it will not trigger the awaiting code. 
 loop 
 . 
 call_soon_threadsafe 
 ( 
 event 
 . 
 set 
 ) 
 # operations_response represents a Long-Running Operation or LRO. The class 
 # provides an interface for polling the API to check when the operation is 
 # complete. Below we use the asynchronous interface, but there's also a 
 # synchronous interface that uses the Operation.result method. 
 # See: https://googleapis.dev/python/google-api-core/latest/operation.html 
 operations_response 
 . 
 add_done_callback 
 ( 
 done_callback 
 ) 
 # type: ignore  
 

Ruby

 def 
  
 poll_batch_job 
 ( 
 operation_response 
 ) 
  
 operation_response 
 . 
 wait_until_done! 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 poll_batch_job 
  
 { 
  
 my 
  
 ( 
 $operation_service 
 , 
  
 $batch_job_lro 
 ) 
  
 = 
  
 @_ 
 ; 
  
 $operation_service 
 - 
> poll_until_done 
 ({ 
  
 name 
  
 = 
>  
 $batch_job_lro 
 - 
> { 
 name 
 }, 
  
 pollFrequencySeconds 
  
 = 
>  
 POLL_FREQUENCY_SECONDS 
 , 
  
 pollTimeoutSeconds 
  
 = 
>  
 POLL_TIMEOUT_SECONDS 
  
 }); 
 } 
  
  

curl

 # 
Gets  
the  
status  
of  
a  
batch  
job. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. # 
BATCH_JOB_OPERATION_NAME: # 
The  
operation  
name  
of  
the  
running  
batch  
job  
as  
returned  
by  
the  
previous # 
step. curl -f --request GET \ 
 "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_OPERATION_NAME}" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ 
  
  

List all batch job results

When all of your batch jobs finish, use ListBatchJobResults to list their results, and print their statuses and responses:

Java

 private 
  
 void 
  
 fetchAndPrintResults 
 ( 
  
 BatchJobServiceClient 
  
 batchJobServiceClient 
 , 
  
 String 
  
 batchJobResourceName 
 ) 
  
 { 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Mutate job with resource name '%s' has finished. Now, printing its results...%n" 
 , 
  
 batchJobResourceName 
 ); 
  
 // Gets all the results from running mutate job and prints their information. 
  
 ListBatchJobResultsPagedResponse 
  
 batchJobResults 
  
 = 
  
 batchJobServiceClient 
 . 
 listBatchJobResults 
 ( 
  
 ListBatchJobResultsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setResourceName 
 ( 
 batchJobResourceName 
 ) 
  
 . 
 setPageSize 
 ( 
 PAGE_SIZE 
 ) 
  
 . 
 build 
 ()); 
  
 for 
  
 ( 
 BatchJobResult 
  
 batchJobResult 
  
 : 
  
 batchJobResults 
 . 
 iterateAll 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "Mutate job #%d has a status '%s' and response of type '%s'.%n" 
 , 
  
 batchJobResult 
 . 
 getOperationIndex 
 (), 
  
 batchJobResult 
 . 
 getStatus 
 (). 
 getMessage 
 (). 
 isEmpty 
 () 
  
 ? 
  
 "N/A" 
  
 : 
  
 batchJobResult 
 . 
 getStatus 
 (). 
 getMessage 
 (), 
  
 batchJobResult 
  
 . 
 getMutateOperationResponse 
 () 
  
 . 
 getResponseCase 
 () 
  
 . 
 equals 
 ( 
 ResponseCase 
 . 
 RESPONSE_NOT_SET 
 ) 
  
 ? 
  
 "N/A" 
  
 : 
  
 batchJobResult 
 . 
 getMutateOperationResponse 
 (). 
 getResponseCase 
 ()); 
  
 } 
 } 
  
  

C#

 private 
  
 static 
  
 void 
  
 FetchAndPrintResults 
 ( 
 BatchJobServiceClient 
  
 batchJobService 
 , 
  
 string 
  
 batchJobResourceName 
 ) 
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"batch job with resource name '{batchJobResourceName}' has " 
  
 + 
  
 $"finished. Now, printing its results..." 
 ); 
  
 ListBatchJobResultsRequest 
  
 request 
  
 = 
  
 new 
  
 ListBatchJobResultsRequest 
 () 
  
 { 
  
 ResourceName 
  
 = 
  
 batchJobResourceName 
 , 
  
 PageSize 
  
 = 
  
 PAGE_SIZE 
 , 
  
 }; 
  
 ListBatchJobResultsResponse 
  
 resp 
  
 = 
  
 new 
  
 ListBatchJobResultsResponse 
 (); 
  
 // Gets all the results from running batch job and prints their information. 
  
 foreach 
  
 ( 
 BatchJobResult 
  
 batchJobResult 
  
 in 
  
 batchJobService 
 . 
 ListBatchJobResults 
 ( 
 request 
 )) 
  
 { 
  
 if 
  
 ( 
 ! 
 batchJobResult 
 . 
 IsFailed 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"batch job result #{batchJobResult.OperationIndex} is " 
  
 + 
  
 $"successful and response is of type " 
  
 + 
  
 $"'{batchJobResult.MutateOperationResponse.ResponseCase}'." 
 ); 
  
 } 
  
 else 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"batch job result #{batchJobResult.OperationIndex} " 
  
 + 
  
 $"failed with error message {batchJobResult.Status.Message}." 
 ); 
  
 foreach 
  
 ( 
 GoogleAdsError 
  
 error 
  
 in 
  
 batchJobResult 
 . 
 Failure 
 . 
 Errors 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Error found: {error}." 
 ); 
  
 } 
  
 } 
  
 } 
 } 
  
  

PHP

 private static function fetchAndPrintResults( 
 BatchJobServiceClient $batchJobServiceClient, 
 string $batchJobResourceName 
 ): void { 
 printf( 
 "Batch job with resource name '%s' has finished. Now, printing its results...%s", 
 $batchJobResourceName, 
 PHP_EOL 
 ); 
 // Gets all the results from running batch job and print their information. 
 $batchJobResults = $batchJobServiceClient->listBatchJobResults( 
 ListBatchJobResultsRequest::build($batchJobResourceName)->setPageSize(self::PAGE_SIZE) 
 ); 
 foreach ($batchJobResults->iterateAllElements() as $batchJobResult) { 
 /** @var BatchJobResult $batchJobResult */ 
 printf( 
 "Batch job #%d has a status '%s' and response of type '%s'.%s", 
 $batchJobResult->getOperationIndex(), 
 $batchJobResult->getStatus() 
 ? $batchJobResult->getStatus()->getMessage() : 'N/A', 
 $batchJobResult->getMutateOperationResponse() 
 ? $batchJobResult->getMutateOperationResponse()->getResponse() 
 : 'N/A', 
 PHP_EOL 
 ); 
 } 
 }  
 

Python

 def 
  
 fetch_and_print_results 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 batch_job_service 
 : 
 BatchJobServiceClient 
 , 
 resource_name 
 : 
 str 
 , 
 ) 
 - 
> None 
 : 
  
 """Prints all the results from running the batch job. 
 Args: 
 client: an initialized GoogleAdsClient instance. 
 batch_job_service: an instance of the BatchJobService message class. 
 resource_name: a str of a resource name for a batch job. 
 """ 
 print 
 ( 
 f 
 'Batch job with resource name " 
 { 
 resource_name 
 } 
 " has finished. ' 
 "Now, printing its results..." 
 ) 
 list_results_request 
 : 
 ListBatchJobResultsRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "ListBatchJobResultsRequest" 
 ) 
 list_results_request 
 . 
 resource_name 
 = 
 resource_name 
 list_results_request 
 . 
 page_size 
 = 
 1000 
 # Gets all the results from running batch job and prints their information. 
 batch_job_results 
 : 
 ListBatchJobResultsResponse 
 = 
 ( 
 batch_job_service 
 . 
 list_batch_job_results 
 ( 
 request 
 = 
 list_results_request 
 ) 
 ) 
 for 
 batch_job_result 
 in 
 batch_job_results 
 : 
 status 
 : 
 str 
 = 
 batch_job_result 
 . 
 status 
 . 
 message 
 status 
 = 
 status 
 if 
 status 
 else 
 "N/A" 
 result 
 : 
 Any 
 = 
 batch_job_result 
 . 
 mutate_operation_response 
 result 
 = 
 result 
 or 
 "N/A" 
 print 
 ( 
 f 
 "Batch job # 
 { 
 batch_job_result 
 . 
 operation_index 
 } 
 " 
 f 
 'has a status " 
 { 
 status 
 } 
 " and response type " 
 { 
 result 
 } 
 "' 
 ) 
  

Ruby

 def 
  
 fetch_and_print_results 
 ( 
 batch_job_service 
 , 
  
 batch_job_resource_name 
 ) 
  
 puts 
  
 "Batch job with resource name ' 
 #{ 
 batch_job_resource_name 
 } 
 ' has " 
  
 \ 
  
 "finished. Now, printing its results..." 
  
 \ 
  
 # Gets all the results from running batch job and print their information. 
  
 batch_job_results 
  
 = 
  
 batch_job_service 
 . 
 list_batch_job_results 
 ( 
  
 resource_name 
 : 
  
 batch_job_resource_name 
 , 
  
 page_size 
 : 
  
 PAGE_SIZE 
 , 
  
 ) 
  
 batch_job_results 
 . 
 each 
  
 do 
  
 | 
 result 
 | 
  
 puts 
  
 "Batch job # 
 #{ 
 result 
 . 
 operation_index 
 } 
 has a status " 
  
 \ 
  
 " 
 #{ 
 result 
 . 
 status 
  
 ? 
  
 result 
 . 
 status 
 . 
 message 
  
 : 
  
 'N/A' 
 } 
 and response of type " 
  
 \ 
  
 " 
 #{ 
 result 
 . 
 mutate_operation_response 
  
 ? 
  
 result 
 . 
 mutate_operation_response 
 . 
 response 
  
 : 
  
 'N/A' 
 } 
 " 
  
 end 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 fetch_and_print_results 
  
 { 
  
 my 
  
 ( 
 $batch_job_service 
 , 
  
 $batch_job_resource_name 
 ) 
  
 = 
  
 @_ 
 ; 
  
 printf 
  
 "Batch job with resource name '%s' has finished. " 
  
 . 
  
 "Now, printing its results...\n" 
 , 
  
 $batch_job_resource_name 
 ; 
  
 # Get all the results from running batch job and print their information. 
  
 my 
  
 $list_batch_job_results_response 
  
 = 
  
 $batch_job_service 
 - 
> list_results 
 ({ 
  
 resourceName 
  
 = 
>  
 $batch_job_resource_name 
 , 
  
 pageSize 
  
 = 
>  
 PAGE_SIZE 
  
 }); 
  
 foreach 
  
 my 
  
 $batch_job_result 
  
 ( 
 @ 
 { 
 $list_batch_job_results_response 
 - 
> { 
 results 
 }}) 
  
 { 
  
 printf 
  
 "Batch job #%d has a status '%s' and response of type '%s'.\n" 
 , 
  
 $batch_job_result 
 - 
> { 
 operationIndex 
 }, 
  
 $batch_job_result 
 - 
> { 
 status 
 } 
  
 ? 
  
 $batch_job_result 
 - 
> { 
 status 
 }{ 
 message 
 } 
  
 : 
  
 "N/A" 
 , 
  
 $batch_job_result 
 - 
> { 
 mutateOperationResponse 
 } 
  
 ? 
  
 [ 
 keys 
  
 % 
 { 
 $batch_job_result 
 - 
> { 
 mutateOperationResponse 
 }}] 
 - 
> [ 
 0 
 ] 
  
 : 
  
 "N/A" 
 ; 
  
 } 
 } 
  
  

curl

 # 
Gets  
the  
results  
of  
a  
batch  
job. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. # 
BATCH_JOB_RESOURCE_NAME: # 
The  
operation  
name  
of  
the  
running  
batch  
job  
as  
returned  
by  
the  
previous # 
step. curl -f --request GET \ 
 "https://googleads.googleapis.com/v${API_VERSION}/${BATCH_JOB_RESOURCE_NAME}:listResults?pageSize=1000" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" 
  
  

If the corresponding operation was successful, the response of the mutate_operation_response contains the result with its resource_name . In addition, the resource of the result contains the modified resource with all of its mutable fields populated if response_content_type is set to MUTABLE_RESOURCE .

If the corresponding operation produced errors and can't be completed, the mutate_operation_response field is null .

The status field of BatchJobResult contains error details for each failed operation.

Cancel a batch job

If necessary, you can attempt to cancel a batch job. See CancelOperation .

Error handling

BatchJobService automatically retries operations that fail due to transient errors. However, not all failure scenarios can be avoided. Operations that failed due to validation errors can be fixed and resubmitted in a new batch job. Operations that were cancelled can be retried by adding them to a new batch job.

Create a Mobile Website
View Site in Mobile | Classic
Share by: