Posts tagged with python

I'm trying to access Google Ads campaing reports from Python folowing this tutorial.

I've requested my Developer Token with Basic Access. I think it has enough privileges to execute the script. I Can see my token active when I go to "API Center" in google ads.

I've created a project in google cloud and an Oauth Token.

In google Cloud:

  • Created a new project
  • Activated the Google Ads API.
  • When I go to Manage-> Credentials I see that the Oauth token is compatible with that API.
  • I have successfully created a refresh token.

I'm using this script as proof of concept:

import os import json import sys from google.ads.google_ads.errors import GoogleAdsException # Put an account id to download stats from. Note: not MCC, no dash lines CUSTOMER_ID = "xxxxxxxxxx" def get_account_id(account_id, check_only=False):     """     Converts int to str, checks if str has dashes. Returns 10 chars str or raises error     :check_only - if True, returns None instead of Error     """     if isinstance(account_id, int) and len(str(account_id)) == 10:         return str(account_id)     if isinstance(account_id, str) and len(account_id.replace("-", "")) == 10:         return account_id.replace("-", "")     if check_only:         return None     raise ValueError(f"Couldn't recognize account id from {account_id}") def micros_to_currency(micros):     return micros / 1000000.0 def main(client, customer_id):          ga_service = client.get_service("GoogleAdsService")#     , version="v5")     query = """         SELECT           campaign.id,           campaign.name,           ad_group.id,           ad_group.name,           ad_group_criterion.criterion_id,           ad_group_criterion.keyword.text,           ad_group_criterion.keyword.match_type,           metrics.impressions,           metrics.clicks,           metrics.cost_micros         FROM keyword_view         WHERE           segments.date DURING LAST_7_DAYS           AND campaign.advertising_channel_type = 'SEARCH'           AND ad_group.status = 'ENABLED'           AND ad_group_criterion.status IN ('ENABLED', 'PAUSED')         ORDER BY metrics.impressions DESC         LIMIT 50"""     # Issues a search request using streaming.     response = ga_service.search_stream(customer_id, query) #THIS LINE GENERATES THE ERROR     keyword_match_type_enum = client.get_type(         "KeywordMatchTypeEnum"     ).KeywordMatchType     try:         for batch in response:             for row in batch.results:                 campaign = row.campaign                 ad_group = row.ad_group                 criterion = row.ad_group_criterion                 metrics = row.metrics                 keyword_match_type = keyword_match_type_enum.Name(                     criterion.keyword.match_type                 )                 print(                     f'Keyword text "{criterion.keyword.text}" with '                     f'match type "{keyword_match_type}" '                     f"and ID {criterion.criterion_id} in "                     f'ad group "{ad_group.name}" '                     f'with ID "{ad_group.id}" '                     f'in campaign "{campaign.name}" '                     f"with ID {campaign.id} "                     f"had {metrics.impressions} impression(s), "                     f"{metrics.clicks} click(s), and "                     f"{metrics.cost_micros} cost (in micros) during "                     "the last 7 days."                 )     except GoogleAdsException as ex:         print(             f'Request with ID "{ex.request_id}" failed with status '             f'"{ex.error.code().name}" and includes the following errors:'         )         for error in ex.failure.errors:             print(f'\tError with message "{error.message}".')             if error.location:                 for field_path_element in error.location.field_path_elements:                     print(f"\t\tOn field: {field_path_element.field_name}")         sys.exit(1) if __name__ == "__main__":     # credentials dictonary     creds = {"google_ads": "googleads.yaml"}     if not os.path.isfile(creds["google_ads"]):         raise FileExistsError("File googleads.yaml doesn't exists. ")     resources = {"config": "config.json"}     # This logging allows to see additional information on debugging     import logging     logging.basicConfig(level=logging.INFO, format='[%(asctime)s - %(levelname)s] %(message).5000s')     logging.getLogger('google.ads.google_ads.client').setLevel(logging.DEBUG)     # Initialize the google_ads client     from google.ads.google_ads.client import GoogleAdsClient     gads_client = GoogleAdsClient.load_from_storage(creds["google_ads"])     id_to_load = get_account_id(CUSTOMER_ID)      main(gads_client, id_to_load) 
  • I've changed CUSTOMER_ID to the account number that appears on the upper left corner
  • I've created a googleads.yaml and I've loaded the aforementioned information.

