Thanks, please allow me to dive deeper to my question:

*Google Ads API: batch-processing vs bulk mutates*


I want to remove a few ads in one server request.
What is the difference between:

 - batch-processing (only async?) 
 - bulk mutates (only sync, shorter code?)



I have tried both ways and got errors:


1) batch-processing

I've tried to follow this [post][1] about `batch-processing` to create an 
async batch job for removing multiple ads. It was sent to the server, but I 
didn't see the sent ad ids were deleted.

Do I miss anything?


*    class ServiceWrapper:*
*        """Wraps GoogleAdsService API request"""*
    
*        # public properties ...*
    
*        def __init__(self, client, customer_id):*
*            self._client = client*
*            self._ga_service = client.get_service("GoogleAdsService")*
*            self._ad_group_ad_service = 
client.get_service("AdGroupAdService")*
*            self._batch_job_service = 
client.get_service("BatchJobService")*
*            self._customer_id = customer_id*
    
*            self._batch_job_operation = 
self._create_batch_job_operation(client)*
*            self._batch_job_resource_name = 
self._create_batch_job(self._batch_job_service, customer_id,*
*                                                                  
 self._batch_job_operation)*
    
*        def _create_batch_job_operation(self, client):*
*            """Created a BatchJobOperation and sets an empty BatchJob 
instance to*
*            the "create" property in order to tell the Google Ads API that 
we're*
*            creating a new BatchJob.*
*            Args:*
*                client: an initialized GoogleAdsClient instance.*
*            Returns: a BatchJobOperation with a BatchJob instance set in 
the "create"*
*                property.*
*            """*
*            batch_job_operation = client.get_type("BatchJobOperation")*
*            batch_job = client.get_type("BatchJob")*
*            client.copy_from(batch_job_operation.create, batch_job)*
*            return batch_job_operation*
    
*        def _create_batch_job(self, batch_job_service, customer_id, 
batch_job_operation):*
*            """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 = batch_job_service.mutate_batch_job(*
*                    customer_id=customer_id, operation=batch_job_operation*
*                )*
*                resource_name = 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)*
    
*        def add_all_batch_job_operations(self, batch_job_service, 
operations, resource_name):*
*            """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 = batch_job_service.add_batch_job_operations(*
*                    resource_name=resource_name,*
*                    sequence_token=None,*
*                    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)*
    
    
*    def remove_disapproved_ads_for_account(account):*
*        """Remove all disapproved ads for a given customer id"""*
*        ad_removal_operations = []*
*            for row in rows:*
*                        ad_removal_operations.append(*
*                            build_removal_operation(customer_id, 
ad_json["ad_group_id"],     *
*        if len(ad_removal_operations) > 0:*
*            remove_ads(ad_removal_operations)*
*            #serviceWrapper.mutate(customer_id, [mutate_operation1, 
mutate_operation2])*
    
    
*    def build_removal_operation(customer_id, ad_group_id, ad_id):*
*        """Removes the specified ad"""*
*        resource_name = 
serviceWrapper.ad_group_ad_service.ad_group_ad_path(*
*            customer_id, ad_group_id, ad_id*
*        )*
*        ad_group_ad_operation = 
serviceWrapper.client.get_type("AdGroupAdOperation")*
*        ad_group_ad_operation.remove = resource_name*
*        return ad_group_ad_operation*
    
*    async def remove_ads(removal_operations):*
*        """Removes the specified ad"""*
*        
serviceWrapper.add_all_batch_job_operations(serviceWrapper.batch_job_service, 
removal_operations,*
*                                                    
serviceWrapper.batch_job_resource_name)*
*        operations_response = 
_run_batch_job(serviceWrapper.batch_job_service, 
serviceWrapper.batch_job_resource_name)*
    
*        # Create an asyncio.Event instance to control execution during the*
*        # asyncronous steps in _poll_batch_job. Note that this is not 
important*
*        # for polling asyncronously, it simply helps with execution 
control so we*
*        # can run _fetch_and_print_results after the asyncronous 
operations have*
*        # completed.*
*        _done_event = asyncio.Event()*
*        _poll_batch_job(operations_response, _done_event)*
*        # Execution will stop here and wait for the asyncronous steps in*
*        # _poll_batch_job to complete before proceeding.*
*        await _done_event.wait()*
*        _fetch_and_print_results(serviceWrapper.client, 
serviceWrapper.batch_job_service,*
*                                 serviceWrapper.batch_job_resource_name)*
    
    
*    def _run_batch_job(batch_job_service, resource_name):*
*        """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 = 
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)*
    
    
*    def _poll_batch_job(operations_response, event):*
*        """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.get_event_loop()*
    
