Posts tagged with google-ads-api

I am very new to Python and Stackoverflow. I am working on connecting my Google Ads account with Python to automate few standard charts creation and email them to my team members. Please help me resolve this as I had not been able to find an answer to it upon Googling either. Let me know if I have missed out on any info which might provide more context to the question here.

I have been using the steps as mentioned by @msaniscalchi. Created client ID and client Secret from https://console.developers.google.com and created googleads.yaml file in the same directory as the generate_refresh_token.py. When I run the script with respective client ID and client Secret values, I am getting "invalid syntax" error. I have verified my multiple times my client secret and ID values multiple times.

"""Generates refresh token for AdWords using the Installed Application flow.""" import argparse import sys from google_auth_oauthlib.flow import InstalledAppFlow from oauthlib.oauth2.rfc6749.errors import InvalidGrantError # Your OAuth2 Client ID and Secret. If you do not have an ID and Secret yet, # please go to https://console.developers.google.com and create a set. DEFAULT_CLIENT_ID = 609XXXXXXX22-58mbhXXXXXXXXXXXXXXXXXX6ri.apps.googleusercontent.com DEFAULT_CLIENT_SECRET = 7uO7XXXXXXXXXXXXXX7dKBAP # The AdWords API OAuth2 scope. SCOPE = u'https://www.googleapis.com/auth/adwords' # The redirect URI set for the given Client ID. The redirect URI for Client ID # generated for an installed application will always have this value. _REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' parser = argparse.ArgumentParser(description='Generates a refresh token with '                                  'the provided credentials.') parser.add_argument('--client_id', default=DEFAULT_CLIENT_ID,                     help='Client Id retrieved from the Developer\'s Console.') parser.add_argument('--client_secret', default=DEFAULT_CLIENT_SECRET,                     help='Client Secret retrieved from the Developer\'s '                     'Console.') parser.add_argument('--additional_scopes', default=None,                     help='Additional scopes to apply when generating the '                     'refresh token. Each scope should be separated by a comma.') class ClientConfigBuilder(object):   """Helper class used to build a client config dict used in the OAuth 2.0 flow.   """   _DEFAULT_AUTH_URI = 'https://accounts.google.com/o/oauth2/auth'   _DEFAULT_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'   CLIENT_TYPE_WEB = 'web'   CLIENT_TYPE_INSTALLED_APP = 'installed'   def __init__(self, client_type=None, client_id=None, client_secret=None,                auth_uri=_DEFAULT_AUTH_URI, token_uri=_DEFAULT_TOKEN_URI):     self.client_type = client_type     self.client_id = client_id     self.client_secret = client_secret     self.auth_uri = auth_uri     self.token_uri = token_uri   def Build(self):     """Builds a client config dictionary used in the OAuth 2.0 flow."""     if all((self.client_type, self.client_id, self.client_secret,             self.auth_uri, self.token_uri)):       client_config = {           self.client_type: {               'client_id': self.client_id,               'client_secret': self.client_secret,               'auth_uri': self.auth_uri,               'token_uri': self.token_uri           }       }     else:       raise ValueError('Required field is missing.')     return client_config def main(client_id, client_secret, scopes):   """Retrieve and display the access and refresh token."""   client_config = ClientConfigBuilder(       client_type=ClientConfigBuilder.CLIENT_TYPE_WEB, client_id=client_id,       client_secret=client_secret)   flow = InstalledAppFlow.from_client_config(       client_config.Build(), scopes=scopes)   # Note that from_client_config will not produce a flow with the   # redirect_uris (if any) set in the client_config. This must be set   # separately.   flow.redirect_uri = _REDIRECT_URI   auth_url, _ = flow.authorization_url(prompt='consent')   print('Log into the Google Account you use to access your AdWords account '         'and go to the following URL: \n%s\n' % auth_url)   print('After approving the token enter the verification code (if specified).')   code = input('Code: ').strip()   try:     flow.fetch_token(code=code)   except InvalidGrantError as ex:     print('Authentication has failed: %s' % ex)     sys.exit(1)   print('Access token: %s' % flow.credentials.token)   print('Refresh token: %s' % flow.credentials.refresh_token) if __name__ == '__main__':   args = parser.parse_args()   configured_scopes = [SCOPE]   if not (any([args.client_id, DEFAULT_CLIENT_ID]) and           any([args.client_secret, DEFAULT_CLIENT_SECRET])):     raise AttributeError('No client_id or client_secret specified.')   if args.additional_scopes:     configured_scopes.extend(args.additional_scopes.replace(' ', '').split(','))   main(args.client_id, args.client_secret, configured_scopes) 