When I execute the script I get this error:

Traceback (most recent call last):  File "download_keywords_from_account.py", line 138, in <module>    main(gads_client, id_to_load)  File "download_keywords_from_account.py", line 70, in main    response = ga_service.search_stream(customer_id, query)  File "google/ads/google_ads/v6/services/google_ads_service_client.py", line 366, in search_stream    return self._inner_api_calls['search_stream'](request, retry=retry, timeout=timeout, metadata=metadata)  File google/api_core/gapic_v1/method.py", line 145, in __call__    return wrapped_func(*args, **kwargs)  File "google/api_core/retry.py", line 281, in retry_wrapped_func    return retry_target(  File "google/api_core/retry.py", line 184, in retry_target    return target()  File "google/api_core/timeout.py", line 214, in func_with_timeout    return func(*args, **kwargs)  File "google/api_core/grpc_helpers.py", line 152, in error_remapped_callable    six.raise_from(exceptions.from_grpc_error(exc), exc)  File "<string>", line 3, in raise_from google.api_core.exceptions.PermissionDenied: 403 Request had insufficient authentication scopes

The googleads.yaml file looks like this:

  #############################################################################   # Required Fields                                                           #   #############################################################################   developer_token: {developer token as seen in google ads -> tools -> api center}   #############################################################################   # Optional Fields                                                           #   #############################################################################   login_customer_id: {Id from the top left corner in google ads, only numbers}   # user_agent: INSERT_USER_AGENT_HERE   # partial_failure: True   validate_only: False   #############################################################################   # OAuth2 Configuration                                                      #   # Below you may provide credentials for either the installed application or #   # service account flows. Remove or comment the lines for the flow you're    #   # not using.                                                                #   #############################################################################   # The following values configure the client for the installed application   # flow.   client_id: {Oauth client id taken from gcloud -> api -> credentials} ends with apps.googleusercontent.com   client_secret: {got it while generating the token}   refresh_token:  1//0hr.... made with generate_refresh_token.py    # The following values configure the client for the service account flow.   path_to_private_key_file: ads.json   # delegated_account: INSERT_DOMAIN_WIDE_DELEGATION_ACCOUNT   #############################################################################   # ReportDownloader Headers                                                  #   # Below you may specify boolean values for optional headers that will be    #   # applied to all requests made by the ReportDownloader utility by default.  #   #############################################################################   # report_downloader_headers:     # skip_report_header: False     # skip_column_header: False     # skip_report_summary: False     # use_raw_enum_values: False 

NOTES:

The file ads.json contains the private key downloaded from the credentials page in gcloud.

I've seen some posts on this issue but none of them are Python + GoogleADs and I couldn't find a solution there either.

I have also tried other Python + GoogleAds examples getting the same error. This makes me think that I must be configuring something wrong in gcloud / google ads. But I don't understand what.

Please help me make the query I'm really stuck.

Thanks a lot!

I need to modify the blocked IP addresses for a given campaign using the Google Ads API call (version v8). I figured that to add blocked IPs to a given campaign I must create a new campaign criterion, not update an existing one, using the MutateCampaignCriterion endpoint.

My request is

Request: customer_id: "xxxxxxxx" operations {   create {     ip_block {       ip_address: "xxx.x.x.xx"     }     campaign: "customers/xxxxxxx/campaigns/xxxxxxx"   } } validate_only: true 

with the proper numbers instead of the x's. The error I get is

Fault: errors {   error_code {     criterion_error: FIELD_INCOMPATIBLE_WITH_NEGATIVE_TARGETING   }   message: "The field is not allowed to be set when the negative field is set to true, e.g. we don\'t allow bids in negative ad group or campaign criteria."   location {     field_path_elements {       field_name: "operations"       index: 0     }     field_path_elements {       field_name: "create"     }     field_path_elements {       field_name: "ip_block"     }   } } 

Even when I set the negative field to false the same occurs. I don't understand why. Any help would be appreciated, thanks!

I'm trying to pull data from my Google Ads account using their API. I'm using Python

