Usage flow
Stay organized with collections
Save and categorize content based on your preferences.
Page Summary
Batch processing involves creating a batch job, adding operations, running the job, and then polling its status and listing the results.
To create a batch job resource, call MutateBatchJob, which initially sets the job's status to PENDING.
Add operations to the batch job by calling AddBatchJobOperations and use the returned sequence token for subsequent calls to add more operations.
After adding all operations, request the Google Ads API to execute the batch job by calling RunBatchJob, which returns a long-running Operation.
Poll the status of the batch job using the LRO's GetOperation until its done value is true, then use ListBatchJobResults to retrieve and examine the outcome of each operation.
The steps for using batch processing are as follows:
defcreate_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_nameprint(f'Created a batch job with resource name "{resource_name}"')returnresource_nameexceptGoogleAdsExceptionasexception: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
defcreate_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_nameputs"Created a batch job with resource name: '#{batch_job_resource_name}'"batch_job_resource_nameend
subcreate_batch_job{my($batch_job_service,$customer_id)=@_;# Create a batch job operation.my$batch_job_operation=Google::Ads::GoogleAds::V22::Services::BatchJobService::BatchJobOperation->
new({create=>Google::Ads::GoogleAds::V22::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;}
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.
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.
defadd_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: ignoremutate_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}")exceptGoogleAdsExceptionasexception:handle_googleads_exception(exception)
defadd_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 timeputs"Next sequence token for adding next operations is "\"'#{response.next_sequence_token}'"end
subadd_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};}
defrun_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.")returnresponseexceptGoogleAdsExceptionasexception: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.returnOperation(op_type_name="type.googleapis.com/google.protobuf.Empty",complete=True,done_callbacks=[],metadata_type=None,result_type=None,)# type: ignore
defrun_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_responseend
subrun_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;}
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.
defpoll_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()defdone_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.htmloperations_response.add_done_callback(done_callback)# type: ignore
When you poll the long-running operation, the
metadata field in the Operation response
provides additional details about the batch job's progress. This field contains
a BatchJobMetadata object. Key
subfields include:
creation_date_time: The timestamp when the batch job was created.
completion_date_time: The timestamp when the batch job finished (only
present if the job is done).
estimated_completion_ratio: An estimate of the fraction of the job
(from 0.0 to 1.0) that has been completed.
operation_count: The total number of operations in the batch job.
executed_operation_count: The number of operations that have been executed
so far.
These fields, especially estimated_completion_ratio and the operation counts,
can help you gauge the job's progress, estimate remaining time, and adjust your
polling frequency. For example, you might poll less frequently when the
estimated_completion_ratio is low, and more frequently as it approaches 1.0.
List all batch job results
When all of your batch jobs finish, use
ListBatchJobResults to
list their results, and print their statuses and responses:
deffetch_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_namelist_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))forbatch_job_resultinbatch_job_results:status:str=batch_job_result.status.messagestatus=statusifstatuselse"N/A"result:Any=batch_job_result.mutate_operation_responseresult=resultor"N/A"print(f"Batch job #{batch_job_result.operation_index} "f'has a status "{status}" and response type "{result}"')
deffetch_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.eachdo|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'}"endend
subfetch_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});foreachmy$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";}}
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.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-12-11 UTC."],[],[]]