Google Ads API (AdWord API) - Get report and performance data using python

Step by Step guide to using Google Ads API with Python to Extract Data from Google Ads

How to use Google Ads API with python? How to get Google Ads insight (performance data) using python (Google Ads API call with Python)?

Hi Everyone, hope you are keeping well. I have put together this article to help you guys in building python logic to use Google Ads APIs (AdWord API) to extract Google Ads and campaign Performace data.

What is Google Ads API?

The API provided by google enables interaction with the Google Ads platform directly. It makes it easy and efficient to manage large or complex Google Ads accounts and campaigns.

NOTE: Google Ads API is the next-generation programming interface of the AdWords API. Currently, Google ads API is in beta, hence AdWords API will be soon replaced by Google Ads API.

In this article, we will be using Google Ads API to get campaign reports and ads reports. We will be using AdWord query language (AWQL) for getting AD_PERFORMANCE_REPORT and CAMPAIGN_PERFORMANCE_REPORT report (this is applicable for the Adword version). For the Google Ads  API version we will be using Google Ads query language to query the google ads API to get campaign and ads performance data.

Before diving into the process of building python code to extract Google Ads insight (performance data). You need to have some credentials and apps set up before using Google Ads API with python. Refer to the Getting Started with Google Ads API (AdWord API).

Table of Contents:

  1. Create a JSON File.
  2. AdWord Query Language (AWQL) to get reports.
    1. Custom Module for OAuth Authentication.
    2. Python code to query AdWord reports.
    3. Complete Python Code (adword_main.py).
  3. Google Ads Query Language to get Google Ads data.
    1. Custom Module for OAuth Authentication.
    2. Python code to extract Google Ads performance Insight/Data.
    3. Complete Python Code (google_ads_main.py).

1. Create a JSON File to Store Credentials

From the above guide, you will have some set of credentials generated (Tokens). We will be storing these credentials in a JSON file. 

Using a JSON file to hold authentication-related credentials makes it very easy to maintain and update the credentials. For the python code we are going to build through this article it’s important for you to follow the naming convention (avoid basic naming errors). Save the below JSON format as “google_ads_cred.json”.

{
    "client_id":"Replace with Client Id",
    "client_secret":"Replace with Client Secret",
    "access_token":"Replace with Access Token",
    "refresh_token":"Replace with Refresh Token",
    "developer_token" :"Replace with Developer Token",
    "version": "v10"
}

2. AdWord Query Language (AWQL) to get reports:

2.1 Python code for Google OAuth Authentication.

In this step, you will see python code to authenticate applications on behalf of the user. I will suggest you understand this function and how this function is called because this will also help you understand how to build and use a custom python module.

Save the below file as “adword_authetication.py”.

#!/usr/local/bin/python3
import sys
from googleads import adwords
from googleads import oauth2 
 
def adword_oauth_authentication(client_id,client_secret,developer_token,refresh_token):
    try:
        token_uri = 'https://accounts.google.com/o/oauth2/token'
 
        oauth2_client = oauth2.GoogleRefreshTokenClient(
                        client_id, client_secret, refresh_token)
 
        # Initialize the AdWords client.
        adwords_client = adwords.AdWordsClient(
                        developer_token, oauth2_client)
 
        print("\nFunction (adword_oauth_authentication) finished successfully. ")
        return adwords_client
    except:
        print("\n*** Function (adword_oauth_authentication) Failed *** ",sys.exc_info())
 
 

Save above code as “adword_authentication.py“.

2.2 Python code to query AdWord reports.

Below is the python module with two functions. One function query’s Campaign performance report and another function query’s ad performance report.

You can make out the functions task by their name. Remember same logic can be used to query different report just need to change report name.

#!/usr/bin/python3
 
import sys
import io
import pandas as pd
from googleads import adwords
from datetime import datetime, timedelta
 
#Function for date validation
def date_validation(date_text):
    try:
        while date_text != datetime.strptime(date_text, '%Y-%m-%d').strftime('%Y-%m-%d'):
            Exception('Input Date does not match format yyyy-mm-dd ')
        else:
            return datetime.strptime(date_text,'%Y-%m-%d').date()
    except:
        raise Exception('\n *** Function (date_validation) Failed ***')
 
