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::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;}
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 callAddBatchJobOperationsagain to add more operations, ensure you specify the previously obtained
sequence token in thesequence_tokenfield of arequest. 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
usetemporary IDsto 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 sequencetoken. The response will contain the next sequence token that we can useto 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 along-runningOperation(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'sGetOperationuntil the LRO'sdonevalue istrue.
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 havecompleted, 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
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, theresponseof themutate_operation_responsecontains the result with itsresource_name. In addition, the resource of the
result contains the modified resource with all of its mutable fields populated
ifresponse_content_typeis set toMUTABLE_RESOURCE.
If the corresponding operation produced errors and can't be completed, themutate_operation_responsefield isnull.
Thestatusfield ofBatchJobResultcontains error details for
each failed operation.
Cancel a batch job
If necessary, you can attempt to cancel a batch job. SeeCancelOperation.
Error handling
BatchJobServiceautomatically 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-09-03 UTC."],[[["\u003cp\u003eGoogle Ads API offers batch processing to efficiently execute multiple operations, like creating or updating ads, in a single request.\u003c/p\u003e\n"],["\u003cp\u003eThe batch processing workflow involves creating a job, adding operations, running the job, monitoring its progress, and retrieving the results.\u003c/p\u003e\n"],["\u003cp\u003eResults for each operation within a batch job can be retrieved using \u003ccode\u003eListBatchJobResults\u003c/code\u003e and indicate either success or failure with detailed information.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003eBatchJobService\u003c/code\u003e automatically retries transient errors, while validation or cancellation errors necessitate fixing and resubmitting operations in a new batch job.\u003c/p\u003e\n"],["\u003cp\u003eCode examples in various languages (Java, C#, PHP, Python, Ruby, Perl) are available to guide developers through the batch processing implementation.\u003c/p\u003e\n"]]],[],null,[]]