Question

I am having trouble generating a refresh token using Python for the AdWords API & need some help. Here is the situation:

  • I have a client on AdWords that I want to pull reports for through the AdWords API (we have a developer token now for this). Let's say that, in AdWords, the clients account is 521-314-0974 (making this up). Here is where I am confused:

Below is the following code snippet needed to generate a refresh token that I am trying to get working:

"""Generates a refresh token for use with AdWords."""

__author__ = 'Nathaniel Payne'

import sys
import urllib2

from oauthlib import oauth2

# Your OAuth 2.0 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.
CLIENT_ID = 'INSERT_CLIENT_ID_HERE'
CLIENT_SECRET = 'INSERT_CLIENT_SECRET_HERE'

# You may optionally provide an HTTPS proxy.
HTTPS_PROXY = None

# The AdWords API OAuth 2.0 scope.
SCOPE = u'https://adwords.google.com/api/adwords'
# This callback URL will allow you to copy the token from the success screen.
CALLBACK_URL = 'urn:ietf:wg:oauth:2.0:oob'
# The HTTP headers needed on OAuth 2.0 refresh requests.
OAUTH2_REFRESH_HEADERS = {'content-type':
                          'application/x-www-form-urlencoded'}
# The web address for generating new OAuth 2.0 credentials at Google.
GOOGLE_OAUTH2_AUTH_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth'
GOOGLE_OAUTH2_GEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'


def main():
  oauthlib_client = oauth2.WebApplicationClient(CLIENT_ID)

  authorize_url = oauthlib_client.prepare_request_uri(
      GOOGLE_OAUTH2_AUTH_ENDPOINT, redirect_uri=CALLBACK_URL, scope=SCOPE)
  print ('Log in to your AdWords account and open the following URL: \n%s\n' %
         authorize_url)
  print 'After approving the token enter the verification code (if specified).'
  code = raw_input('Code: ').strip()

  post_body = oauthlib_client.prepare_request_body(
      client_secret=CLIENT_SECRET, code=code, redirect_uri=CALLBACK_URL)
  if sys.version_info[0] == 3:
    post_body = bytes(post_body, 'utf8')
  request = urllib2.Request(GOOGLE_OAUTH2_GEN_ENDPOINT, post_body,
                            OAUTH2_REFRESH_HEADERS)
  if HTTPS_PROXY:
    request.set_proxy(HTTPS_PROXY, 'https')
  raw_response = urllib2.urlopen(request).read().decode()
  oauth2_credentials = oauthlib_client.parse_request_body_response(raw_response)

  print ('Your access token is %s and your refresh token is %s'
         % (oauth2_credentials['access_token'],
            oauth2_credentials['refresh_token']))
  print ('You can cache these credentials into a yaml file with the '
         'following keys:\nadwords:\n  client_id: %s\n  client_secret: %s\n'
         '  refresh_token: %s\n'
         % (CLIENT_ID, CLIENT_SECRET, oauth2_credentials['refresh_token']))


if __name__ == '__main__':
  main()

Questions: 1) Do I need to have a special project set-up for every AdWords customer in the console.developers.google.com, in order to pull from the AdWords Reporting API? Or, can I simply provide the client secret and ID for a generic account in the console?

2) Following from this, can someone please confirm what should go in place of the client_ID & Client_Secret in order to make the Python code block below work. What I mean is, I was using the client ID and client secret from https://console.developers.google.com ... for the analytics account that we have billing set-up on (and which I have used for BigQuery API access previously). Is that correct? I am not seeing clearly how this will be linked to the AdWords account for this client.

2) In the consent screen, I put my own e-mail, since I am owner of the project,. That said, when I run the code, I get the link to the URL that I need to run to generate the code. That said, when I sun this snippet:

print ('Log in to your AdWords account and open the following URL: \n%s\n' %
             authorize_url)
      print 'After approving the token enter the verification code (if specified).'
      code = raw_input('Code: ').strip()

I get an error. This is the message that I get in error:

Error: redirect_uri_mismatch
The redirect URI in the request: urn:ietf:wg:oauth:2.0:oob did not match a registered redirect URI

Learn more
    Request Details
    cookie_policy_enforce=false
    scope=https://adwords.google.com/api/adwords
    response_type=code
    access_type=online
    redirect_uri=urn:ietf:wg:oauth:2.0:oob
    display=page
    client_id=XXXXXXXXX.apps.googleusercontent.com

I am puzzled here. Some folks suggested changing the e-mail address in the consent screen (which I did ... but was unsuccessful). Again, my simple goal is to be able to pull one report from tis clients through the AdWords API (which I will expand once I get there). Any help would be appreciated. Cheers.

Was it helpful?

Solution

After some work, I was able to successfully navigate through this issue. Here are the detailed steps that I took to get to the point where I could successfully pull data through the API. In my situation, I manage an AdWords MCC with multiple accounts. Thus, I went back to the beginning of many of the help manuals and did the following:

  1. Create a new project called AdWords-API-XXXX.
  2. In the credentials screen on the console, I created a new "Client ID for native application". This allowed me to generate my CLIENT_ID and the CLIENT_SECRET that I needed. Critically, it also generated a re-direct URI which was the source of my problem.
  3. I took both of these values, added them to the main script, and ran the generate_refresh_token.py script. This allowed me to generate a working refresh token. I had to be signed into my AdWords account MCC, in order to make sure that OAuth2 provided me the ability to access all potential AdWord clientsinside my MCC. I got an authentication screen generated by URL for this process which asked me to confirm that permission was being granted for AdWords access.
  4. Following this, I created a new googleads.yaml script and placed this in my c:\gsutil directory. This is the code in most Python programs where the program looks for the file googleads.yaml:

    adwords_client = adwords.AdWordsClient.LoadFromStorage()
    
  5. Once this was done, I was able to successfully run the script from my command line to generate the final output. The script was:

    python download_criteria_report.py
    

Note of course that I have changed my path variable previously in order to run Python 2.7 from the command line. This script was run inside the directory of the download_criteria_report.py file. This script ran successfully and enabled me to pull data from the AdWords API for one of my test clients.

The next challenge will be working with the returned output from the API and putting it into a format that I can quickly use for analysis & storage.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top