#Function for date validation
def date_conversion(dt):
    try:
        dt_iso = dt.isoformat().replace("-", "")
        return dt_iso
    except:
        raise Exception('adword_processing : date format conversion failed')
 
 
def get_campaign_report(client,account_id,s_date,e_date):
        try:
                #calling date validation funtion for start date format check
                startDate = date_validation(s_date)
                #s_date = datetime.datetime.strptime(startDate,'%Y-%m-%d')
                dt = startDate+timedelta(1)
                week_number = dt.isocalendar()[1]
                #calling date validation funtion for end date format check
                endDate = date_validation(e_date)
 
                client.SetClientCustomerId(account_id)
                output= io.StringIO()
                # Initialize appropriate service.
                report_downloader = client.GetReportDownloader(version='v201809')
 
                date_range = str(date_conversion(startDate))+','+str(date_conversion(endDate))
                # Create report query.
                report_query = (adwords.ReportQueryBuilder()
                                .Select('CampaignId','CampaignName','Clicks','Cost','Impressions','Conversions','CampaignStatus')
                                .From('CAMPAIGN_PERFORMANCE_REPORT')
                                .Where('CampaignStatus').In('ENABLED', 'PAUSED')
                                #.During('LAST_7_DAYS')
                                .During(date_range)
                                .Build())
                
                # You can provide a file object to write the output to.
                report_downloader.DownloadReportWithAwql(
                        report_query, 'CSV', output, skip_report_header=True,
                        skip_column_header=False, skip_report_summary=True,
                        include_zero_impressions=False)
 
                output.seek(0)
 
                df_ads_report = pd.read_csv(output)
                df_ads_report = df_ads_report.rename(columns={'Campaign ID':'campaign_id','Campaign':'campaign',
                                'Clicks':'clicks','Cost':'cost','Impressions':'impressions','CampaignStatus':'CampaignStatus',
                                'Conversions':'conversions'})
                df_ads_report["start_date"] = startDate
                df_ads_report["end_date"] = endDate
                df_ads_report["week"] = week_number
 
                #divide micro amount by 1000000, to get normal amount
                df_ads_report["cost"] = df_ads_report["cost"]/1000000                
 
                return df_ads_report
        except:
                print("\n*** Function (get_campaign_report) Failed *** ", sys.exc_info())
                pass
 
def get_ads_report(client,account_id,s_date,e_date):
        try:
                #calling date validation funtion for start date format check
                startDate = date_validation(s_date)
                #s_date = datetime.datetime.strptime(startDate,'%Y-%m-%d')
                dt = startDate+timedelta(1)
                week_number = dt.isocalendar()[1]
                #calling date validation funtion for end date format check
                endDate = date_validation(e_date)
 
                client.SetClientCustomerId(account_id)
                output= io.StringIO()
                # Initialize appropriate service.
                report_downloader = client.GetReportDownloader(version='v201809')
 
                date_range = str(date_conversion(startDate))+','+str(date_conversion(endDate))
                # Create report query.
                report_query = (adwords.ReportQueryBuilder()
                                .Select('CampaignId','CampaignName', 'Id','Clicks','Cost',
                                'AdType','CreativeFinalUrls','Impressions','Conversions')
                                .From('AD_PERFORMANCE_REPORT')
                                .Where('Status').In('ENABLED', 'PAUSED')
                                #.During('LAST_7_DAYS')
                                .During(date_range)
                                .Build())
                
                # You can provide a file object to write the output to.
                report_downloader.DownloadReportWithAwql(
                        report_query, 'CSV', output, skip_report_header=True,
                        skip_column_header=False, skip_report_summary=True,
                        include_zero_impressions=False)
 
                output.seek(0)
 
                df_ads_report = pd.read_csv(output)
                df_ads_report = df_ads_report.rename(columns={'Campaign ID':'campaign_id','Campaign':'campaign',
                                'Ad ID':'ad_id','Clicks':'clicks','Cost':'cost','Ad type':'ad_type','Final URL':'final_url',
                                'Impressions':'impressions','Conversions':'conversions'})
                
                df_ads_report["start_date"] = startDate
                df_ads_report["end_date"] = endDate
                df_ads_report["week"] = week_number
 
                #divide micro amount by 1000000, to get normal amount
                df_ads_report["cost"] = df_ads_report["cost"]/1000000
                #removing "[ from url value
                bad_char = ['"','[',']']
                for i in bad_char:
                        df_ads_report["final_url"] = df_ads_report["final_url"].str.replace(i,'')
 
                return df_ads_report
        except:
                print("\n*** Function (get_ads_report) Failed *** ", sys.exc_info())
                pass
 
        
 