*        def _done_callback(future):*
*            # 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)*
    
    
*    def _fetch_and_print_results(client, batch_job_service, 
resource_name):*
*        """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 = 
client.get_type("ListBatchJobResultsRequest")*
*        list_results_request.resource_name = resource_name*
*        list_results_request.page_size = BULK_REMOVE_PAGE_SIZE*
*        # Gets all the results from running batch job and prints their 
information.*
*        batch_job_results = batch_job_service.list_batch_job_results(*
*            request=list_results_request*
*        )*
    
*        for batch_job_result in batch_job_results:*
*            status = batch_job_result.status.message*
*            status = status if status else "N/A"*
*            result = 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}"'*
*            )*


2) Bulk Mutates

If I choose to follow this [post][2] about `Bulk Mutates`, and create a 
sync batch, I get an undefined symbol `:Mutate` how can I fix this? Or make 
this code work?



*    class ServiceWrapper:*
*        """Wraps GoogleAdsService API request"""*
    
*        # public properties ...*
    
*        def __init__(self, client, customer_id):*
*            self._client = client*
*            self._ga_service = client.get_service("GoogleAdsService")*
*            self._ad_group_ad_service = 
client.get_service("AdGroupAdService")*
*            self._batch_job_service = 
client.get_service("BatchJobService")*
*            self._customer_id = customer_id*
    
*            self._batch_job_operation = 
self._create_batch_job_operation(client)*
*            self._batch_job_resource_name = 
self._create_batch_job(self._batch_job_service, customer_id,*
*                                                                  
 self._batch_job_operation)*
    
           
    
*     def build_removal_operation_sync(customer_id, ad_group_id, ad_id):*
*         mutate_operation1 = serviceWrapper.client.operation(:Mutate)*
    
*         """Removes the specified ad"""*
*         resource_name = 
serviceWrapper.ad_group_ad_service.ad_group_ad_path(*
*             customer_id, ad_group_id, ad_id*
*         )*
*         ad_group_ad_operation = 
serviceWrapper.client.get_type("AdGroupAdOperation")*
*         ad_group_ad_operation.remove = resource_name*
    
*         mutate_operation1.ad_group_ad_operation = campaign_operation*
    
    


  [1]: 
https://developers.google.com/google-ads/api/docs/batch-processing/flow
  [2]: 
https://developers.google.com/google-ads/api/docs/mutating/bulk-mutate
On Tuesday, September 7, 2021 at 9:29:10 AM UTC+3 adsapi wrote:

> Hi,
>
> You can make use of a test account 
> <https://developers.google.com/google-ads/api/docs/first-call/overview#test_account>,
>  
> and create (non serving) ads if you wish to test the bulk removal of ads.
>
> For the bulk removal of ads, I would recommend that you refer to our batch 
> processing 
> <https://developers.google.com/google-ads/api/docs/batch-processing/overview> 
> guide for more information. The limitations are then discussed here 
> <https://developers.google.com/google-ads/api/docs/batch-processing/best-practices#limitations>
> .
>
> For the non BatchJobService approach, you can refer to the below guides 
> for more information on the API's limits : 
>    
>    - API limits and quotas  
>    <https://developers.google.com/google-ads/api/docs/best-practices/quotas> 
>    - System limits 
>    
> <https://developers.google.com/google-ads/api/docs/best-practices/system-limits>
>  
>    - Rate limits 
>    
> <https://developers.google.com/google-ads/api/docs/best-practices/rate-limits>
>  
>
> For mutate requests 
> <https://developers.google.com/google-ads/api/docs/best-practices/quotas#mutate_requests>,
>  
> up to 5,000 operations can be included in a single request.
>
> I hope this helps.
>
> Best regards,
>
> [image: Google Logo] 
> Peter Laurence Napa Oliquino 
> Google Ads API Team 
>   
>
> ref:_00D1U1174p._5004Q2MlCCh:ref
>

-- 
-- 
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
Also find us on our blog:
https://googleadsdeveloper.blogspot.com/
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~

You received this message because you are subscribed to the Google
Groups "AdWords API and Google Ads API Forum" group.
To post to this group, send email to adwords-api@googlegroups.com
To unsubscribe from this group, send email to
adwords-api+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/adwords-api?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"AdWords API and Google Ads API Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to adwords-api+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/adwords-api/4a649ce6-6819-417f-8324-ab4d052e6af2n%40googlegroups.com.
  • Bulk remove ads 'EladB' via AdWords API and Google Ads API Forum
    • RE: Bulk re... Google Ads API Forum Advisor
      • Re: Bul... 'EladB' via AdWords API and Google Ads API Forum
        • Re:... Google Ads API Forum Advisor
          • ... 'Elad Ben-David' via AdWords API and Google Ads API Forum
            • ... Google Ads API Forum Advisor

Reply via email to