Posts tagged with google-ads-api

I am following this package: https://github.com/googleads/google-ads-php. Here they said that I need to run this page:

https://github.com/googleads/google-ads-php/blob/main/examples/Authentication/GenerateUserCredentials.php

to terminal.

and I did it like:

php /locaation of the fie/GenerateUserCredentials.php 

After that I can get a link which is something like that:

https://accounts.google.com/o/oauth2/v2/auth?response_type=code&access_type=offline&client_id=535777736006-d1rp8msevnls2pmihk7b8l23j3vra7duh.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fcallback&state=4e23ce963534701029c1a22d2de7848d034d8b0b0&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadwords

(Above link is demo purpose)

So, When I click on this link I redirect to my google account and give access to them and after that I redirect back to this following URL:

http://localhost:3000/auth/callback?state=fddbaae6583b15aba552f682fe9f018233388533555f&code=4%2F0AfgeXvs4NV49mrqEBrl81ATRnXhqcu9x9ja8SAbaENSWhmNejGRGkZJE_AcD1aAFWdrlGg&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fadwords

Here you can see I have 2 params which is state and code.

Now my question is how can I get the access token and refresh token using this URL?

I have multiple keywords for which I am looking for some related keyword ideas along with their metrics. For that, I am using google-ads-api's GenerateKeywordIdeasRequest. It takes a list of keywords, but right now I am passing a single keyword at a time. After that I convert the output into a dataframe and pick the top 3 keywords ideas based on their monthly search volume.

for example: if passed "bottle", it would return

and from there I would extract the top 3 keyword searches suggested for "bottle".

But with this approach, it takes a lot of time to generate ideas for all input keywords. So I tried passing all input keywords at once, which reduce the processing time dramatically but the issue is, I am not able to get the top 3 suggested keyword for each input keyword separately as all suggested keywords ideas for each input are now mixed. And It is hard to tell which is suggested for which passed input.

Here is the code I am using

import pandas as pd from google.ads.googleads.client import GoogleAdsClient class GoogleAD:     def __init__(self):       pass          def get_keywords_search_volume(client, customer_id, location_ids, language_id, keyword_texts, page_url= None):         """function to get keyword search volume from google ads API """         keyword_plan_idea_service = client.get_service("KeywordPlanIdeaService")         keyword_competition_level_enum = (client.enums.KeywordPlanCompetitionLevelEnum)         keyword_plan_network = (client.enums.KeywordPlanNetworkEnum.GOOGLE_SEARCH_AND_PARTNERS)         location_rns = GoogleAD.map_locations_ids_to_resource_names(client, location_ids)         language_rn = client.get_service("GoogleAdsService").language_constant_path(language_id)                  # Either keywords or a page_url are required to generate keyword ideas         # so this raises an error if neither are provided.         if not (keyword_texts or page_url):             raise ValueError(                 "At least one of keywords or page URL is required, "                 "but neither was specified."             )                  # Only one of the fields "url_seed", "keyword_seed", or         # "keyword_and_url_seed" can be set on the request, depending on whether         # keywords, a page_url or both were passed to this function.         request = client.get_type("GenerateKeywordIdeasRequest")         request.customer_id = customer_id         request.language = language_rn         request.geo_target_constants = location_rns         request.include_adult_keywords = False         request.keyword_plan_network = keyword_plan_network                  # To generate keyword ideas with only a page_url and no keywords we need         # to initialize a UrlSeed object with the page_url as the "url" field.         if not keyword_texts and page_url:             request.url_seed.url = page_url                  # To generate keyword ideas with only a list of keywords and no page_url         # we need to initialize a KeywordSeed object and set the "keywords" field         # to be a list of StringValue objects.         if keyword_texts and not page_url:             request.keyword_seed.keywords.extend(keyword_texts)                  # To generate keyword ideas using both a list of keywords and a page_url we         # need to initialize a KeywordAndUrlSeed object, setting both the "url" and         # "keywords" fields.         if keyword_texts and page_url:             request.keyword_and_url_seed.url = page_url             request.keyword_and_url_seed.keywords.extend(keyword_texts)                  keyword_ideas = keyword_plan_idea_service.generate_keyword_ideas(request=request)                  for idea in keyword_ideas:             competition_value = idea.keyword_idea_metrics.competition.name         return keyword_ideas          def map_locations_ids_to_resource_names(client, location_ids):             """Converts a list of location IDs to resource names.             Args:                 client: an initialized GoogleAdsClient instance.                 location_ids: a list of location ID strings.             Returns:                 a list of resource name strings using the given location IDs.             """             build_resource_name = client.get_service(                 "GeoTargetConstantService"             ).geo_target_constant_path             return [build_resource_name(location_id) for location_id in location_ids]          def get_keyword_df(key_word):          """function to generate dataframe with keyword search volume"""         try:             client = GoogleAdsClient.load_from_storage('desc.yaml')             list_keywords = GoogleAD.get_keywords_search_volume(client, "686xxxxx647", ["2840"], "1000", key_word, None)             keyword_df = pd.DataFrame()             for idea in list_keywords:                 keyword_dict = {}                 competition_value = idea.keyword_idea_metrics.competition.name                 idea_text = idea.text                 monthly_search_volume = idea.keyword_idea_metrics.avg_monthly_searches                 keyword_dict['idea_text'] = idea_text                 keyword_dict['monthly_search_volume'] = int(monthly_search_volume)                 keyword_dict['competition_value'] = competition_value                 keyword_dict['key_word'] = key_word                 keyword_dict['key_word_modified'] = key_word.replace('%',' percent')                 keyword_series = pd.Series(keyword_dict)                 keyword_df = keyword_df.append(keyword_series, ignore_index = True)         except Exception as e:             print(e)             # print(e.args[2])             keyword_df = pd.DataFrame()         return keyword_df suggestion_df = GoogleAD.get_keyword_df(['bottle']) 