In the code example there is a query where I can specify the date range from which I want to collect results from my campaign.

I would like to dynamically change de date everyday and run the script to get data from the previous day.

My idea was to create a variable with the previous day date in the format Google API is requiering it, named "yesterday".

But I don't know how to use this variable into the query

Here's a part of the code :

import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from datetime import * yesterday_date = date.today() - timedelta(days=1) yesterday = yesterday_date.strftime("%Y-%m-%d") def main(client, customer_id): ga_service = client.get_service("GoogleAdsService") query = """     SELECT       campaign.id,       campaign.name,       metrics.cost_micros,       campaign.status     FROM campaign     WHERE segments.date = '2021-08-19'         """ # Issues a search request using streaming. response = ga_service.search_stream(customer_id=customer_id, query=query) for batch in response:     for row in batch.results:         print(             f"Campaign with ID {row.campaign.id}, status is {row.campaign.status}, cost is {row.metrics.cost_micros} and name "             f'"{row.campaign.name}" was found.'         ) 

I would like to do something like this :

WHERE segments.date = yesterday 

I've tried to use sqlite3 library, to use cursor.execute() but I don't know how to use them properly.

I'm a beginner so the answer might be very easy.

Attempting to use the googleads adwords api

from googleads import adwords 

and get

ModuleNotFoundError: No module named 'googleads' 

I had previous done the

python -m pip install google-ads 

and am running on a macbook pro

How do I resolve this?

Edit

I didn't set up an active virtual environment first, could that be the issue? And as an aside, why is that necessary?

I want to use google-ads in AWS EC2.

I try to install it with, pip install google-ads but this throws an error.

Error:

