Expert guidance for Google Ads Script development including AdsApp API, campaign management, ad groups, keywords, bidding strategies, performance reporting, budget management, automated rules, and optimization patterns. Use when automating Google Ads campaigns, managing keywords and bids, creating performance reports, implementing automated rules, optimizing ad spend, working with campaign budgets, monitoring quality scores, tracking conversions, pausing low-performing keywords, adjusting bids based on ROAS, or building Google Ads automation scripts. Covers campaign operations, keyword targeting, bid optimization, conversion tracking, error handling, and JavaScript-based automation in Google Ads editor.
/plugin marketplace add henkisdabro/wookstar-claude-code-plugins/plugin install google-apps-ads-script@wookstar-claude-code-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/bid-manager-template.jsassets/campaign-optimizer-template.jsreferences/ads-api-reference.mdscripts/validators.pyThis skill provides comprehensive guidance for developing Google Ads Scripts using the AdsApp API. Google Ads Scripts enable automation of campaign management, bid optimization, performance reporting, and bulk operations through JavaScript code that runs directly in the Google Ads editor.
Invoke this skill when:
Manage campaigns programmatically including creation, modification, status changes, and bulk updates. The AdsApp.campaigns() selector provides filtering and iteration patterns.
Common operations:
Automate keyword targeting and bid adjustments based on performance metrics.
Common operations:
Generate custom reports using campaign, ad group, keyword, and ad statistics.
Common operations:
Control spending and allocate budgets across campaigns.
Common operations:
Build intelligence into campaign management with automated decision-making.
Common operations:
Implement robust error handling to manage API limits, quota issues, and runtime errors.
Key patterns:
function pauseLowQualityKeywords() {
const keywords = AdsApp.keywords()
.withCondition('keyword.status = ENABLED')
.withCondition('keyword.quality_info.quality_score < 4')
.withCondition('keyword.metrics.cost > 100000000') // >100 spend
.get();
let count = 0;
while (keywords.hasNext()) {
const keyword = keywords.next();
keyword.pause();
count++;
}
Logger.log(`Paused ${count} low-quality keywords`);
}
function optimizeBidsByROAS() {
const TARGET_ROAS = 3.0; // 300%
const keywords = AdsApp.keywords()
.withCondition('keyword.status = ENABLED')
.withCondition('keyword.metrics.conversions > 5') // Min conversions
.get();
while (keywords.hasNext()) {
const keyword = keywords.next();
const stats = keyword.getStatsFor('LAST_30_DAYS');
const roas = stats.getReturnOnAdSpend();
const currentBid = keyword.getMaxCpc();
if (roas > TARGET_ROAS) {
// Increase bid by 10%
keyword.setMaxCpc(Math.floor(currentBid * 1.1));
} else if (roas < TARGET_ROAS * 0.7) {
// Decrease bid by 5%
keyword.setMaxCpc(Math.floor(currentBid * 0.95));
}
}
}
function exportCampaignPerformance() {
const campaigns = AdsApp.campaigns()
.withCondition('campaign.status = ENABLED')
.orderBy('campaign.metrics.cost DESC')
.get();
const report = [['Campaign', 'Clicks', 'Cost', 'Conversions', 'CPC', 'ROAS']];
while (campaigns.hasNext()) {
const campaign = campaigns.next();
const stats = campaign.getStatsFor('LAST_30_DAYS');
report.push([
campaign.getName(),
stats.getClicks(),
stats.getCost() / 1000000, // Convert from micros
stats.getConversions(),
stats.getAverageCpc() / 1000000,
stats.getReturnOnAdSpend()
]);
}
// Write to Google Sheets
const ss = SpreadsheetApp.openById('YOUR_SHEET_ID');
const sheet = ss.getSheetByName('Campaign Report') || ss.insertSheet('Campaign Report');
sheet.clear();
sheet.getRange(1, 1, report.length, report[0].length).setValues(report);
}
For comprehensive API documentation, code patterns, and detailed examples, see:
The reference file contains:
Avoid individual API calls in loops. Instead, collect entities and perform batch operations:
// ✅ Good - Batch collection
const keywords = AdsApp.keywords()
.withCondition('keyword.quality_info.quality_score < 5')
.get();
const toUpdate = [];
while (keywords.hasNext()) {
toUpdate.push(keywords.next());
}
toUpdate.forEach(keyword => keyword.setMaxCpc(50000));
Use .withCondition() to filter at the API level rather than in JavaScript:
// ✅ Good - API-level filtering
const campaigns = AdsApp.campaigns()
.withCondition('campaign.status = ENABLED')
.withCondition('campaign.budget_information.budget_amount > 100000000')
.get();
Always wrap operations in try-catch blocks and log errors:
function safeOperation() {
try {
// Operation code
} catch (error) {
Logger.log('Error: ' + error.message);
Logger.log('Stack: ' + error.stack);
// Optionally email alert
MailApp.sendEmail(
Session.getEffectiveUser().getEmail(),
'Ads Script Error',
error.message
);
}
}
Scripts have a 30-minute execution timeout. For large accounts:
.withLimit()Google Ads API uses micros (1/1,000,000) for currency values:
const costMicros = stats.getCost();
const costCurrency = costMicros / 1000000; // Convert to dollars/local currency
const bidCurrency = 5.00; // $5.00
const bidMicros = bidCurrency * 1000000; // 5000000 micros
Maintain audit trails by logging changes to Google Sheets:
function logChange(operation, entity, details) {
const ss = SpreadsheetApp.openById('LOG_SHEET_ID');
const sheet = ss.getSheetByName('Audit Log');
sheet.appendRow([
new Date(),
operation,
entity,
JSON.stringify(details)
]);
}
function adjustBidsBasedOnDayOfWeek() {
const today = new Date().getDay(); // 0 = Sunday, 6 = Saturday
const isWeekend = today === 0 || today === 6;
const campaigns = AdsApp.campaigns()
.withCondition('campaign.status = ENABLED')
.get();
while (campaigns.hasNext()) {
const campaign = campaigns.next();
const budget = campaign.getBudget().getAmount();
if (isWeekend) {
campaign.getBudget().setAmount(budget * 1.2); // +20% on weekends
}
}
}
function monitorQualityScores() {
const threshold = 5;
const lowQualityKeywords = AdsApp.keywords()
.withCondition(`keyword.quality_info.quality_score < ${threshold}`)
.withCondition('keyword.status = ENABLED')
.orderBy('keyword.metrics.cost DESC') // Most expensive first
.withLimit(100)
.get();
const alerts = [];
while (lowQualityKeywords.hasNext()) {
const keyword = lowQualityKeywords.next();
alerts.push({
keyword: keyword.getText(),
qualityScore: keyword.getQualityScore(),
cost: keyword.getStatsFor('LAST_7_DAYS').getCost() / 1000000
});
}
if (alerts.length > 0) {
// Send email or log to sheet
Logger.log(`${alerts.length} keywords with QS < ${threshold}`);
}
}
Use the validation scripts in scripts/ for pre-deployment checks:
Common Issues:
.withLimit() or process in batchesDebug with Logger:
Logger.log('Debug info: ' + JSON.stringify(data));
// View logs: View > Logs in script editor
This skill provides production-ready patterns for Google Ads automation. Consult the comprehensive API reference for detailed method signatures and advanced use cases.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.