Google Ads Landing Page 404 & Redirect Chain Monitor Script (GAQL)
Scheduled GAQL script checking HTTP response codes, redirect chains and soft-404 signatures across all active ad final URLs.
Google Ads 404 & Redirect Chain Dual Monitoring Architecture
Dual-element governance: (1) Client-side GTM event tag intercepting landing page 404s/redirects into GA4 & BigQuery for persistent URL list monitoring, and (2) Scheduled Google Ads backend script running GAQL scans with live Slack/Teams/Email anomaly alerting.
Google Ads Landing Page 404 & Redirect Chain Monitor Script (GAQL) Configurator
Lead Gen CPL Defense — Landing Page 404 & Broken URL Scanner
Automated crawler scanning active ad final URLs and sitelink extensions for HTTP 404/500 errors.
1 Input Parameters & Assumptions
| Parameter | Value | Context & Provenance |
|---|---|---|
| URL Batch Size | 100 URLs Batch / Run | Number of active ad URLs verified per script iteration |
| Execution Frequency | Hourly Schedule | Continuous verification schedule to catch site deployment regressions |
| Notification Channel | Microsoft Teams Webhook Target | Incoming webhook channel for site reliability and marketing ops |
2 Explicit Mathematical Formula
Target URL Scope = Active Ad Final URLs + Sitelink Extension Destination URLs
Error Condition = HTTP Status Code in (404, 500, 502, 503) OR Response Body contains soft-404 signatures
Batch Processing = 100 URLs per run with exponential backoff on connection timeout
Alert Payload = Microsoft Teams MessageCard with Campaign, Ad Group, Broken URL, and Status Code3 Computed Output Metrics
| Computed Metric | Result | Interpretation & Threshold |
|---|---|---|
| HTTP Failure Codes Monitored | 4xx / 5xx HTTP Codes | Catches broken landing pages, expired promotional routes, and server gateway errors |
| Sitelink Extension Coverage | 100% Asset Scope | Scans both ad-level final URLs and shared sitelink assets across all campaigns |
Google Ads Landing Page 404 & Redirect Chain Monitor Script (GAQL) — Scope & Limitations
Explicit operational boundaries and constraints defining target use cases and out-of-scope scenarios.
Built For (Target Use Cases)
- Checking active Google Ads final URLs and sitelink destinations for 404, 500, 502 or 503 responses.
- Detecting soft-404 pages and redirect chains via HTTP status checks and page-level signature matching.
- Pairing the ads script with an optional GTM tag that logs 404 or redirect events to GA4.
Not Built For (Limitations & Out-of-Scope)
- Auditing landing pages that are not linked from active Google Ads final URLs or sitelinks.
- Multi-account (MCC) portfolios; the script config targets one Google Ads account ID.
- Real-time uptime monitoring; checks run on a fixed schedule, not continuous polling.
Operational Assumptions & Defaults
- Assumes URLs are checked in fixed batch sizes with backoff on connection timeouts.
- Assumes the GTM tag fires on page load and reads document title and DOM selectors for 404 signals.
- Webhook destination, account ID and dry-run mode are configured manually before deployment.
Google Ads Automated Governance Script & Multi-Channel Webhook Builder
Google Ads API & AutomationConfigure production-ready Google Ads scripts with live GAQL linting, dry-run toggles, GTM/GA4 error monitoring tags, and multi-channel webhook formatting for Slack, Microsoft Teams, Discord, Google Chat, and Email alerts.
Script Template & Destination
Thresholds & Execution Settings
Generated Artifacts Preview
<script>
/**
* ============================================================================
* Element 1: GTM & GA4 Landing Page 404 & Redirect Chain Event Monitor
* Purpose: Captures broken landing pages (404/500) and redirect chains from Google Ads
* Trigger: All Pages (or Exception / 404 Page Template Trigger in GTM)
* Output: Logs URL list directly into GA4 custom event "ad_landing_page_error"
* ============================================================================
*/
(function() {
try {
var urlParams = new URLSearchParams(window.location.search);
var gclid = urlParams.get('gclid') || urlParams.get('wbraid') || urlParams.get('gbraid');
var utmSource = urlParams.get('utm_source');
var utmCampaign = urlParams.get('utm_campaign');
var isPaidTraffic = Boolean(gclid || (utmSource && utmSource.toLowerCase().indexOf('google') > -1));
// 1. Detect 404 / 500 status via title, meta tags, or DOM indicators
var title = (document.title || '').toLowerCase();
var is404 = title.indexOf('404') > -1 ||
title.indexOf('not found') > -1 ||
title.indexOf('page not found') > -1 ||
Boolean(document.querySelector('.error-404, #not-found, [data-status="404"], .not-found-container'));
// 2. Detect landing page client-side / server-side redirect chains
var referrer = document.referrer || '';
var currentUrl = window.location.href;
var hadRedirect = Boolean(referrer && referrer !== currentUrl && isPaidTraffic);
if (is404 || hadRedirect) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'ad_landing_page_error',
error_type: is404 ? '404_not_found' : 'redirect_chain_detected',
http_status: is404 ? 404 : 301,
page_location: currentUrl,
page_path: window.location.pathname,
page_referrer: referrer,
gclid: gclid || 'none',
utm_source: utmSource || 'none',
utm_campaign: utmCampaign || 'none',
is_paid_traffic: isPaidTraffic,
landing_page_url: currentUrl,
timestamp: new Date().toISOString()
});
console.warn('[Ads Governance] Pushed ad_landing_page_error to dataLayer for GA4 URL monitoring.');
}
} catch (err) {
// Fail silently in production
}
})();
</script>Deploy Dual 404 & Redirect Chain Monitoring Pipeline
Deploy the GTM Custom HTML tag into your website container for real-time GA4 URL list monitoring, and schedule the Google Ads Script in your Ads account for instant Slack/Teams alerting.
Eliminating Paid Traffic to Broken URLs
E-commerce product discontinuations and CMS migrations frequently orphan landing pages while paid ads continue spending. This script checks every live ad URL hourly and delivers an immediate notification when a 404 or 500 error code occurs.
Implementation Code & Script
Iterates active final URLs and emails a report if any link returns HTTP status 400 or above.
/**
* Google Ads Landing Page 404 & Status Monitor (GAQL)
* Author: Gordon Geraghty - Head of Performance Media
* Licence: MIT
* Filter: campaign.status = "ENABLED" AND campaign.serving_status = "SERVING"
*/
const CONFIG = {
EMAIL: 'alerts@example.com',
};
function main() {
Logger.log('Scanning active final URLs for broken pages...');
const query =
'SELECT ad_group_ad.ad.final_urls, campaign.name, ad_group.name ' +
'FROM ad_group_ad ' +
'WHERE campaign.status = "ENABLED" ' +
'AND campaign.serving_status = "SERVING" ' +
'AND ad_group.status = "ENABLED" ' +
'AND ad_group_ad.status = "ENABLED"';
const seen = {};
const broken = [];
const rows = AdsApp.search(query);
while (rows.hasNext()) {
const row = rows.next();
const urls = row.adGroupAd.ad.finalUrls || [];
const camp = row.campaign.name;
const adg = row.adGroup.name;
urls.forEach(function(u) {
if (seen[u]) return;
seen[u] = true;
try {
const response = UrlFetchApp.fetch(u, { muteHttpExceptions: true });
const code = response.getResponseCode();
if (code >= 400) {
broken.push({ url: u, code: code, campaign: camp, adGroup: adg });
}
} catch (e) {
broken.push({ url: u, code: 'FETCH_ERROR: ' + e.message, campaign: camp, adGroup: adg });
}
});
}
Logger.log('Scanned ' + Object.keys(seen).length + ' unique URLs. Broken found: ' + broken.length);
if (broken.length > 0 && CONFIG.EMAIL) {
let msg = 'Google Ads Broken Landing Page Alert:\n\n';
broken.forEach(function(b) {
msg += 'Status ' + b.code + ' on: ' + b.url + '\n';
msg += 'Campaign: ' + b.campaign + ' | Ad Group: ' + b.adGroup + '\n\n';
});
MailApp.sendEmail(CONFIG.EMAIL, 'Google Ads Broken URL Alert (' + broken.length + ' broken URLs)', msg);
}
}Dual Monitoring Pipeline QA & Verification Guide
Verify that GTM Tag Assistant captures the ad_landing_page_error event in GA4 DebugView, and run a dry-run test of the Google Ads alert script.
Pre-Production Verification Checklist
Load a test 404 URL with ?gclid=test_click_123 and confirm "ad_landing_page_error" fires with page_location and gclid parameters.
Register "landing_page_url", "error_type", and "http_status" as Custom Dimensions in GA4 to build an automated broken URL list report.
Execute the Google Ads script in Preview mode to verify UrlFetchApp HTTP checks and test Slack/Teams webhook delivery.
Terminal Diagnostic & Debug Commands
Inspects final resolved destination URL, HTTP response code, and total redirect hops.
curl -s -L -o /dev/null -w "Final URL: %{url_effective} | Status: %{http_code} | Redirects: %{num_redirects}\n" https://example.com/test-landing-pageFailure Remediation & Troubleshooting
Cause: Custom event trigger not firing on 404 page template, or GA4 tag not listening to "ad_landing_page_error".
Fix: Create a GA4 Event Tag in GTM triggered by Custom Event name "ad_landing_page_error" with event parameters forwarded.
Cause: Account has >20,000 enabled ads being checked every run.
Fix: Filter GAQL query to check only ads with impressions > 0 in the last 7 days or increase schedule interval to daily.
How to cite and attribute this tool
MIT LicenceThis resource is free, open and un-gated under the MIT Open Source Licence. You are encouraged to use, integrate and cite it with attribution:
@misc{geraghty_landing_page_404_monitor_script,
author = {Geraghty, Gordon},
title = {Google Ads Landing Page 404 & Redirect Chain Monitor Script (GAQL)},
year = {2026},
url = {https://gordongeraghty.com/resources/performance-media/landing-page-404-monitor-script},
note = {Head of Performance Media, Empire Amplify}
}Changelog & Version History
v1.0.0Initial release with UrlFetchApp status code verification and deduplicated URL checking.
Strategic Takeaway & Operational Guidelines
Bidding on 404 URLs destroys Quality Score and burns ad spend with zero conversion yield. This automated monitor catches broken URLs within 60 minutes of release regressions and alerts engineering immediately.