Let me know if there's any more information I can provide.

I am trying to build a report that shows metrics such as clicks, impressions and costs per targeted location from Google Ads.

I compare these numbers with Campaigns stats and it does not match. I got lower number from Geo stats actually. On the other hand, in google Ads application, the numbers are the same.

(When I compare Ads stats with Campaing stats, it is matching for 100 %)

Would you know how what I am doing wrong? How the query from geo stats should look to match with Campaign stats?

Thanks for help.

select sum(Clicks) FROM `ct-gtm.Google_Ads_Manager_Account.CampaignBasicStats` as stats where stats.Date between '2022-10-01' and '2022-10-31' select sum(Clicks) from `ct-gtm.Google_Ads_Manager_Account.GeoStats_3749539878` as stats where stats.Date between '2022-10-01' and '2022-10-31' and IsTargetingLocation = true I would expect the same numbers but geo stats result is smaller. 

I'm trying to use selenium to download reports from Google Ads, the script is working fine until I try to click the Campaign-wide target button in the image, It's not showing in the DOM and selenium can't see it until I click/inspect it that it's accessible.

I tried to switch frames and search for it but to no avail, I have only two frames when I try

iframes = b.driver.find_elements(By.XPATH, "//iframe")

Code:

from selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager from time import sleep from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC import csv class Bot:     def __init__(self, user_data_dir=None, profile_dir=None, csv_filename=None):         self.__service = ChromeService(ChromeDriverManager().install())         self.user_data_dir = user_data_dir          self.profile_dir = profile_dir         self.__options = webdriver.ChromeOptions()         self.__options.add_argument(f"user-data-dir={self.user_data_dir}")         self.__options.add_argument(f"--profile-directory={self.profile_dir}")         self.csv_filename = csv_filename or "data.csv"         self.driver = webdriver.Chrome(service=self.__service, options=self.__options)       def login(self):         self.driver.get("https://ads.google.com")         sleep(1)         try:             # get the sign in button and click it             sign_in_btn = self.driver.find_element(By.XPATH, '//*[@id="header-topbar"]/div/div[3]/div/div[3]/a')             sign_in_btn.click()             sleep(2)                      except Exception as e:             print(e)             # if the sign in button is not found, try clicking the drawer menu button and then the sign in button             drawer_btn = self.driver.find_element(By.XPATH, '//*[@id="header-drawer"]/div/div/div/div[1]/div/button')             drawer_btn.click()             sleep(2)                          sign_in_btn = self.driver.find_element(By.XPATH, '//*[@id="header-topbar"]/div/div[3]/div/div[3]/a')             sign_in_btn.click()             sleep(2)         finally:             accnt_btn = self.driver.find_element(By.XPATH, '/html/body/div[1]/root/div[2]/nav-view-loader/multiaccount-view/div/div[2]/div/div[1]/material-list/material-list-item[4]/div/div[1]')             accnt_btn.click()             sleep(5)          def do(self):         self.login()         # get the campaigns button dropdown button and click it         campaigns_drpdwn_btn = self.driver.find_element(By.XPATH, '/html/body/div[2]/root/div/div[1]/div/div/div[3]/div/div/awsm-skinny-nav/nav/div[1]/div[3]/awsm-skinny-nav-item[1]/a/material-ripple')         campaigns_drpdwn_btn.click()         sleep(2)         # TODO get all the campaigs lists and click on each one of them         # get a certain campaign and click it         campaign_btn = self.driver.find_element(By.XPATH, '//*[@id="cmExtensionPoint-id"]/base-root/div/div[2]/div[1]/view-loader/campaign-view/tableview/div[6]/ess-table/ess-particle-table/div[1]/div/div[2]/div[3]/ess-cell[2]/campaign-name/campaign-name-generic/a')         campaign_btn.click()         sleep(2)         # campaign more details button         campaign_more_details_btn = self.driver.find_element(By.XPATH, '/html/body/div[2]/root/div/div[1]/div/div/div[3]/div/content-header/deferred-infosnack/infosnack/div/div[1]/review-panel-trigger/button/div[2]')         campaign_more_details_btn.click()         sleep(5)         # get the bid strategy button, using the 'Maximize conversions' text as a span and click it         campaign_bid_strategy_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Maximize conversions')]")         campaign_bid_strategy_btn.click()         sleep(4)         # get the campaign simulator button and click it         campaign_sim_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Campaign simulator')]")         campaign_sim_btn.click()         sleep(2)         # get the campaign simulator target dropdown and click it [%, campaign wide target]         campaign_sim_target_dropdn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Target scaling')]")         campaign_sim_target_dropdn.click()         sleep(2)         campaign_wide_target_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Campaign-wide target')]")         campaign_wide_target_btn.click()         sleep(2) 

I'm trying to get selenium to see the button, any help would be appreciated.

The Image shows the overview of ads related to an ad account, I need to find the cost marked in the pic through API

I tried with

 ad_group metrics.average_cost, metrics.cost,      account_budget.amount_served_micros,      account_budget.total_adjustments_micros,      account_budget.proposed_spending_limit_micros,     account_budget_proposal.account_budget,     account_budget_proposal.approved_spending_limit_micros,      account_budget_proposal.proposed_spending_limit_micros,      campaign.campaign_budget,      campaign_budget.amount_micros,      campaign_budget.total_amount_micros 

most of the values I got in these are zero or not relevant to the cost in the overview (marked in pic) . Can someone help me find the cost value( which is marked in the image) in the ads overview screen through GoogleAds API.