Share

blog-header

Automatic Campaign URL Monitoring with Google Ads API

Regularly monitoring the destination URLs of your Google Ads campaigns is one of the most effective ways to protect your ad budget. Broken or misdirected pages waste paid clicks, lower your Quality Score, and hurt your conversion rates.

In this article we’ll walk you step-by-step through building an automation system that exports Google Ads destination URL data into Google Sheets, checks whether those URLs are working, and—if a problem is found—sends alert emails via Gmail.

We won’t focus solely on code snippets; our emphasis is on API connection structure, data flow, authentication processes, and the logical design of the automation.

The provided Python examples give you a solid, extensible foundation—so you can adapt this solution to your own use case, and expand it to other API endpoints or data sources.

Throughout the article we’ll examine how to set the system up from scratch, which integrations kick in at each stage, and the technical details you may encounter. If you have additions that would improve the reports or any feedback (positive or critical), we’d love to hear it.

 

Our Goal

With this system, you’ll be able to:

  • Fetch data from active campaigns through the Google Ads API,
  • Write campaign, ad group, and asset URLs into Google Sheets,
  • Automatically test all URLs (flagging any that don’t return a 200 OK status),
  • Send automated email alerts via Gmail when broken URLs are detected,
  • Run the entire process automatically every day at a specific time (e.g., 3:00 PM).

Required Tools

To set up this system, you’ll need the following components:

  • Google Cloud Console – to manage API access and create credentials,
  • Google Ads Account – to retrieve campaign data,
  • Google Sheets – to store and monitor the URL reports,
  • Gmail Account – to send automated notification emails,
  • Python 3.8+ – the language and environment that will power the automation

 

Step 1 – Create a Google Cloud Project and Enable API Access

Start by creating a new project in Google Cloud Console.

Once your project is ready, enable the following APIs:

  • Google Ads API
  • Google Sheets API

These APIs will allow us to both retrieve ad data and manage Sheets operations directly through Python.

 

Step 2 – Setting Up Google Ads API Credentials

To use the Google Ads API, you’ll need four key pieces of information:

  • Developer Token

You can find this in your Google Ads account under Admin -> API Center -> API Access.

If you don’t already have a token, the newly issued one will start at Test Access level. To upgrade to Basic Access, you’ll need to submit an additional application explaining your API usage purpose in a brief documentation format.

  • Client ID ve Client Secret

You can create it in Google Cloud Console under APIs & Services -> Credentials -> OAuth 2.0 Client IDs.

  • Refresh Token

It’s required to ensure automatic token renewal when access expires.

By now, you should have your Developer Token, Client ID, and Client Secret ready. You’ll also need a Gmail account that has access to the Google Ads account.

You can quickly generate your Refresh Token using Google’s official tool, OAuth 2.0 Playground:

  • Click the Settings icon in the top-right corner.
  • Enable “Use your own OAuth credentials.”
  • Enter the following:
    • Client ID -> from your Google Cloud Console
    • Client Secret -> from your Google Cloud Console
  • Click Save.
  • Under “Select & authorize APIs,” find and select:
  • Click “Authorize APIs.”
  • Approve the permissions.
  • Click “Exchange authorization code for tokens.”
  • Copy your Refresh Token — you’ll need it for authentication in your automation.

We store all of this information in the “google-ads.yaml” file using the following format:

developer_token: “your_developer_token”
client_id: “your_client_id”
client_secret: “your_client_secret”
refresh_token: “your_refresh_token”
login_customer_id: 1111111111 # MCC hesabınız
use_proto_plus: True

Keep this file in your project directory.

 

Step 3 – Preparing Google Sheets

Create a new spreadsheet in Google Sheets.
This file will store campaign URLs, sitelinks, and their error statuses.

Create two sheets (you can rename them as you like):

  • Sheet1 – Final URLs for Search and PMax campaigns
  • Sitelinks – Account- and campaign-level sitelink URLs

Make sure to note the Spreadsheet ID.
You can find it in the URL of your Google Sheet, between /d/ and /edit.

 

Step 4 – Setting Up Access with a Service Account

To access the Sheets API, create a service account:

  1. Google Cloud Console -> IAM & Admin -> Service Accounts -> “Create Service Account”
  2. Create the account and download the JSON key file (service_account.json)