Save above code as “get_report_awql.py”.

2.3 Complete Python Script (adword_main.py).

This step will build python code that will import the above module and call its function. We will be executing This main python file. Code for which is below.

#!/usr/local/bin/python3
#Python3 ./adword_main.py -s startDate(yyyy-mm-dd) -e endDate(yyyy-mm-dd)
import getopt
import sys
import os.path
import json
from datetime import datetime, timedelta
 
from adword_authentication import*
from get_report_awql import *
 
def readCommandLine(argv):
    global s_date
    global e_date
    try:
        opts, args = getopt.getopt(argv,"s:e:")
    except getopt.GetoptError:
        usage()
    for opt, arg in opts:
        if opt == '-s':
            s_date = arg
        elif opt == '-e':
            e_date = arg
        else:
            print("Invalid Option in command line")
 
if __name__ == '__main__':
    try:
        timestamp = datetime.strftime(datetime.now(),'%Y-%m-%d : %H:%M')
        print("DATE : ",timestamp)
        print("AdWord process started.")
 
        #getting the command line parameter.
        readCommandLine(sys.argv[1:])
        
        cred_file = "./google_ads_cred.json"
        cred_data = open(cred_file, 'r')
        cred_data = json.load(cred_data)
 
        client_id = cred_data["client_id"]
        client_secret = cred_data["client_secret"]
        access_token = cred_data["access_token"]
        refresh_token = cred_data["refresh_token"]
        developer_token = cred_data["developer_token"]
 
        #Function call for OAuth Authentication
        api_client = adword_oauth_authentication(client_id,client_secret,developer_token,refresh_token)
 
        account_id = "Replace With Google Ads Account ID"
 
        df_campaign_report = get_campaign_report(api_client,account_id,s_date,e_date)
        print("\n AdWord campaign report :\n",df_campaign_report)
 
        df_ads_report = get_ads_report(api_client,account_id,s_date,e_date)
        print("\n AdWord ads report :\n",df_ads_report)
 
        print("\nAdWord Process Finished.")
    except:
        print("\n*** Adword processing Failed ***", sys.exc_info())
 
 

Lets understand above code:

First, we will be reading the start date and end date passed in the command line. Function for which is defined at line number 12 (readCommandLine) and will be calling this as soon as execution starts (i.e at line number 34).

Next, we will be getting credentials from a JSON file. This process is a multi-step process, code which is from line number 36 to line number 44.

We got credentials from a JSON file now we will be using this credential for OAuth authentication. Above we have already defined a function (adword_authentication) for the same in a separate custom module (adword_authentication.py). Here we will be importing that module at line number 9 (i.e from adword_authentication import *) followed by calling its function (adword_oauth_authentication) at line number 47.

Line number 49 a variable (account_id) is defined to store Google Ads Account ID. The quired report is going to return data for this account ID.

Now we are ready to query reports and get some data. Remember we have defined two functions. One to query Campaign performance report another to query ads performance report will call this function at line number 51 and line number 54 respectively. 

Don’t forget to import the custom module (i.e line number 10) which holds the definition of the above function.

NOTE: querying report logic remains the same for any kind of report. Check out available report types. The only thing one needs to change in the above query logic is the report name and some parameters as needed and available.

You are all set to run the code file. Use the command Python3 ./adword_main.py -s startDate -e endDate. Here start date and end date are command line parameters. The start date and end date format are yyyy-mm-dd.

After running the above code you should get to tables one for campaign report and the other for ads report.

3. Google Ads Query Language to get Google Ads data