When I run the above code, I am getting the "Invalid Syntax" error highlighting at the numeric part of the Client ID and Secret.

Syntax error screenshot attached here

Editor Highlighter screenshot attached here

I'm using Google AdWords Python SDK to create ResponsiveDisplayAds. My code is like below.

adgroup_ad_service = adwords_client.GetService(     service_name = "AdGroupAdService",     version = "v201809" ) operations = [{     'operator': 'ADD',     'operand': {         'xsi_type': 'AdGroupAd',         'adGroupId': '<AD_GROUP_ID>',         'ad': {             'xsi_type': 'ResponsiveDisplayAd',             'marketingImage': {                 'mediaId': '<MEDIA_ID>'             },             'shortHeadline': 'Short Headline',             'longHeadline': 'This is a very long headline',             'description': 'This is a description',             'businessName': 'Test Business Name',             'finalUrls': ['https://www.google.com'],             'squareMarketingImage': {                 'mediaId': '<MEDIA_ID>'             }         },         'status': 'PAUSED'     } }] ads_response = adgroup_ad_service.mutate(operations) print("AD RESPONSE : {}".format(ads_response)) 

But It's giving me, AdGroupAdError.CANNOT_CREATE_DEPRECATED_ADS.

According to the documentation it describe this error as An ad of this type is deprecated and cannot be created. Only deletions are permitted..

But in documentation of the AdGroupAd ResponsiveDisplayAd, is one of the accepted Ad types.

So it would be great if someone can point me a direction to resolve this issue.

our marketing team is running adwords for our google store ad campaign. they wants to check if an app installation event is triggered when a user clicked on the advertised link or not. (probably like conversion tracking for installation via adwords). is there anyway we can do this?

I'm developing an integration between existing CPA system and Google AdWords. Conversions are stored in the system, and the goal is to periodically, as a background task, parse conversions and send them to user's Google Ad account.

Here's what I figured so far:

  1. I need a google application to which users will grant permission to push data to their ad account.
  2. I need Oauth2 credentials to authorize my application AND users credentials to authorize the API request.

The process of creating and storing gclid is out of concern right now.

I use php client library https://github.com/googleads/googleads-php-lib, which has adsapi_php.ini configuration file. In this file, there are developer token, manager's account client ID, and OAuth2 credentials (cliendId, clientSecret, refreshToken).

However, when user gives access to my application via consent screen, I create OAuth2 object as follows:

 $oAuth2Credential = new OAuth2([         'authorizationUri'   => 'https://accounts.google.com/o/oauth2/v2/auth',         'tokenCredentialUri' => 'https://www.googleapis.com/oauth2/v4/token',         'redirectUri'        => '<myEndpoint>',         'clientId'           => '<myClientId>',         'clientSecret'       => '<myClientSecret>',         'scope'              => 'https://www.googleapis.com/auth/adwords'     ]); 

If I understand correctly, I absolutely need to have web application OAuth credentials in order to have a callback to save user's access and refresh tokens, to use them later in my background task.

1) Does this credentials and the ones in adsapi_ini.php file has to be the same?

I've tried to generate a refresh token for my web type credentials to use in conf file, but it did not work. Right now I'm able to get a valid response when I have credentials for application type 'other' in the configuration file, and 'web' application credentials in Oauth2 object for getting user credentials, but I'm not sure this is correct way to do it.