ssm-user@ip-172-31-47-200:/var/snap/amazon-ssm-agent/3552$ pip install pip install google-ads Collecting pip   Downloading https://files.pythonhosted.org/packages/47/ca/f0d790b6e18b3a6f3bd5e80c2ee4edbb5807286c21cdd0862ca933f751dd/pip-21.1.3-py3-none-any.whl (1.5MB)     100% |████████████████████████████████| 1.6MB 871kB/s Collecting install   Downloading https://files.pythonhosted.org/packages/f0/a5/fd2eb807a9a593869ee8b7a6bcb4ad84a6eb31cef5c24d1bfbf7c938c13f/install-1.3.4-py3-none-any.whl Collecting google-ads Collecting grpcio<2.0.0,>=1.33.2 (from google-ads)   Using cached https://files.pythonhosted.org/packages/cd/80/4b65b06e35599af065076891248b88d16c87cee1121b8886316ad4343f50/grpcio-1.38.1.tar.gz Collecting PyYAML<6.0,>=5.1 (from google-ads)   Using cached https://files.pythonhosted.org/packages/7a/5b/bc0b5ab38247bba158504a410112b6c03f153c652734ece1849749e5f518/PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl Collecting google-auth-oauthlib<1.0.0,>=0.3.0 (from google-ads)   Using cached https://files.pythonhosted.org/packages/9d/d3/7541e89f1fc456eef157224f597a8bba22589db6369a03eaba68c11f07a0/google_auth_oauthlib-0.4.4-py2.py3-none-any.whl Collecting google-api-core<2.0.0,>=1.21.0 (from google-ads)   Using cached https://files.pythonhosted.org/packages/f6/72/6dc3c3c4576fedc409fd825bf71e22d0f448bd68143c79cdbd6216744282/google_api_core-1.30.0-py2.py3-none-any.whl Collecting dataclasses<1.0.0,>=0.6; python_version < "3.7" (from google-ads)   Using cached https://files.pythonhosted.org/packages/fe/ca/75fac5856ab5cfa51bbbcefa250182e50441074fdc3f803f6e76451fab43/dataclasses-0.8-py3-none-any.whl Collecting nox==2020.12.31 (from google-ads)   Using cached https://files.pythonhosted.org/packages/d3/a6/6a6a1cca717bf241323ec1bfa5b679b643437fee3c26af2387d3766a8986/nox-2020.12.31-py3-none-any.whl Collecting proto-plus<2.0.0,>=1.18.0 (from google-ads)   Using cached https://files.pythonhosted.org/packages/8c/72/6f3f4cdc5bb0294f8d7f3f8aacb617b4c3cb17554ed78f7e28009162c795/proto_plus-1.19.0-py3-none-any.whl Collecting setuptools>=40.3.0 (from google-ads)   Using cached https://files.pythonhosted.org/packages/a2/e1/902fbc2f61ad6243cd3d57ffa195a9eb123021ec912ec5d811acf54a39f8/setuptools-57.1.0-py3-none-any.whl Collecting googleapis-common-protos<2.0.0,>=1.5.8 (from google-ads)   Using cached https://files.pythonhosted.org/packages/55/08/796a6bc0b550e2b7116041c953d3d5100016abea106131d71e5651826e7b/googleapis_common_protos-1.53.0-py2.py3-none-any.whl Collecting pep562<2.0,>=1.0 (from google-ads)   Using cached https://files.pythonhosted.org/packages/8f/b9/8a74b93c643b54cc7579087ff6a56aa1a9c52329be6846abfbaee4a7828b/pep562-1.1-py2.py3-none-any.whl Collecting six>=1.5.2 (from grpcio<2.0.0,>=1.33.2->google-ads)   Using cached https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl Collecting google-auth>=1.0.0 (from google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/6e/1d/e4718af587967b8fb6ac7e0e257809934005a3f8fde8f31a304c7e682874/google_auth-1.32.1-py2.py3-none-any.whl Collecting requests-oauthlib>=0.7.0 (from google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/a3/12/b92740d845ab62ea4edf04d2f4164d82532b5a0b03836d4d4e71c6f3d379/requests_oauthlib-1.3.0-py2.py3-none-any.whl Collecting protobuf>=3.12.0 (from google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/53/4e/e2db88d0bb0bda6a879eea62fddbaf813719ce3770d458bc5580512d9c95/protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl Collecting requests<3.0.0dev,>=2.18.0 (from google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/29/c1/24814557f1d22c56d50280771a17307e6bf87b70727d975fd6b2ce6b014a/requests-2.25.1-py2.py3-none-any.whl Collecting packaging>=14.3 (from google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/3c/77/e2362b676dc5008d81be423070dd9577fa03be5da2ba1105811900fda546/packaging-21.0-py3-none-any.whl Collecting pytz (from google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/70/94/784178ca5dd892a98f113cdd923372024dc04b8d40abe77ca76b5fb90ca6/pytz-2021.1-py2.py3-none-any.whl Collecting virtualenv>=14.0.0 (from nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/03/08/f819421002e85a71d58368f7bffbe0b1921325e0e8ca7857cb5fb0e1f7c1/virtualenv-20.4.7-py2.py3-none-any.whl Collecting argcomplete<2.0,>=1.9.4 (from nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/b7/9e/9dc74d330c07866d72f62d553fe8bdbe32786ff247a14e68b5659963e6bd/argcomplete-1.12.3-py2.py3-none-any.whl Collecting py<2.0.0,>=1.4.0 (from nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/67/32/6fe01cfc3d1a27c92fdbcdfc3f67856da8cbadf0dd9f2e18055202b2dc62/py-1.10.0-py2.py3-none-any.whl Collecting colorlog<5.0.0,>=2.6.1 (from nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/51/62/61449c6bb74c2a3953c415b2cdb488e4f0518ac67b35e2b03a6d543035ca/colorlog-4.8.0-py2.py3-none-any.whl Collecting importlib-metadata; python_version < "3.8" (from nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/3f/e1/e5bba549a033adf77448699a34ecafc7a32adaeeb4369396b35f56d5cc3e/importlib_metadata-4.6.1-py3-none-any.whl Collecting cachetools<5.0,>=2.0.0 (from google-auth>=1.0.0->google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/bf/28/c4f5796c67ad06bb91d98d543a5e01805c1ff065e08871f78e52d2a331ad/cachetools-4.2.2-py3-none-any.whl Collecting pyasn1-modules>=0.2.1 (from google-auth>=1.0.0->google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/95/de/214830a981892a3e286c3794f41ae67a4495df1108c3da8a9f62159b9a9d/pyasn1_modules-0.2.8-py2.py3-none-any.whl Collecting rsa<5,>=3.1.4; python_version >= "3.6" (from google-auth>=1.0.0->google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/e9/93/0c0f002031f18b53af7a6166103c02b9c0667be528944137cc954ec921b3/rsa-4.7.2-py3-none-any.whl Collecting oauthlib>=3.0.0 (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/e8/5d/9dd1c29e5a786525f6342f6c1d812ed2e37edc653ad297048c1668988053/oauthlib-3.1.1-py2.py3-none-any.whl Collecting urllib3<1.27,>=1.21.1 (from requests<3.0.0dev,>=2.18.0->google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/5f/64/43575537846896abac0b15c3e5ac678d787a4021e906703f1766bfb8ea11/urllib3-1.26.6-py2.py3-none-any.whl Collecting chardet<5,>=3.0.2 (from requests<3.0.0dev,>=2.18.0->google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/19/c7/fa589626997dd07bd87d9269342ccb74b1720384a4d739a1872bd84fbe68/chardet-4.0.0-py2.py3-none-any.whl Collecting idna<3,>=2.5 (from requests<3.0.0dev,>=2.18.0->google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl Collecting certifi>=2017.4.17 (from requests<3.0.0dev,>=2.18.0->google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/05/1b/0a0dece0e8aa492a6ec9e4ad2fe366b511558cdc73fd3abc82ba7348e875/certifi-2021.5.30-py2.py3-none-any.whl Collecting pyparsing>=2.0.2 (from packaging>=14.3->google-api-core<2.0.0,>=1.21.0->google-ads)   Using cached https://files.pythonhosted.org/packages/8a/bb/488841f56197b13700afd5658fc279a2025a39e22449b7cf29864669b15d/pyparsing-2.4.7-py2.py3-none-any.whl Collecting filelock<4,>=3.0.0 (from virtualenv>=14.0.0->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/93/83/71a2ee6158bb9f39a90c0dea1637f81d5eef866e188e1971a1b1ab01a35a/filelock-3.0.12-py3-none-any.whl Collecting distlib<1,>=0.3.1 (from virtualenv>=14.0.0->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/87/26/f6a23dd3e578132cf924e0dd5d4e055af0cd4ab43e2a9f10b7568bfb39d9/distlib-0.3.2-py2.py3-none-any.whl Collecting importlib-resources>=1.0; python_version < "3.7" (from virtualenv>=14.0.0->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/c3/8d/cb49c07dd01e797e76e86f33c3472ebd861216b57296095f5c17be9b79e8/importlib_resources-5.2.0-py3-none-any.whl Collecting appdirs<2,>=1.4.3 (from virtualenv>=14.0.0->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl Collecting typing-extensions>=3.6.4; python_version < "3.8" (from importlib-metadata; python_version < "3.8"->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/2e/35/6c4fff5ab443b57116cb1aad46421fb719bed2825664e8fe77d66d99bcbc/typing_extensions-3.10.0.0-py3-none-any.whl Collecting zipp>=0.5 (from importlib-metadata; python_version < "3.8"->nox==2020.12.31->google-ads)   Using cached https://files.pythonhosted.org/packages/92/d9/89f433969fb8dc5b9cbdd4b4deb587720ec1aeb59a020cf15002b9593eef/zipp-3.5.0-py3-none-any.whl Collecting pyasn1<0.5.0,>=0.4.6 (from pyasn1-modules>=0.2.1->google-auth>=1.0.0->google-auth-oauthlib<1.0.0,>=0.3.0->google-ads)   Using cached https://files.pythonhosted.org/packages/62/1e/a94a8d635fa3ce4cfc7f506003548d0a2447ae76fd5ca53932970fe3053f/pyasn1-0.4.8-py2.py3-none-any.whl Building wheels for collected packages: grpcio   Running setup.py bdist_wheel for grpcio ... / 

After this, a wired thing happen my ssh stop responding until I restart the AWS EC2


My Environment

  • Python version = 3.6.9
  • pip verions = 9.0.1
  • Ubuntu version = 8.04.5 LTS (Bionic Beaver)


Note: I also have REST API use Nginx reverse proxy a Node server via pm2