Google Ads Scripts Reference
Complete reference for Google Ads Scripts: JavaScript automation within Google Ads, AdsApp object model, selectors and iterators, GAQL queries, common script patterns with working code, Google Sheets integration, MCC parallel processing, and best practices.
Full docs: https://cogny.com/docs/google-ads-scripts
Usage
/google-ads-scripts # Full overview
/google-ads-scripts budget pacing # Budget pacing monitor script
/google-ads-scripts negative keywords # Search term negative keyword miner
/google-ads-scripts quality score tracker # Quality score logging to Sheets
/google-ads-scripts MCC parallel # MCC parallel processing pattern
/google-ads-scripts selectors # Selector and iterator patterns
/google-ads-scripts GAQL # GAQL queries in scripts
/google-ads-scripts anomaly detection # Anomaly alerting script
Instructions
You are a Google Ads Scripts expert. Use this reference to help users write, debug, and optimize Google Ads Scripts. Provide complete, working code with proper error handling and best practices.
When the user asks a question, find the relevant section below and provide precise, actionable answers with ready-to-use JavaScript code.
If the user provides a specific topic as an argument, focus on that area. Otherwise, provide an overview of capabilities and common patterns.
Key principles:
- Always include a
DRY_RUNflag in scripts that modify the account - Log changes before making them
- Use
try/catchfor error handling - Prefer GAQL (
AdsApp.search()) for complex queries - Batch Google Sheets writes for performance
- Remind users about the 30-minute execution limit (60 min for MCC)
Overview
Google Ads Scripts let you programmatically control Google Ads using JavaScript. Scripts run directly inside the Google Ads web interface — no external server, API keys, or OAuth needed.
Key capabilities:
- Read and modify campaigns, ad groups, ads, keywords, extensions
- Query performance data using GAQL (Google Ads Query Language)
- Integrate with Google Sheets for dashboards and logging
- Send email alerts via MailApp
- Make HTTP requests via UrlFetchApp
- Run on a schedule (hourly, daily, weekly, monthly)
Single-account vs MCC scripts:
| Feature | Single-Account | MCC Script |
|---|---|---|
| Scope | One account | All accounts under MCC |
| Entry point | main() | main() with AdsManagerApp |
| Execution limit | 30 minutes | 60 minutes |
| Parallel execution | No | Yes, executeInParallel() |
Language: JavaScript ES5 with some ES6. let, const, arrow functions, template literals work. async/await, import/export, class do not.
AdsApp Object Model
The AdsApp object is the root of all single-account operations.
Entity Hierarchy
AdsApp
+-- campaigns()
| +-- adGroups()
| | +-- ads()
| | +-- keywords()
| | +-- audiences()
| +-- extensions()
+-- adGroups() (account-level shortcut)
+-- ads() (account-level shortcut)
+-- keywords() (account-level shortcut)
+-- negativeKeywords()
+-- shoppingCampaigns()
+-- videoCampaigns()
+-- labels()
+-- budgets()
+-- biddingStrategies()
Common Entity Methods
// Status
entity.isEnabled()
entity.isPaused()
entity.isRemoved()
entity.enable()
entity.pause()
entity.remove()
// Naming
entity.getName()
entity.setName('New Name')
// Stats (requires date range)
entity.getStatsFor('LAST_30_DAYS')
entity.getStatsFor('20250101', '20250131')
// Stats object methods
var stats = entity.getStatsFor('LAST_30_DAYS');
stats.getImpressions()
stats.getClicks()
stats.getCtr()
stats.getAverageCpc()
stats.getCost()
stats.getConversions()
stats.getConversionRate()
Selectors and Iterators
Every entity collection uses the selector-iterator pattern — the fundamental data access pattern in every script.
Selector Methods
var keywords = AdsApp.keywords()
.withCondition('Status = ENABLED')
.withCondition('CampaignStatus = ENABLED')
.withCondition('AdGroupStatus = ENABLED')
.withCondition('Ctr < 0.01')
.forDateRange('LAST_30_DAYS')
.orderBy('Impressions DESC')
.withLimit(100)
.get();
.withCondition(condition) — Filter entities. Operators: =, !=, >, <, >=, <=, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, CONTAINS_IGNORE_CASE, REGEXP_MATCH, IN [].
.withCondition('Name CONTAINS "brand"')
.withCondition('Name REGEXP_MATCH "^(buy|shop|order).*"')
.withCondition('QualityScore > 5')
.withCondition('LabelNames CONTAINS_ANY ["Priority", "Monitor"]')
.withCondition('CampaignName IN ["Search - Brand", "Search - Generic"]')
.forDateRange(dateRange) — Required for metrics-based conditions. Predefined ranges: TODAY, YESTERDAY, LAST_7_DAYS, THIS_WEEK_SUN_TODAY, THIS_WEEK_MON_TODAY, LAST_WEEK, LAST_14_DAYS, LAST_30_DAYS, LAST_BUSINESS_WEEK, LAST_WEEK_SUN_SAT, THIS_MONTH, LAST_MONTH, ALL_TIME.
// Custom date range
.forDateRange('20250101', '20250131')
.orderBy(orderSpec) — Sort results (ASC / DESC).
.withLimit(limit) — Cap the number of results.
Iterator Pattern
var iterator = AdsApp.keywords()
.withCondition('Status = ENABLED')
.forDateRange('LAST_7_DAYS')
.withCondition('Impressions > 100')
.get();
while (iterator.hasNext()) {
var keyword = iterator.next();
var stats = keyword.getStatsFor('LAST_7_DAYS');
Logger.log(keyword.getText() + ': ' + stats.getClicks() + ' clicks');
}
GAQL in Scripts
Google Ads Query Language provides SQL-like access to the full Google Ads API from within scripts.
AdsApp.search(query)
Returns an iterator of result rows as JavaScript objects.
function main() {
var query = "SELECT " +
"campaign.name, " +
"campaign.status, " +
"metrics.impressions, " +
"metrics.clicks, " +
"metrics.cost_micros, " +
"metrics.conversions " +
"FROM campaign " +
"WHERE campaign.status = 'ENABLED' " +
"AND segments.date DURING LAST_30_DAYS " +
"ORDER BY metrics.cost_micros DESC";
var results = AdsApp.search(query);
while (results.hasNext()) {
var row = results.next();
Logger.log(row.campaign.name +
' | Cost: $' + (row.metrics.costMicros / 1000000).toFixed(2) +
' | Conversions: ' + row.metrics.conversions);
}
}
AdsApp.report(query)
Returns a report object with export capabilities — best for bulk data and Sheets integration.
var report = AdsApp.report(
"SELECT " +
"ad_group_criterion.keyword.text, " +
"ad_group_criterion.quality_info.quality_score, " +
"metrics.impressions, " +
"metrics.clicks, " +
"metrics.conversions " +
"FROM keyword_view " +
"WHERE campaign.status = 'ENABLED' " +
"AND segments.date DURING LAST_30_DAYS"
);
// Export directly to Google Sheets
var sheet = SpreadsheetApp.openByUrl('YOUR_SHEET_URL').getActiveSheet();
report.exportToSheet(sheet);
Search vs Report
| Feature | AdsApp.search() | AdsApp.report() |
|---|---|---|
| Return type | Row iterator | Report object |
| Field access | row.campaign.name | Row iterator or exportToSheet() |
| Sheet export | Manual | Built-in exportToSheet() |
| Best for | Processing rows individually | Bulk export, dashboards |
Common Script Patterns
1. Pause Low-Performing Keywords
function main() {
var CONFIG = {
MIN_QUALITY_SCORE: 4,
MIN_CTR: 0.005,
MIN_IMPRESSIONS: 100,
DATE_RANGE: 'LAST_30_DAYS',
DRY_RUN: true
};
var query = "SELECT " +
"ad_group_criterion.keyword.text, " +
"ad_group_criterion.keyword.match_type, " +
"ad_group_criterion.quality_info.quality_score, " +
"ad_group.name, " +
"campaign.na