Here’s an example of a “service_account.json” file structure:

{
“type”: “service_account”,
“project_id”: “your_project_id”,
“private_key_id”: “your_private_key_id”,
“private_key”: “—–BEGIN PRIVATE KEY—–\your_privete_key\n—–END PRIVATE KEY—–\n”,
“client_email”: “your_client_email_name@abiding-hull-471108-q5.iam.gserviceaccount.com”,
“client_id”: “your_client_id”,
“auth_uri”: “https://accounts.google.com/o/oauth2/auth”,
“token_uri”: “https://oauth2.googleapis.com/token”,
“auth_provider_x509_cert_url”: “https://www.googleapis.com/oauth2/v1/certs”,
“client_x509_cert_url”: “https://www.googleapis.com/robot/v1/metadata/x509/your_client_email_name%40abiding-hull-471108-q5.iam.gserviceaccount.com”,
“universe_domain”: “googleapis.com”
}

  • And add it as an Editor in the “Share” settings of your Google Sheet.

This grants your Python script direct write access to the spreadsheet.

 

Step 5 – Preparing the Python Environment

Assuming your Python environment is already set up with the latest version, install the required libraries via your terminal or command prompt:

pip install google-ads google-api-python-client google-auth requests  

 

Step 6 – Sending Emails via Gmail

At the end of the automation, if a broken URL is detected, the system will automatically send an email via Gmail.

To enable this, you need to create a Gmail App Password:

  1. Enable 2-Step Verification (2FA) on your Google account.
  2. Go to the App Passwords page.
  3. Create a new app password (e.g., “Broken URL Automation”).
  4. Save the generated 16-character password.

This password can be used securely in your code along with your Gmail account to send emails automatically.

 

Step 7 – How It Works

Now that the setup is complete, the automation workflow is as follows:

  1. Fetch data from active campaigns, ad groups, and asset URLs via the Google Ads API.
  2. Write the retrieved data into your Google Sheets file.
  3. Check each URL:

    • If the page returns 200 OK → Healthy
    • If it returns 404, 500, or times out → Mark as Broken
  4. Send an automatic alert via Gmail if any broken URLs are detected.

 

Step 8 – Scheduling Daily Automatic Runs

To run this system at a specific time every day, you can set up a scheduler.

Since you’re using Windows, you can accomplish this via Task Scheduler.

 

Step 9 – Testing

You can also test the code manually.

In the terminal, run:

python check_urls.py

If everything is set up correctly:

  • New data will appear in your Google Sheets file,
  • Alert emails will be sent to your Gmail if any broken URLs are detected,
  • The logs will show messages like “All URLs are healthy” or “Broken URL detected.”

 

Step 10 – Why We Did It and the Outputs

In this section, we’ll explain what each part of the code (check_url.py) does and the results it produces when executed.

The following codes load external libraries and API clients that the project will use.

from google.ads.googleads.client import GoogleAdsClient
from google.oauth2 import service_account
from googleapiclient.discovery import build
import requests
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

This code snippet sets up the configuration for our project.

It defines all the connection details and authentication files required for Google Ads API, Google Sheets, and email notifications.

GOOGLE_ADS_CONFIG_PATH = “google-ads.yaml”
CUSTOMER_ID = “your_customer_id”

SERVICE_ACCOUNT_FILE = “service_account.json”
SPREADSHEET_ID = “your_spreadsheet_id”
SHEET1_NAME = “Sheet1”
SITELINKS_SHEET_NAME = “Sheet2”

EMAIL_SENDER = “your_email”
EMAIL_RECEIVER = “your_email”
EMAIL_PASSWORD = “your_app_password”

The “send_email” function is used to automatically send an email notification once the process is complete

def send_email(subject, body):

msg = MIMEMultipart()
msg[“From”] = EMAIL_SENDER
msg[“To”] = EMAIL_RECEIVER
msg[“Subject”] = subject
msg.attach(MIMEText(body, “plain”))

try:
with smtplib.SMTP_SSL(“smtp.gmail.com”, 465) as server:
server.login(EMAIL_SENDER, EMAIL_PASSWORD)
server.send_message(msg)
print(“The email has been sent.”)
except Exception as e:
print(f”The email could not be sent.: {e}”) 

