def _get_service(self) -> GoogleAdsClient: """Connects and authenticates with the Google Ads API using a service account""" with NamedTemporaryFile("w", suffix=".json") as secrets_temp: self._get_config() self._update_config_with_secret(secrets_temp) try: client = GoogleAdsClient.load_from_dict(self.google_ads_config) return client.get_service("GoogleAdsService", version=self.api_version) except GoogleAuthError as e: self.log.error("Google Auth Error: %s", e) raise
def setup_client(): from google.ads.google_ads.client import GoogleAdsClient credentials = load_credentials() return GoogleAdsClient.load_from_dict(credentials)
def ewah_execute(self, context): # Task execution happens here def get_data_from_ads_output(fields_dict, values, prefix=None): if prefix is None: prefix = '' elif not prefix[-1] == '_': prefix += '_' # e.g. 2b prefix = 'ad_group_criterion_' data = {} for key, value in fields_dict.items(): # e.g. 1 key = 'metrics', value = ['impressions', 'clicks'] # e.g. 2a key = 'ad_group_criterion', value = [{'keyword': ['text', 'match_type']}] # e.g. 2b key = 'keyword', value = ['text', 'match_type'] node = getattr(values, key) # e.g. 1 node = row.metrics # e.g. 2a node = row.ad_group_criterion # e.g. 2b node = row.ad_group_criterion.keyword for item in value: # e.g. 1 item = 'clicks' # e.g. 2a item = {'keyword': ['text', 'match_type']} # e.g. 2b item = 'text' if type(item) == dict: data.update( get_data_from_ads_output( fields_dict=item, values=node, prefix=prefix + key, # e.g. 2a '' + 'ad_group_criterion' )) else: # e.g. 1: {'' + 'metrics' + '_' + 'clicks': row.metrics.clicks.value} # e.g. 2b: {'ad_group_criterion_' + 'keyeword' + '_' + 'text': row.ad_group_criterion.keyword.text.value} if hasattr(getattr(node, item), 'value'): data.update({ prefix + key + '_' + item: \ getattr(node, item).value }) else: # some node ends don't respond to .value but are # already the value data.update({ prefix + key + '_' + item: getattr(node, item) }) return data self.data_until = airflow_datetime_adjustments(self.data_until) self.data_until = self.data_until or context['next_execution_date'] if isinstance(self.data_from, timedelta): self.data_from = self.data_until - self.data_from else: self.data_from = airflow_datetime_adjustments(self.data_from) self.data_from = self.data_from or context['execution_date'] conn = BaseHook.get_connection(self.source_conn_id).extra_dejson credentials = {} for key in self._REQUIRED_KEYS: if not key in conn.keys(): raise Exception( '{0} must be in connection extra json!'.format(key)) credentials[key] = conn[key] # build the query query = 'SELECT {0} FROM {1} WHERE segments.date {2} {3}'.format( ', '.join(self.fields_list), self.resource, "BETWEEN '{0}' AND '{1}'".format( self.data_from.strftime('%Y-%m-%d'), self.data_until.strftime('%Y-%m-%d'), ), ('AND' + ' AND '.join(self.conditions)) if self.conditions else '', ) self.log.info('executing this google ads query:\n{0}'.format(query)) cli = GoogleAdsClient.load_from_dict(credentials) service = cli.get_service("GoogleAdsService", version="v3") search = service.search( self.client_id.replace('-', ''), query=query, ) data = [row for row in search] # get into uploadable format upload_data = [] while data: datum = data.pop(0) upload_data += [ get_data_from_ads_output( deepcopy(self.fields_dict), datum, ) ] self.upload_data(upload_data)
def ewah_execute(self, context): # Task execution happens here def get_data_from_ads_output(fields_dict, values, prefix=None): if prefix is None: prefix = "" elif not prefix[-1] == "_": prefix += "_" # e.g. 2b prefix = 'ad_group_criterion_' data = {} for key, value in fields_dict.items(): # e.g. 1 key = 'metrics', value = ['impressions', 'clicks'] # e.g. 2a key = 'ad_group_criterion', value = [{'keyword': ['text', 'match_type']}] # e.g. 2b key = 'keyword', value = ['text', 'match_type'] node = getattr(values, key) # e.g. 1 node = row.metrics # e.g. 2a node = row.ad_group_criterion # e.g. 2b node = row.ad_group_criterion.keyword for item in value: # e.g. 1 item = 'clicks' # e.g. 2a item = {'keyword': ['text', 'match_type']} # e.g. 2b item = 'text' if type(item) == dict: data.update( get_data_from_ads_output( fields_dict=item, values=node, prefix=prefix + key, # e.g. 2a '' + 'ad_group_criterion' )) else: # e.g. 1: {'' + 'metrics' + '_' + 'clicks': row.metrics.clicks.value} # e.g. 2b: {'ad_group_criterion_' + 'keyeword' + '_' + 'text': row.ad_group_criterion.keyword.text.value} if hasattr(getattr(node, item), "value"): data.update({ prefix + key + "_" + item: getattr(node, item).value }) else: # some node ends don't respond to .value but are # already the value data.update({ prefix + key + "_" + item: getattr(node, item) }) return data conn = self.source_conn.extra_dejson credentials = {} for key in self._REQUIRED_KEYS: if not key in conn.keys(): raise Exception( "{0} must be in connection extra json!".format(key)) credentials[key] = conn[key] # build the query query = "SELECT {0} FROM {1} WHERE segments.date {2} {3}".format( ", ".join(self.fields_list), self.resource, "BETWEEN '{0}' AND '{1}'".format( self.data_from.strftime("%Y-%m-%d"), self.data_until.strftime("%Y-%m-%d"), ), ("AND" + " AND ".join(self.conditions)) if self.conditions else "", ) self.log.info("executing this google ads query:\n{0}".format(query)) cli = GoogleAdsClient.load_from_dict(credentials) service = cli.get_service("GoogleAdsService", version="v3") search = service.search( self.client_id.replace("-", ""), query=query, ) data = [row for row in search] # get into uploadable format upload_data = [] fields_dict = deepcopy(self.fields_dict) fields_dict.update({self.resource: ["resource_name"]}) while data: datum = data.pop(0) upload_data += [get_data_from_ads_output( fields_dict, datum, )] self.upload_data(upload_data)