In this step, you will see python code to authenticate applications on behalf of the user. I will suggest you understand this function and how this function is called because this will also help you understand how to build and use a custom python module.

Save the below file as “google_ads_authetication.py”.

#!/usr/local/bin/python3
import sys
from google.ads.googleads.client import GoogleAdsClient
 
def google_ads_authentication(cred_dict):
    try:
        client = GoogleAdsClient.load_from_dict(cred_dict)
 
        print("\nFunction (google_ads_authentication) finished successfully. ")
        return client
 
    except:
        print("\n*** Function(google_ads_authentication) Failed *** ",sys.exc_info())

Below is the python module with two functions. One function query’s Campaign performance report and another function query’s ad performance report.

You can make out the functions task by their name. Save below code as “get_google_ads_data.py”.

#!/usr/bin/python3
import sys
import pandas as pd
from datetime import datetime, timedelta
 
#Function for date validation
def date_validation(date_text):
    try:
        while date_text != datetime.strptime(date_text, '%Y-%m-%d').strftime('%Y-%m-%d'):
            Exception('*** Input Date does not match format yyyy-mm-dd ***')
        else:
            return datetime.strptime(date_text,'%Y-%m-%d').date()
    except:
        raise Exception('\n *** Function (date_validation) Failed ***')
 
 
def get_campaign_data(client,account_id,start_date,end_date):
  try:
    #calling date validation funtion for start date format check
    start_date = date_validation(start_date)
    #calling date validation funtion for end date format check
    end_date = date_validation(end_date)
 
    ga_service = client.get_service("GoogleAdsService")
 
    query = """
        SELECT
          campaign.id,
          campaign.name,
          metrics.impressions,
          metrics.clicks,
          metrics.cost_micros,
          segments.date
        FROM campaign
        WHERE segments.date BETWEEN '{}' AND '{}'
        ORDER BY campaign.id""".format(start_date,end_date)
 
    search_request = client.get_type("SearchGoogleAdsStreamRequest")
    search_request.customer_id = account_id
    search_request.query = query
    response = ga_service.search_stream(search_request)
 
    data_df = pd.DataFrame()
 
    
    for batch in response:
      for row in batch.results:
        tmp_dict = {}
        tmp_dict['campaign_name'] = row.campaign.name
        tmp_dict['campaign_id'] = row.campaign.id
        tmp_dict['clicks'] = row.metrics.clicks
        tmp_dict['impressions'] = row.metrics.impressions
        tmp_dict['cost'] = row.metrics.cost_micros/1000000
        tmp_dict['start_date'] = row.segments.date
        data_df = data_df.append(tmp_dict,ignore_index = True)
 
    return data_df
  except:
    print("\n*** Function(get_campaign_data) Failed *** ",sys.exc_info())
 
 
def get_ads_data(client,account_id,start_date,end_date):
  try:
    #calling date validation funtion for start date format check
    start_date = date_validation(start_date)
    #calling date validation funtion for end date format check
    end_date = date_validation(end_date)
 
    ga_service = client.get_service("GoogleAdsService")
 
    query = """
        SELECT
          ad_group_ad.ad.id,
          ad_group_ad.ad.final_urls,
          ad_group_ad.ad.type,
          campaign.id,
          campaign.name,
          ad_group.name,
          ad_group.id,
          metrics.impressions,
          metrics.clicks,
          metrics.cost_micros,
          segments.date
        FROM ad_group_ad
        WHERE segments.date BETWEEN '{}' AND '{}' AND ad_group_ad.status != 'REMOVED'
        ORDER BY campaign.id""".format(start_date,end_date)
 
    search_request = client.get_type("SearchGoogleAdsStreamRequest")
    search_request.customer_id = account_id
    search_request.query = query
    response = ga_service.search_stream(search_request)
 
    data_df = pd.DataFrame()
    
    for batch in response:
      for row in batch.results:
        tmp_dict = {}
        tmp_dict['campaign_name'] = row.campaign.name
        tmp_dict['campaign_id'] = row.campaign.id
        tmp_dict['adgroup_name'] = row.ad_group.name
        tmp_dict['adgroup_id'] = row.ad_group.id
 
        tmp_dict['ad_type'] = row.ad_group_ad.ad.type_
        tmp_dict['ad_url'] = row.ad_group_ad.ad.final_urls[0]
        tmp_dict['ad_id'] = row.ad_group_ad.ad.id
 
        tmp_dict['clicks'] = row.metrics.clicks
        tmp_dict['impressions'] = row.metrics.impressions
        tmp_dict['cost'] = row.metrics.cost_micros/1000000
        tmp_dict['start_date'] = row.segments.date
        data_df = data_df.append(tmp_dict,ignore_index = True)
 
    return data_df
  except:
    print("\n*** Function (get_ads_data) Failed *** ",sys.exc_info())
 
 

