2026-03-12
Google Ads Scripts for E-Commerce: Automate Your Way to 20% Better Performance

Google Ads Scripts for E-Commerce: Automate Your Way to 20% Better Performance
Manual Google Ads management burns through budgets faster than a Black Friday flash sale. You're bidding on gut feelings, catching negative keywords weeks too late, and missing optimization opportunities that algorithms spot in seconds.
Google Ads Scripts change everything. They automate the tedious, optimize the complex, and free you to focus on strategy instead of spreadsheet wrestling.
At ATTN Agency, our scripts have automated 80% of routine optimizations for brands like Kaged and Goose Creek, resulting in 15-25% performance improvements and 40-60% time savings on campaign management.
Here are the essential scripts every e-commerce brand needs, plus step-by-step implementation guides.
Why Scripts Beat Manual Management
The Scale Problem
Manual Management Limitations:
- Can only monitor 50-100 keywords effectively
- Takes 2-4 hours daily for basic optimizations
- Human error rates: 5-15% in bid adjustments
- Delayed reaction to performance changes
Script-Powered Management:
- Monitors thousands of keywords simultaneously
- Executes optimizations every hour
- Zero calculation errors
- Immediate response to performance triggers
ROI Impact
Performance Improvements:
- 15-30% increase in Quality Score through better keyword management
- 20-40% reduction in wasted spend via automated negative keyword additions
- 10-25% improvement in conversion rates through bid optimization
- 25-50% time savings on campaign management
Essential Scripts for E-Commerce
1. Automated Bid Management Script
What it does: Adjusts bids based on performance data and conversion probability
function main() {
var campaigns = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.get();
while (campaigns.hasNext()) {
var campaign = campaigns.next();
var keywords = campaign.keywords()
.withCondition("Status = ENABLED")
.withCondition("Impressions > 100")
.forDateRange("LAST_30_DAYS")
.get();
while (keywords.hasNext()) {
var keyword = keywords.next();
var stats = keyword.getStatsFor("LAST_7_DAYS");
var conversionRate = stats.getConversions() / stats.getClicks();
var costPerConversion = stats.getCost() / stats.getConversions();
var targetCPA = 50; // Adjust based on your target
var currentBid = keyword.bidding().getCpc();
var newBid = calculateNewBid(conversionRate, costPerConversion, targetCPA, currentBid);
if (newBid !== currentBid) {
keyword.bidding().setCpc(newBid);
Logger.log("Bid updated for keyword: " + keyword.getText() +
" from $" + currentBid + " to $" + newBid);
}
}
}
}
function calculateNewBid(conversionRate, cpa, targetCPA, currentBid) {
if (cpa < targetCPA * 0.8) {
// Performance is good, increase bid by 10%
return Math.min(currentBid * 1.1, 5.00); // Cap at $5
} else if (cpa > targetCPA * 1.2) {
// Performance is poor, decrease bid by 15%
return Math.max(currentBid * 0.85, 0.10); // Floor at $0.10
}
return currentBid; // No change needed
}
Implementation Steps:
- In Google Ads, go to Tools & Settings > Scripts
- Click the "+" button to create a new script
- Paste the code above
- Adjust
targetCPAto your desired cost per acquisition - Set to run every 4 hours during business hours
2. Negative Keyword Harvesting Script
What it does: Automatically finds and adds negative keywords from search query reports
function main() {
var NEGATIVE_KEYWORD_LIST_NAME = "Auto-Generated Negatives";
var MIN_COST = 10; // Minimum spend before considering
var MAX_CTR = 0.02; // 2% CTR threshold
var MIN_IMPRESSIONS = 50;
// Get or create negative keyword list
var negativeKeywordLists = AdsApp.negativeKeywordLists()
.withCondition("Name = '" + NEGATIVE_KEYWORD_LIST_NAME + "'")
.get();
var negativeList;
if (negativeKeywordLists.hasNext()) {
negativeList = negativeKeywordLists.next();
} else {
negativeList = AdsApp.negativeKeywordLists()
.create(NEGATIVE_KEYWORD_LIST_NAME);
}
// Find poor performing search queries
var searchTermsReport = AdsApp.report(
"SELECT Query, Impressions, Clicks, Cost, Conversions " +
"FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
"WHERE Impressions > " + MIN_IMPRESSIONS + " " +
"AND Cost > " + MIN_COST + " " +
"AND Conversions = 0 " +
"DURING LAST_30_DAYS"
);
var rows = searchTermsReport.rows();
var negativeKeywords = [];
while (rows.hasNext()) {
var row = rows.next();
var query = row["Query"];
var impressions = parseInt(row["Impressions"]);
var clicks = parseInt(row["Clicks"]);
var cost = parseFloat(row["Cost"]);
var ctr = clicks / impressions;
if (ctr < MAX_CTR && isIrrelevantQuery(query)) {
negativeKeywords.push(query);
Logger.log("Adding negative keyword: " + query);
}
}
// Add negative keywords to list
if (negativeKeywords.length > 0) {
negativeList.addNegativeKeywords(negativeKeywords);
}
}
function isIrrelevantQuery(query) {
var irrelevantTerms = [
"free", "cheap", "diy", "how to make",
"review", "vs", "alternative", "competitor"
];
query = query.toLowerCase();
for (var i = 0; i < irrelevantTerms.length; i++) {
if (query.indexOf(irrelevantTerms[i]) !== -1) {
return true;
}
}
return false;
}
Implementation Steps:
- Create script in Google Ads interface
- Customize
irrelevantTermsarray for your business - Adjust cost and CTR thresholds
- Schedule to run daily
- Review generated negative keywords weekly
3. Ad Performance Monitoring Script
What it does: Pauses underperforming ads and sends alerts for review
function main() {
var EMAIL_ADDRESSES = ["marketing@yourcompany.com"];
var MIN_IMPRESSIONS = 1000;
var MIN_CTR = 0.01; // 1%
var MAX_CPA = 75; // Adjust based on your targets
var poorPerformingAds = [];
var adIterator = AdsApp.ads()
.withCondition("Status = ENABLED")
.withCondition("Type = EXPANDED_TEXT_AD")
.forDateRange("LAST_14_DAYS")
.get();
while (adIterator.hasNext()) {
var ad = adIterator.next();
var stats = ad.getStatsFor("LAST_14_DAYS");
var impressions = stats.getImpressions();
var clicks = stats.getClicks();
var conversions = stats.getConversions();
var cost = stats.getCost();
if (impressions < MIN_IMPRESSIONS) continue;
var ctr = clicks / impressions;
var cpa = conversions > 0 ? cost / conversions : Infinity;
if (ctr < MIN_CTR || cpa > MAX_CPA) {
var adGroup = ad.getAdGroup();
var campaign = adGroup.getCampaign();
poorPerformingAds.push({
campaignName: campaign.getName(),
adGroupName: adGroup.getName(),
headline: ad.getHeadline(),
ctr: (ctr * 100).toFixed(2),
cpa: cpa === Infinity ? "No conversions" : cpa.toFixed(2),
action: "Paused"
});
ad.pause();
Logger.log("Paused ad: " + ad.getHeadline() +
" (CTR: " + (ctr * 100).toFixed(2) + "%, CPA: $" +
(cpa === Infinity ? "No conversions" : cpa.toFixed(2)) + ")");
}
}
// Send email report
if (poorPerformingAds.length > 0) {
sendPerformanceAlert(poorPerformingAds, EMAIL_ADDRESSES);
}
}
function sendPerformanceAlert(ads, emails) {
var subject = "Google Ads: " + ads.length + " underperforming ads paused";
var body = "The following ads have been automatically paused due to poor performance:\n\n";
for (var i = 0; i < ads.length; i++) {
var ad = ads[i];
body += "Campaign: " + ad.campaignName + "\n";
body += "Ad Group: " + ad.adGroupName + "\n";
body += "Headline: " + ad.headline + "\n";
body += "CTR: " + ad.ctr + "%\n";
body += "CPA: $" + ad.cpa + "\n";
body += "Action: " + ad.action + "\n\n";
}
body += "Please review and create new ad variations to test.";
MailApp.sendEmail({
to: emails.join(","),
subject: subject,
body: body
});
}
4. Budget Pacing Script
What it does: Monitors and adjusts daily budgets to ensure monthly spend targets
function main() {
var campaigns = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.get();
while (campaigns.hasNext()) {
var campaign = campaigns.next();
var campaignName = campaign.getName();
// Skip if campaign name doesn't include monthly budget info
// Expected format: "Campaign Name [Monthly: 1500]"
var monthlyBudgetMatch = campaignName.match(/\[Monthly:\s*(\d+)\]/);
if (!monthlyBudgetMatch) continue;
var monthlyBudget = parseFloat(monthlyBudgetMatch[1]);
var currentBudget = campaign.getBudget();
// Calculate optimal daily budget based on month progress
var today = new Date();
var daysInMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();
var dayOfMonth = today.getDate();
var daysRemaining = daysInMonth - dayOfMonth + 1;
// Get month-to-date spend
var firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
var dateRange = Utilities.formatDate(firstDayOfMonth, "PST", "yyyyMMdd") + "," +
Utilities.formatDate(today, "PST", "yyyyMMdd");
var stats = campaign.getStatsFor(dateRange);
var monthToDateSpend = stats.getCost();
var remainingBudget = monthlyBudget - monthToDateSpend;
var recommendedDailyBudget = remainingBudget / daysRemaining;
// Adjust budget if needed (within reasonable bounds)
var minDailyBudget = monthlyBudget / daysInMonth * 0.5;
var maxDailyBudget = monthlyBudget / daysInMonth * 2.0;
recommendedDailyBudget = Math.max(minDailyBudget,
Math.min(maxDailyBudget, recommendedDailyBudget));
if (Math.abs(currentBudget - recommendedDailyBudget) > currentBudget * 0.1) {
campaign.getBudget().setAmount(recommendedDailyBudget);
Logger.log("Budget adjusted for " + campaignName +
": $" + currentBudget.toFixed(2) + " -> $" +
recommendedDailyBudget.toFixed(2));
}
}
}
5. Quality Score Monitoring Script
What it does: Tracks Quality Score changes and identifies optimization opportunities
function main() {
var QUALITY_SCORE_THRESHOLD = 7;
var MIN_IMPRESSIONS = 100;
var lowQualityKeywords = [];
var keywordIterator = AdsApp.keywords()
.withCondition("Status = ENABLED")
.withCondition("Impressions > " + MIN_IMPRESSIONS)
.forDateRange("LAST_30_DAYS")
.get();
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
var qualityScore = keyword.getQualityScore();
if (qualityScore > 0 && qualityScore < QUALITY_SCORE_THRESHOLD) {
var adGroup = keyword.getAdGroup();
var campaign = adGroup.getCampaign();
var stats = keyword.getStatsFor("LAST_30_DAYS");
lowQualityKeywords.push({
campaign: campaign.getName(),
adGroup: adGroup.getName(),
keyword: keyword.getText(),
qualityScore: qualityScore,
impressions: stats.getImpressions(),
ctr: ((stats.getClicks() / stats.getImpressions()) * 100).toFixed(2),
cost: stats.getCost().toFixed(2)
});
}
}
// Log results
if (lowQualityKeywords.length > 0) {
Logger.log("Found " + lowQualityKeywords.length + " keywords with QS < " +
QUALITY_SCORE_THRESHOLD);
lowQualityKeywords.forEach(function(kw) {
Logger.log("Low QS: " + kw.keyword + " (QS: " + kw.qualityScore +
", CTR: " + kw.ctr + "%, Cost: $" + kw.cost + ")");
});
// Create improvement report
generateQualityScoreReport(lowQualityKeywords);
}
}
function generateQualityScoreReport(keywords) {
var spreadsheet = SpreadsheetApp.create("Quality Score Report - " +
Utilities.formatDate(new Date(), "PST", "MM-dd-yyyy"));
var sheet = spreadsheet.getActiveSheet();
// Headers
sheet.getRange(1, 1, 1, 7).setValues([
["Campaign", "Ad Group", "Keyword", "Quality Score", "Impressions", "CTR%", "Cost"]
]);
// Data
for (var i = 0; i < keywords.length; i++) {
var kw = keywords[i];
sheet.getRange(i + 2, 1, 1, 7).setValues([[
kw.campaign, kw.adGroup, kw.keyword, kw.qualityScore,
kw.impressions, kw.ctr, kw.cost
]]);
}
Logger.log("Quality Score report created: " + spreadsheet.getUrl());
}
Advanced Script Strategies
Dynamic Keyword Bidding Based on Weather
Use Case: Seasonal products that perform differently based on weather conditions
function main() {
var WEATHER_API_KEY = "your_weather_api_key";
var LOCATION = "New York,NY"; // Adjust for your target market
// Get current weather
var weatherData = getWeatherData(LOCATION, WEATHER_API_KEY);
var temperature = weatherData.temperature;
// Adjust bids for weather-sensitive keywords
var winterKeywords = ["boots", "coats", "heaters"];
var summerKeywords = ["shorts", "sandals", "fans"];
if (temperature < 50) {
adjustKeywordBids(winterKeywords, 1.2); // Increase winter bids 20%
adjustKeywordBids(summerKeywords, 0.8); // Decrease summer bids 20%
} else if (temperature > 75) {
adjustKeywordBids(summerKeywords, 1.3);
adjustKeywordBids(winterKeywords, 0.7);
}
}
function getWeatherData(location, apiKey) {
var url = "http://api.openweathermap.org/data/2.5/weather?q=" +
location + "&appid=" + apiKey + "&units=imperial";
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
return {
temperature: data.main.temp,
condition: data.weather[0].main
};
}
function adjustKeywordBids(keywords, multiplier) {
keywords.forEach(function(keywordText) {
var keywordIterator = AdsApp.keywords()
.withCondition("Text CONTAINS '" + keywordText + "'")
.withCondition("Status = ENABLED")
.get();
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
var currentBid = keyword.bidding().getCpc();
var newBid = currentBid * multiplier;
keyword.bidding().setCpc(Math.min(newBid, 10.00)); // Cap at $10
Logger.log("Weather-adjusted bid for " + keyword.getText() +
": $" + currentBid.toFixed(2) + " -> $" + newBid.toFixed(2));
}
});
}
Competitor Ad Monitoring
What it does: Tracks competitor ad copy and positioning changes
function main() {
var COMPETITORS = ["competitor1.com", "competitor2.com"];
var MONITOR_KEYWORDS = ["protein powder", "supplements", "fitness"];
COMPETITORS.forEach(function(competitor) {
MONITOR_KEYWORDS.forEach(function(keyword) {
var searchResults = getCompetitorAds(keyword, competitor);
if (searchResults.found) {
logCompetitorActivity(competitor, keyword, searchResults);
}
});
});
}
function getCompetitorAds(keyword, competitor) {
// This would integrate with a SERP API service
// Simplified example structure
return {
found: true,
position: 2,
headline: "Best Protein Powder - Free Shipping",
description: "Premium quality whey protein...",
timestamp: new Date()
};
}
function logCompetitorActivity(competitor, keyword, results) {
Logger.log("Competitor " + competitor + " found for '" + keyword +
"' in position " + results.position);
Logger.log("Headline: " + results.headline);
Logger.log("Description: " + results.description);
// Store in spreadsheet for trend analysis
storeCompetitorData(competitor, keyword, results);
}
Inventory-Based Bid Adjustments
What it does: Adjusts bids based on inventory levels from your e-commerce platform
function main() {
var INVENTORY_ENDPOINT = "https://your-store.com/api/inventory";
var API_KEY = "your_api_key";
var inventoryData = getInventoryLevels(INVENTORY_ENDPOINT, API_KEY);
inventoryData.forEach(function(product) {
var sku = product.sku;
var stockLevel = product.quantity;
var daysOfInventory = product.daysRemaining;
var bidMultiplier = calculateBidMultiplier(stockLevel, daysOfInventory);
adjustBidsForProduct(sku, bidMultiplier);
});
}
function calculateBidMultiplier(stockLevel, daysRemaining) {
if (daysRemaining < 3) {
return 0.5; // Reduce bids for low inventory
} else if (daysRemaining > 30) {
return 1.3; // Increase bids for overstocked items
}
return 1.0; // No change
}
function adjustBidsForProduct(sku, multiplier) {
var keywordIterator = AdsApp.keywords()
.withCondition("Text CONTAINS '" + sku + "'")
.withCondition("Status = ENABLED")
.get();
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
var currentBid = keyword.bidding().getCpc();
var newBid = currentBid * multiplier;
keyword.bidding().setCpc(newBid);
Logger.log("Inventory-adjusted bid for " + keyword.getText() +
" (SKU: " + sku + "): $" + currentBid.toFixed(2) +
" -> $" + newBid.toFixed(2));
}
}
function getInventoryLevels(endpoint, apiKey) {
var headers = {
"Authorization": "Bearer " + apiKey,
"Content-Type": "application/json"
};
var response = UrlFetchApp.fetch(endpoint, {
method: "GET",
headers: headers
});
return JSON.parse(response.getContentText());
}
Script Management Best Practices
Version Control and Testing
Development Process:
- Test scripts in test accounts first
- Use preview mode for bid changes
- Implement gradual rollouts
- Monitor impact for 48-72 hours
- Keep backup copies of working scripts
Error Handling:
function main() {
try {
// Your main script logic here
executeMainLogic();
} catch (error) {
Logger.log("Script error: " + error.toString());
sendErrorAlert(error);
}
}
function sendErrorAlert(error) {
MailApp.sendEmail({
to: "admin@yourcompany.com",
subject: "Google Ads Script Error",
body: "Script failed with error: " + error.toString()
});
}
Performance Monitoring
Script Performance Metrics:
- Execution time (should be < 30 minutes)
- Memory usage
- API quota consumption
- Success/failure rates
Optimization Tips:
- Use
.withLimit()for large datasets - Implement batch processing for bulk changes
- Cache frequently accessed data
- Use parallel processing where possible
Security and Permissions
Access Control:
- Use service accounts for production scripts
- Implement approval workflows for bid changes
- Log all automated actions
- Set up rollback procedures
Data Protection:
- Never log sensitive customer data
- Use encrypted connections for external APIs
- Implement proper authentication
- Regular security audits
ROI Measurement for Scripts
Performance Tracking
Key Metrics to Monitor:
- Time saved on manual tasks
- Performance improvement percentages
- Error reduction rates
- Consistency of optimization execution
Before/After Analysis:
- 30 days pre-script performance
- 30 days post-script performance
- Account for seasonal variations
- Isolate script impact from other changes
Case Study: Goose Creek Candles Script Results
Challenge: Managing 500+ seasonal keywords across 12 product lines
Scripts Implemented:
- Automated bid management based on seasonality
- Negative keyword harvesting for irrelevant queries
- Inventory-based bid adjustments
- Quality Score monitoring and alerts
Results After 90 Days:
- 23% improvement in Quality Score average
- 31% reduction in wasted spend
- 18% increase in conversion rate
- 67% time savings on daily optimizations
- $43,000 additional revenue attributed to automation
Key Success Factors:
- Gradual implementation with careful monitoring
- Custom business logic for seasonal patterns
- Integration with inventory management system
- Regular script performance reviews and updates
Implementation Timeline
Week 1: Foundation Setup
- Audit current manual processes
- Identify automation opportunities
- Set up script development environment
- Create test account for script development
Week 2: Basic Scripts Implementation
- Implement bid management script
- Set up negative keyword automation
- Create performance monitoring script
- Test all scripts in controlled environment
Week 3: Advanced Features
- Implement budget pacing script
- Set up Quality Score monitoring
- Create custom business logic scripts
- Establish error handling and alerts
Week 4: Optimization and Scaling
- Monitor script performance and impact
- Optimize for speed and efficiency
- Scale successful scripts across all campaigns
- Plan advanced automation features
Conclusion
Google Ads Scripts transform campaign management from reactive to proactive, from manual to automated, from good to exceptional.
The most successful e-commerce brands use scripts not just to save time, but to execute optimizations that humans simply cannot do at scale. They automate the routine to focus on the strategic.
Start with the basic scripts provided here, then customize based on your specific business needs. Monitor impact carefully and iterate based on results. The goal is consistent, data-driven optimizations that compound over time.
At ATTN Agency, our script automation has generated millions in additional revenue for clients while reducing management overhead by 40-70%. The secret is treating scripts as strategic tools, not just time-savers.
Remember: The best script is the one that solves your specific business problem. Start simple, prove value, then expand.
Ready to automate your Google Ads for better performance and efficiency? Contact ATTN Agency to learn how our custom script solutions have helped DTC brands improve performance by 15-30% while reducing management time by 50%.
Related Articles
- Advanced Google Ads Scripts for DTC Automation: Performance Optimization and Campaign Management at Scale 2026
- Advanced Google Ads Scripts for DTC Automation and Optimization
- Google AI Max Creative Controls: Advanced Campaign Optimization for 2026
- Google Ads Negative Keywords Strategy: Stop Wasting 30% of Your Ad Spend
- Google Ads Performance Max: Advanced Optimization Strategies for DTC Brands in 2026
Additional Resources
- Google Ads Keyword Planning Guide
- Google Ads Resource Center
- Harvard Business Review - Marketing
- Klaviyo Email Platform
- VWO Conversion Optimization Guide
Ready to Grow Your Brand?
ATTN Agency helps DTC and e-commerce brands scale profitably through paid media, email, SMS, and more. Whether you're looking to optimize your current strategy or launch something new, we'd love to chat.
Book a Free Strategy Call or Get in Touch to learn how we can help your brand grow.