2) How to authorize API request to push data to certain user's account?

Here's sample code:

 $session = (new AdWordsSessionBuilder())         ->fromFile()         ->withOAuth2Credential($oAuth2Credential)         ->withClientCustomerId('<client-customer-id>')         ->build(); 

As I understand, session object is essential to build any further queries, including uploding conversions.

->fromFile() uses mentined configuration file to get my token and Auth data - basically authorize my application.

$oAuth2Credential is the OAuth2 object containing specific user's authorization data. The problem is that in documentation, this object is created by builder and uses the same method fromFile(), and I don't understand what data it must contain.

I store access_token and refresh_token in my database, and right now I'm building OAuth object as follows:

$oAuth2Credential = new OAuth2([         'authorizationUri'   => 'https://accounts.google.com/o/oauth2/v2/auth',         'tokenCredentialUri' => 'https://www.googleapis.com/oauth2/v4/token',         'redirectUri'        => '<myEndpoint>',         'clientId'           => '<myClientId>',         'clientSecret'       => '<myClientSecret>',         'scope'              => 'https://www.googleapis.com/auth/adwords',         'access_token'       => '<user_access_token>'     ]); 

So basically just adding access_token to parameters that I'm using for getting this token from user. It works, but doesn't look like correct way to do this.

3) How to manage user's token expiration?

Documentation says that client library automatically handles refreshing tokens, but I don't understand how it will work in my case. Do I need to pass access_token with refresh_token in OAuth object when making API request and then it will refresh automatically, or do I need separate worker to periodically refresh user tokens to keep them valid?

I want to fetch location details for all the ads from google adwords but I am getting null entries.I am not able to get any data from adwords api .Help me in That as according to my knowledge there is not problem with my code and I am not able to find any solution for that.My code that I have tried is written below.

 public void GetLocationAds()             {                 AdWordsUser user = new AdWordsUser();                 {                     try                     {                         int offset = 0;                                                                 // Create selector.                         using (CampaignCriterionService campaignCriterionService =                             (CampaignCriterionService)user.GetService(AdWordsService.v201809.CampaignCriterionService))                         {                             Selector selector = new Selector()                             {                                 fields = new string[]                              {                                   CampaignCriterion.Fields.CampaignId,                                     CampaignCriterion.Fields.CampaignCriterionStatus,                                      //Location.Fields.LocationName,                                      //Location.Fields.CriteriaType,                                      //Location.Fields.ParentLocations,                                      //LocationCriterion.Fields.CanonicalName,                                      //LocationCriterion.Fields.CountryCode,                                   CampaignCriterion.Fields.IsNegative,                              },                            //     predicates = new Predicate[]                            //{                            //    Predicate.Equals( "CriteriaType","LOCATION"),                            //},                                 paging = Paging.Default,                                 ordering = new OrderBy[]                        {                                 OrderBy.Asc(  CampaignCriterion.Fields.CampaignId)                        }                             };                             CampaignCriterionPage page = new CampaignCriterionPage();                             do                             {                                 // Get the ad groups.                                  page = campaignCriterionService.get(selector);                                 // Display the results.                                 if (page != null && page.entries != null)                                 {                                     int j = selector.paging.startIndex;                                     foreach (CampaignCriterion campaignCriterion in page.entries)                                     {                                         var campaignId = campaignCriterion.campaignId;                                         bool IsLocation = campaignCriterion.isNegative;                                         var CampaignCriterionType = campaignCriterion.CampaignCriterionType;                                     }                                 }                                 else                                 {                                     Console.Write("No campaignCriterion were found.");                                 }                                 selector.paging.IncreaseOffset();                             }                             while (selector.paging.startIndex < page.totalNumEntries);                         }                     }                     catch (Exception ex)                     {                     }                 }             } 

Kindly help me in that.