Posts tagged with google-ads-api

How do I use Google protocol buffers in a multiprocess script?

My use case is:

  • pulling data from the new Google Ads API
  • appending the objects with metadata
  • modelling using the objects
  • pushing the results to a database

AdWords Campaign Wrapper Object

I have an existing process for the old AdWords API, where I pull the data and store it in custom classes, e.g.

class Campaign(Represantable):     def __init__(self, id, managed_customer_id, base_campaign_id, name, status, serving_status):         self.id = id         self.managed_customer_id = managed_customer_id         self.base_campaign_id = base_campaign_id         self.name = name         self.status = status         self.serving_status = serving_status @classmethod     def from_zeep(cls, campaign, managed_customer_id):         return cls(             campaign.id,             managed_customer_id,             campaign.baseCampaignId,             campaign.name,             campaign.status,             campaign.servingStatus         ) 

Multiprocessing script

If I want to pull campaigns from a dozen accounts, I can run the scripts that populate the Campaign objects in parallel using pathos (again code simplified for this example):

import multiprocessing as mp from pathos.pools import ProcessPool class WithParallelism(object):     def __init__(self, parallelism_level):         self.parallelism_level = parallelism_level     def _parallel_apply(self, fn, collection, **kwargs):         pool = ProcessPool(             nodes=self.parallelism_level         )                  # this is to prevent Python from printing large traces when user interrupts execution (e.g. Ctrl+C)         def keyboard_interrupt_wrapper_fn(*args_wrapped):             try:                 return fn(*args_wrapped, **kwargs)             except KeyboardInterrupt:                 pass             except Exception as err:                 return err         errors = pool.map(keyboard_interrupt_wrapper_fn, collection)         return error 

Google Ads Campaign Wrapper Object

With the new API, I planned to store the protobuf object within my class, and use pointers to access the objects attributes. My class is a lot more complex than the example, using descriptors and subclass init for the attributes, but for simplicity it's effectively something like this:

class Campaign(Proto):     def __init__(self, **kwargs):         if "proto" in kwargs:             self._proto = kwargs['proto']         if "parent" in kwargs:             self._parent = kwargs['parent']         self._init_metadata(**kwargs) @property     def id(self):         return self._proto.id.value @property     def name(self):         return self._proto.name.value    ... 

This has the added advantage of being able to traverse the parent Google Ads object, to extract data from that protobuf object.

However, when I run my script of to populate these new objects in parallel, I get a pickle error. I understand that multiprocess uses pickle to serialize the objects, and one of the key advantages of protobuf objects is that they can be easily serialized.

How should I go about pulling the new Google Ads data in parallel:

  • Should I be serializing and deserializing the data in the Campaign object using SerializeToString
  • Should I just be extracting and storing the scalar data (id, name) like how I did with AdWords
  • Is there an entirely different approach?

So I have a client that wants to do a Google Ad campaign for certain locations. From what we gathered, you can set up location of interest and pass on a parameter {loc_physical_ms} that can be used to get some details based on that ID. My question is, how do I access that info? Is it by using an API? I did looked at the reference here:

https://developers.google.com/adwords/api/docs/appendix/geotargeting

But it is not explained how I can use that ID on my website to get something like the ZIP code and city of the click. I been looking around, but to no avail. Any suggestion is welcome.

Thanks in advance!

I'm currently trying to track form submissions on a site that has forms all over it as well as user accounts. We want to track the first form submission (a new lead) then nothing else. Because of the platform (I don't have access to the backend) it's causing every form submission to be tracked. Is there a way to limit it to user or session?

In this instance I'm wanting to fire conversion pixels for adwords and it's firing every time a form is filled out.

I've looked at Simo's guide on this that was written 6 years ago but it doesn't seem to be working.

What I did as a stopgap is identify the most common single use form (the registration form) and use that as the conversion method. However, there are other forms that are meant to be used by logged in users that get submitted over and over again. If a non-logged-in user uses this form an account is automatically created. These are the form submissions I'm trying to track.

I'm trying to modularize a type of report from the API. This is my query for the request:

content = ['CampaignId', 'AdvertisingChannelType', ...] report_query = (adwords.ReportQueryBuilder()                        .Select(content)                        .From('CAMPAIGN_PERFORMANCE_REPORT')                        .During(start_date=since,end_date=until)                        .Build()) 

However, I'm having a problem with the .Select() statement since its common usage is .Select('CampaignId', 'AdvertisingChannelType', ...) (as the list but without the brackets []) and in my query I'm parsing the arguments as a list, which of course returns an error.

My question is, how can I parse the elements of content as required? I've tried turning the list into a string but it doesn't work as all the list becomes a single element. I can't assign by hand the elements since it's number may vary (will be used for more than one client).

Any help will be appreciated. Thanks!

Is it possible to change the ad group for a campaign? I've searched Google and seemingly clicked on every tab in Adwords. I have a difficult time believing something like this wouldn't be possible... or that Adwords would make it so convoluted to do this. Any help is appreciated.

Thank you!