The “check_url” function is used to verify the accessibility of a given URL.

  • It takes a URL as input and first checks if it is empty.
  • If a URL is provided, it makes a request using requests.get() with a 5-second timeout.
  • If the response status_code is 200, it returns “OK”; otherwise, it returns “Error [code]” for any other status code.

def check_url(url):
if not url:
return “”
try:
r = requests.get(url.strip(), timeout=5)
if r.status_code == 200:
return “OK”
else:
return f”Error {r.status_code}”
except requests.exceptions.RequestException as e:
return f”Failed: {e.__class__.__name__}”

The “get_search_campaigns” function is used to retrieve the ad URLs from active Search and Display campaigns in a Google Ads account.

  • It runs a GAQL query via the GoogleAdsService.
  • The query fetches campaign ID, campaign name, ad ID, ad group name, and final URLs.
  • Only campaigns with ENABLED status and SEARCH or DISPLAY channel type are retrieved.

def get_search_campaigns(client, customer_id):
ga_service = client.get_service(“GoogleAdsService”)
query = “””
SELECT
campaign.id,
campaign.name,
ad_group_ad.ad.id,
ad_group.name,
ad_group_ad.ad.final_urls,
campaign.advertising_channel_type
FROM ad_group_ad
WHERE campaign.status = ‘ENABLED’
AND campaign.advertising_channel_type IN (‘SEARCH’, ‘DISPLAY’)
ORDER BY campaign.id
“””
results = []
response = ga_service.search(customer_id=customer_id, query=query)
for row in response:
final_urls = [str(url) for url in row.ad_group_ad.ad.final_urls] if row.ad_group_ad.ad.final_urls else []
results.append((
row.campaign.id,
row.campaign.name,
row.ad_group_ad.ad.id,
row.ad_group.name,
“, “.join(final_urls),
“SEARCH/DISPLAY”
))
return results 

The “get_account_sitelinks” function is used to retrieve account-level Sitelink extensions.

  • It queries the customer_asset table via GAQL using the GoogleAdsService.
  • The query returns, for each sitelink: link text, descriptions, final URLs, and asset name.
  • This function lists sitelinks attached directly at the account level, not at the campaign or ad group level.

def get_account_sitelinks(google_ads_client, customer_id):
ga_service = google_ads_client.get_service(“GoogleAdsService”)
query = “””
SELECT
customer_asset.asset,
customer_asset.status,
asset.name,
asset.sitelink_asset.link_text,
asset.sitelink_asset.description1,
asset.sitelink_asset.description2,
asset.final_urls
FROM customer_asset
WHERE asset.type = ‘SITELINK’
“””
results = []
response = ga_service.search(customer_id=customer_id, query=query)
for row in response:
final_urls = [str(url) for url in row.asset.final_urls] if row.asset.final_urls else []
results.append((“”, “”, row.asset.name, row.asset.sitelink_asset.link_text, row.asset.sitelink_asset.description1 or “”, “, “.join(final_urls)))
return results

Using the same approach, we run separate functions to retrieve PMax and campaign-level sitelink URLs.
These URLs are then written into the corresponding fields in the Google Sheet.

You can access the full code via the following link.

https://github.com/mehmetakifc/google-ads-url-checker

The Sheet1 page containing the campaign URL information looks like this:

 

The Sitelinks page containing the sitelink URL information looks like this:

 

The email notification looks like this:

 

Conclusion

In this article, we outlined how to build a fully automated system that regularly checks and reports Google Ads Final URLs and Sitelink URLs, detecting any broken links.

This system allows you to:

  • Quickly identify broken URLs in Google Ads campaigns,
  • Prevent wasted ad spend on invalid clicks,
  • Monitor all data centrally in Google Sheets,
  • Take fast action through email notifications.

In short, this solution makes your ad accounts healthier, more transparent, and more efficient—both technically and operationally.

 

Hello, I am Mehmet Akif ÇANDIR, after working as an engineer in the sector, I started working in the Web/App Analytics sector with the contribution of my curiosity and engineering knowledge. I am improving myself and providing service as a Web/App Analyst. I have been working as a Web/App Analyst at Perfist since July 2022.

Perfist Blog

Similar Articles

Other Articles