Posts tagged with ads-api

I follow all step of connectivity to Google Ads API. Using it I get account info like account number and time zone etc. But when I call API for campaign id or ads group at that time it return below output. In ads account (ui) I can see many campaigns.

output :

SearchPager<field_mask { paths: "campaign.id" paths: "ad_group.id"paths: "ad_group.name"}>

additionally : above output is getting in result variable and after that the for loop is not executing in image ofimage of code code

I want to get keywords' historical metrics using google Ads API, but I must create a keyword plan and get the data, but it also has other keyword suggestions which is not needed. Currently am using keyword idea endpoint in which the given keyword is the first row with data. How to use the historical metrics endpoint without creating a keyword plan?

https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics

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 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}"'         )         # [END add_complete_campaigns_using_batch_job_4] 
  1. Bulk Mutates

If I choose to follow this post 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 

I am using google ads api and displaying Google adwords ads on our site. At every request the terminal displaying logging request and response. I want to know that is there any way to disable request/response Info from console. I am using google ads java library. I tried to use new RequestLogger But I could not disable that. Below is the given message type which I am getting at every google ads api call.

com.google.api.client.http.HttpTransport [] - -------------- REQUEST  -------------- POST https://oauth.googleapis.com/token Accept-Encoding: gzip User-Agent: Google-HTTP-Java-Client/1.39.0 (gzip) Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 241 com.google.api.client.http.HttpTransport [] - curl -v --compressed -X POST -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.39.0 (gzip)' -H 'Content-Typ e: application/x-www-form-urlencoded; charset=UTF-8' -d '@-' -- 'https://oauth2.googleapis.com/token' << $$$ com.google.api.client.http.HttpTransport [] - Total: 241 bytes com.google.api.client.http.HttpTransport [] - client_id=xxxx&refresh_token=xxxx&grant_type=refresh_token com.google.api.client.http.HttpTransport [] - -------------- RESPONSE -------------- HTTP/1.1 200 OK Transfer-Encoding: chunked Alt-Svc: h3=":443"; ma=2592000,h3-29=":111"; ma=333,h3-T051=":3"; ma=000,h3-Q050=":443"; ma=2000,h3-Q046=":443"; ma=2592000,h3-Q043=":443" 46,43" Server: scaffolding on HTTPServer2 X-Content-Type-Options: nosniff Pragma: no-cache 

I'm trying to block an IP list through Google API v2 but I'm getting the error "Criteria type can not be targeted." on field: operations, on field: create, on field: ip_block. Another doubt that I have, is if I will need to repeat the create operation for each IP on my list or there is a way to put multiple Ip on the same request.

client = (google.ads.google_ads.client.GoogleAdsClient.load_from_storage(path="./google-ads.yaml")) campaign_criterion_operation = client.get_type('CampaignCriterionOperation', version='v2') campaign_criterion = campaign_criterion_operation.create campaign_criterion.campaign.value = campaign_service.campaign_path(customer, campaign) campaign_criterion.ip_block.ip_address.value = "xxx.xxx.xxx.xxx" campaign_criterion_response = campaign_criterion_service.mutate_campaign_criteria(customer, [campaign_criterion_operation]) for reponse in campaign_criterion_response.results:     print('Added campaign criterion "%s".' % reponse.resource_name)