In this step will build python code which will import the above module and call its function. We will be executing This main python file. Code for which is below.

#!/usr/local/bin/python3
#Python3 ./google_ads_main.py -s startDate(2021-05-11) -e endDate(2021-05-12)
import sys
import json
import os.path
import getopt
from datetime import datetime, timedelta
 
from google_ads_authentication import*
from get_google_ads_data import *
 
def readCommandLine(argv):
    global s_date
    global e_date
    try:
        opts, args = getopt.getopt(argv,"s:e:")
    except getopt.GetoptError:
        usage()
    for opt, arg in opts:
        if opt == '-s':
            s_date = arg
        elif opt == '-e':
            e_date = arg
        else:
            print("Invalid Option in command line")
 
if __name__ == '__main__':
    try:
        timestamp = datetime.strftime(datetime.now(),'%Y-%m-%d : %H:%M')
        print("DATE : ",timestamp)
        print("Google Ads process started.")
 
        #getting the command line parameter.
        readCommandLine(sys.argv[1:])
 
        cred_file = "./google_ads_cred.json"
        cred_file = open(cred_file, 'r')
        cred_json = json.load(cred_file)
 
        account_id = "Replace With Google Ads Account ID"
 
        api_client = google_ads_authentication(cred_json)
 
        campaign_df = get_campaign_data(api_client,account_id,s_date,e_date)
        print("\n Campaign data : \n ",campaign_df)
 
        ads_df = get_ads_data(api_client,account_id,s_date,e_date)
        print("\n Ads data : \n ",ads_df)
 
        print("\nGoogle Ads Process Finished.")
    except:
        print("\n*** Google Ads processing Failed *** ", sys.exc_info())
 

Lets understand above code:

First, we will be reading the start date and end date passed in the command line. Function for which is defined at line number 12 (readCommandLine) and will be calling this as soon as execution starts (i.e at line number 34).

Next, we will be getting credentials from a JSON file. This process is a multi-step process, code which is from line number 36 to line number 38.

We got credentials from a JSON file, now we will be using this credential for OAuth authentication. Above we have already defined a function for the same in a separate custom module. Here we will be importing that module at line number 9 (i.e from google_ads_authentication import *) followed by calling its function (google_ads_authentication) at line number 40.


Line number 42 a variable (account_id) is defined to store Google Ads Account ID. The queried report is going to return data for this account ID.

Now we are ready to query reports and get some data. Remember we have defined two functions. One to query Campaign level data(insight) another to query ads level data(insight) will call this function at line number 44 and line number 47 respectively. 

Don’t forget to import the custom module (i.e line number 10) which holds the definition of the above function.

NOTE: The logic to define and execute google ads query remains the same for any level of data extraction. Check out available report types

You are all set to run the code file. Use the command Python3 ./google_ads_main.py -s startDate -e endDate. Here start date and end date are command line parameters. The start date and end date format are yyyy-mm-dd.

After running the above code you should get two tables for campaign-level data and the other for ads-level data.

Congratulations! you have successfully created python logic (module) to retrieve the Google Ads marketing insights using the Google Ads API. Hope I was able to make the entire process of building python logic using Google Ads API calls and data retrieval simpler.

Hope I was able to solve the problem. If you like this article and think it was easy to understand do share it with your friends and connection. Thank you! see you soon.

If you have any questions or comments feel free to reach me at.

Checkout out my other API Integration and Coding Solution Guide