
📋 Framework Overview
This framework breaks down Google Ads management into seven distinct phases, each with clear objectives and deliverables. Use this as your north star when planning, launching, and optimizing campaigns.
Step 1: Campaign Strategy & Goal Setting
Objective: Define clear business goals and translate them into measurable campaign objectives.
What to do:
Identify your primary business goal (leads, sales, brand awareness, app installs)
Set specific KPI targets: CPA, ROAS, conversion volume, CTR benchmarks
Determine budget allocation across campaigns and ad groups
Map out customer journey stages and align ad messaging accordingly
Document your target audience: demographics, pain points, search intent
Deliverables:
Campaign brief document
KPI targets spreadsheet
Budget allocation plan
Audience persona profiles
Step 2: Keyword Research & Account Structure
Objective: Build a robust keyword foundation and logical account architecture.
What to do:
Conduct comprehensive keyword research using Google Keyword Planner, SEMrush, or similar tools
Organize keywords by theme, intent (informational, navigational, transactional), and match type
Create tightly themed ad groups (5-20 keywords per ad group)
Develop negative keyword lists at campaign and account level
Structure campaigns by product/service line, geography, or funnel stage
Deliverables:
Master keyword list with search volumes and CPC estimates
Account structure diagram
Negative keyword master list
Ad group mapping document
Step 3: Ad Copy & Creative Development
Objective: Write compelling ad copy that drives clicks and conversions.
What to do:
Write 3-5 ad variations per ad group (use Responsive Search Ads)
Incorporate target keywords in headlines and descriptions
Highlight unique value propositions, offers, and CTAs
Test different messaging angles: features vs. benefits, urgency vs. trust
Ensure ad copy matches landing page messaging
Add all relevant ad extensions (sitelinks, callouts, structured snippets, call extensions)
Deliverables:
Ad copy spreadsheet with all variations
Ad extensions library
Brand messaging guidelines
Step 4: Landing Page Setup & QA
Objective: Ensure landing pages are optimized for conversion and align with ad messaging.
What to do:
Review landing page load speed (target <3 seconds)
Verify message match between ads and landing pages
Check form functionality and tracking implementation
Ensure mobile responsiveness
Add conversion tracking pixels (Google Ads, Google Analytics 4)
Set up conversion goals in Google Ads
Test all CTAs and user flows
Deliverables:
Landing page QA checklist (completed)
Conversion tracking documentation
Page speed test results
Step 5: Campaign Launch & Initial Monitoring
Objective: Launch campaigns smoothly and catch any issues within the first 48-72 hours.
What to do:
Double-check budget settings, bid strategies, and targeting parameters
Verify conversion tracking is firing correctly
Monitor search term reports for irrelevant queries
Add negative keywords based on initial data
Check impression share and ad position metrics
Ensure ads are running (not paused or disapproved)
Deliverables:
Launch checklist (completed)
Initial performance snapshot
First batch of negative keywords
Step 6: Ongoing Optimization & Testing
Objective: Continuously improve campaign performance through data-driven optimizations.
What to do:
Review search term reports and add negative keywords
Pause underperforming keywords and ads
Test new ad copy variations
Adjust bids based on performance data
Expand winning keywords to new ad groups
Review audience insights and adjust targeting
Test landing page variations
Optimize Quality Scores (improve CTR, relevance, landing page experience)
Deliverables:
Weekly optimization reports
A/B test results documentation
Updated keyword and negative keyword lists
Step 7: Reporting & Strategic Review
Objective: Analyze performance, extract insights, and plan strategic adjustments.
What to do:
Compile monthly performance reports with KPI tracking
Analyze trends: what's working, what's not, and why
Calculate ROI and present business impact
Identify opportunities for expansion or budget reallocation
Review competitive landscape and adjust strategy
Document learnings and best practices for future campaigns
Deliverables:
Monthly performance report
Strategic recommendations deck
Updated campaign roadmap
✅ Actionable Checklists
Pre-Launch Checklist
Campaign Setup
Campaign objectives and goals documented — Strategist/Account Manager — One-time
Budget allocated across campaigns — Strategist/Account Manager — One-time
Keyword research completed — PPC Specialist — One-time
Account structure finalized — PPC Specialist — One-time
Ad groups created with themed keywords — PPC Specialist — One-time
Negative keyword lists uploaded — PPC Specialist — One-time
Ad Copy & Extensions
Responsive Search Ads written (3-5 per ad group) — Copywriter/PPC Specialist — One-time
Ad extensions created (sitelinks, callouts, structured snippets) — PPC Specialist — One-time
Call extensions added with correct phone numbers — PPC Specialist — One-time
Ad copy reviewed for brand compliance — Account Manager — One-time
Landing Pages & Tracking
Landing pages created and optimized — Web Developer/Designer — One-time
Message match verified between ads and landing pages — PPC Specialist — One-time
Page load speed tested (<3 seconds) — Web Developer — One-time
Mobile responsiveness confirmed — Web Developer — One-time
Google Ads conversion tracking installed — PPC Specialist/Developer — One-time
Google Analytics 4 connected and configured — PPC Specialist/Developer — One-time
Conversion actions tested and verified — PPC Specialist — One-time
Form submissions and phone calls tracked — Developer — One-time
Final Checks
Bid strategy selected and configured — PPC Specialist — One-time
Budget pacing settings verified — PPC Specialist — One-time
Targeting parameters confirmed (location, language, devices) — PPC Specialist — One-time
Ad scheduling set (if applicable) — PPC Specialist — One-time
Client approval received — Account Manager — One-time
Launch date and time scheduled — PPC Specialist — One-time
Daily Management Checklist
Performance Monitoring
Check campaign spend vs. budget pacing — PPC Specialist — Daily (9 AM)
Review conversion data for anomalies — PPC Specialist — Daily (9 AM)
Monitor impression share and lost IS (budget/rank) — PPC Specialist — Daily (9 AM)
Check for disapproved ads or policy violations — PPC Specialist — Daily (9 AM)
Review automated alerts and notifications — PPC Specialist — Daily (9 AM)
Quick Optimizations
Add negative keywords from search terms report — PPC Specialist — Daily (11 AM)
Pause keywords with high spend and zero conversions — PPC Specialist — Daily (11 AM)
Respond to any client questions or concerns — Account Manager — Daily (as needed)
Weekly Optimization Checklist
Search Terms & Keywords
Full search terms report review — PPC Specialist — Weekly (Monday)
Add 10-20 new negative keywords — PPC Specialist — Weekly (Monday)
Identify and promote high-performing search terms to keywords — PPC Specialist — Weekly (Monday)
Pause keywords with poor Quality Scores (<4) or no impressions — PPC Specialist — Weekly (Monday)
Ad Performance
Review ad performance by CTR and conversion rate — PPC Specialist — Weekly (Tuesday)
Pause ads with CTR <50% of ad group average — PPC Specialist — Weekly (Tuesday)
Launch new ad copy variations for testing — Copywriter/PPC Specialist — Weekly (Tuesday)
Update ad extensions based on performance — PPC Specialist — Weekly (Tuesday)
Bid Management
Review keyword-level performance (CPA, ROAS, conversions) — PPC Specialist — Weekly (Wednesday)
Adjust bids on top-performing keywords (+10-20%) — PPC Specialist — Weekly (Wednesday)
Reduce bids on underperformers (-10-20%) — PPC Specialist — Weekly (Wednesday)
Review automated bidding strategy performance — PPC Specialist — Weekly (Wednesday)
Budget & Pacing
Analyze budget utilization across campaigns — PPC Specialist — Weekly (Thursday)
Reallocate budget from low to high performers — PPC Specialist/Account Manager — Weekly (Thursday)
Forecast spend to end of month — PPC Specialist — Weekly (Thursday)
Reporting
Generate weekly performance snapshot — PPC Specialist — Weekly (Friday)
Document key wins and optimizations — PPC Specialist — Weekly (Friday)
Share client-facing update (if required) — Account Manager — Weekly (Friday)
Post-Campaign Wrap-Up Checklist
Performance Analysis
Pull final campaign performance report — PPC Specialist — One-time
Calculate final ROAS, CPA, and other KPIs — PPC Specialist — One-time
Compare actual vs. target performance — PPC Specialist — One-time
Analyze top-performing keywords, ads, and audiences — PPC Specialist — One-time
Identify underperforming elements and root causes — PPC Specialist — One-time
Documentation
Compile master keyword list (winners and losers) — PPC Specialist — One-time
Document negative keyword additions — PPC Specialist — One-time
Save top-performing ad copy for future use — Copywriter/PPC Specialist — One-time
Screenshot best-performing landing pages — PPC Specialist — One-time
Create campaign post-mortem document — Account Manager — One-time
Client Deliverables
Prepare final campaign report with insights — Account Manager — One-time
Schedule client review meeting — Account Manager — One-time
Present findings and recommendations — Account Manager — One-time
Gather client feedback — Account Manager — One-time
Next Steps
Archive campaign or keep paused for future reactivation — PPC Specialist — One-time
Update account-level negative keyword lists — PPC Specialist — One-time
Apply learnings to active campaigns — PPC Specialist — One-time
Plan next campaign iteration or new initiatives — Strategist/Account Manager — One-time
Download the Excel Checklist
A companion spreadsheet is available to track task completion across your team.
📖 Standard Operating Procedures (SOPs)
SOP: Keyword Research
Objective: Identify high-intent, relevant keywords to drive qualified traffic.
Frequency: One-time at campaign launch; quarterly refreshes
Tools Needed: Google Keyword Planner, SEMrush, Ahrefs, or similar
Steps:
Brainstorm seed keywords — List 10-15 core terms related to your product/service
Use keyword research tools — Input seed keywords into Google Keyword Planner or third-party tools
Analyze search volume and competition — Filter for keywords with 100+ monthly searches and manageable CPC
Group keywords by theme — Organize into logical ad groups (e.g., "running shoes for women," "best trail running shoes")
Identify match types — Assign Exact, Phrase, or Broad Match Modifier based on intent
Add long-tail variations — Include specific, high-intent queries (e.g., "buy Nike running shoes size 9")
Research competitor keywords — Use SEMrush or SpyFu to see what competitors are bidding on
Build negative keyword list — Identify irrelevant terms to exclude (e.g., "free," "cheap," "jobs")
Document in master spreadsheet — Include columns for keyword, match type, search volume, CPC, ad group assignment
Review and approve — Get sign-off from account manager or client before upload
Deliverable: Master keyword list with 100-500 keywords organized by ad group
SOP: Ad Copy Writing
Objective: Create compelling, high-CTR ad copy that drives conversions.
Frequency: One-time at launch; weekly for new variations
Steps:
Review ad group keywords — Understand the theme and search intent
Identify unique selling propositions — What makes your offer better? (price, quality, speed, guarantee)
Write 15 headline variations — Include target keywords, benefits, offers, and CTAs
Write 4 description variations — Expand on value props, include social proof or urgency
Use dynamic keyword insertion (DKI) sparingly — Only where it makes sense grammatically
Follow character limits — Headlines: 30 chars max; Descriptions: 90 chars max
Pin critical elements — Pin your main headline or brand name to position 1 if needed
Create 3-5 RSA combinations per ad group — Google will test variations automatically
Add all relevant extensions — Sitelinks, callouts, structured snippets
Review for brand compliance — Ensure tone, messaging, and claims align with brand guidelines
Get approval — Review with client or account manager before launch
Monitor ad strength — Aim for "Excellent" or "Good" ad strength ratings
Deliverable: 3-5 Responsive Search Ads per ad group with full ad extensions
SOP: Bid Management
Objective: Optimize bids to maximize conversions within target CPA or ROAS.
Frequency: Weekly for manual CPC; bi-weekly for automated strategies
Steps:
Pull keyword performance report — Last 7-14 days of data (conversions, CPA, ROAS, CTR, Avg. Position)
Identify top performers — Keywords with CPA below target and strong conversion volume
Increase bids on winners — Raise bids by 10-20% to capture more volume
Identify underperformers — Keywords with high spend, zero conversions, or CPA above target
Decrease bids on losers — Lower bids by 10-20% or pause if consistently poor
Review impression share — If IS Lost (Rank) is high, consider bid increases
Check Quality Score — Low QS keywords may need ad copy or landing page improvements, not just bid changes
Adjust for device performance — Increase/decrease mobile bid adjustments based on conversion data
Monitor automated bid strategy performance — If using Target CPA or Maximize Conversions, review learning period and performance trends
Document changes — Note all bid adjustments in optimization log
Deliverable: Updated keyword bids; optimization log with rationale
SOP: Landing Page QA
Objective: Ensure landing pages are conversion-optimized and technically sound.
Frequency: One-time before launch; monthly spot checks
Tools Needed: Google PageSpeed Insights, GTmetrix, Google Tag Assistant
Steps:
Check page load speed — Test on desktop and mobile using PageSpeed Insights (target: <3 seconds)
Verify mobile responsiveness — Test on multiple devices and screen sizes
Review message match — Ensure headline and copy align with ad messaging
Test form functionality — Submit test leads to verify form submissions work
Check CTA visibility — Ensure primary CTA is above the fold and stands out
Verify tracking implementation — Use Google Tag Assistant to confirm conversion tags fire correctly
Test all links — Ensure no broken links or 404 errors
Review trust signals — Check for security badges, testimonials, social proof
Optimize images — Compress large images to improve load speed
Run accessibility check — Ensure compliance with WCAG guidelines (contrast, alt text)
Test across browsers — Chrome, Safari, Firefox, Edge
Document findings — Create QA report with issues and fixes
Deliverable: QA report with pass/fail status and action items
SOP: Search Terms Report Review
Objective: Identify irrelevant queries and add negative keywords to improve efficiency.
Frequency: Daily for first week; then weekly
Steps:
Pull search terms report — Last 7 days, all campaigns
Filter by clicks or impressions — Focus on terms with meaningful volume
Identify irrelevant queries — Flag searches that don't match intent (e.g., "free," "jobs," "DIY")
Add negative keywords — Add at ad group, campaign, or account level depending on relevance
Choose correct match type — Use Exact for specific terms, Phrase for broader exclusions
Identify expansion opportunities — Promote high-performing search terms to keywords
Flag quality issues — Note any terms that indicate poor keyword targeting
Update negative keyword master list — Document all additions for future reference
Review regularly — Repeat weekly to catch new irrelevant queries
Monitor impact — Track how negative keywords improve CTR and reduce wasted spend
Deliverable: Updated negative keyword lists; list of search terms promoted to keywords
📊 KPI Dashboard
Core Metrics Definitions
Impressions
Definition: Number of times your ad was shown
Why it matters: Indicates reach and visibility
Target: Varies by campaign; monitor impression share
Clicks
Definition: Number of times users clicked your ad
Why it matters: Shows ad engagement and interest
Target: Varies by campaign; aim for consistent volume
CTR (Click-Through Rate)
Definition: (Clicks ÷ Impressions) × 100
Why it matters: Measures ad relevance and appeal
Target: 3-5% for search campaigns; 0.5-1% for display
Notion Formula:
prop("Clicks") / prop("Impressions") * 100
CPC (Cost Per Click)
Definition: Total cost ÷ Total clicks
Why it matters: Shows how much you pay per click
Target: Varies by industry; aim to reduce over time
Notion Formula:
prop("Cost") / prop("Clicks")
Conversions
Definition: Number of desired actions completed (purchases, leads, signups)
Why it matters: Direct measure of campaign effectiveness
Target: Based on business goals and budget
Conversion Rate
Definition: (Conversions ÷ Clicks) × 100
Why it matters: Shows how well your landing page converts traffic
Target: 2-5% for most industries; 10%+ for high-intent campaigns
Notion Formula:
prop("Conversions") / prop("Clicks") * 100
CPA (Cost Per Acquisition)
Definition: Total cost ÷ Total conversions
Why it matters: Shows how much you pay per conversion
Target: Must be lower than customer lifetime value (LTV)
Notion Formula:
prop("Cost") / prop("Conversions")
ROAS (Return on Ad Spend)
Definition: Revenue generated ÷ Ad spend
Why it matters: Measures profitability and ROI
Target: Minimum 4:1 for ecommerce; varies by business model
Notion Formula:
prop("Revenue") / prop("Cost")
Quality Score
Definition: Google's 1-10 rating based on expected CTR, ad relevance, landing page experience
Why it matters: Higher QS = lower CPCs and better ad positions
Target: 7-10 (anything below 5 needs immediate attention)
Impression Share
Definition: (Impressions received ÷ Total eligible impressions) × 100
Why it matters: Shows how often your ad could have shown but didn't
Target: 80%+ for branded campaigns; 50-70% for competitive terms
Notion Formula:
prop("Impressions") / prop("Eligible Impressions") * 100
🤖 Google Ads Automation Scripts
Script 1: Pause Low-Quality Keywords
Purpose: Automatically pauses keywords with Quality Score below 4 to prevent wasted spend.
How to schedule: Set to run daily at 2 AM
// Pause Low Quality Score Keywords
function main() {
var QUALITY_SCORE_THRESHOLD = 4;
var keywordIterator = AdsApp.keywords()
.withCondition("Status = ENABLED")
.withCondition("QualityScore < " + QUALITY_SCORE_THRESHOLD)
.get();
var pausedCount = 0;
while (keywordIterator.hasNext()) {
var keyword = keywordIterator.next();
keyword.pause();
pausedCount++;
Logger.log("Paused keyword: " + keyword.getText() + " (QS: " + keyword.getQualityScore() + ")");
}
Logger.log("Total keywords paused: " + pausedCount);
// Send email notification
if (pausedCount > 0) {
MailApp.sendEmail({
to: "[email protected]",
subject: "Google Ads: " + pausedCount + " Low QS Keywords Paused",
body: "Check Google Ads script logs for details."
});
}
}Script 2: Pause Ads with High Spend and No Conversions
Purpose: Pauses ads that have spent more than $50 with zero conversions in the last 30 days.
How to schedule: Set to run weekly on Monday mornings
// Pause High-Spend, Zero-Conversion Ads
function main() {
var SPEND_THRESHOLD = 50;
var DATE_RANGE = "LAST_30_DAYS";
var adIterator = AdsApp.ads()
.withCondition("Status = ENABLED")
.withCondition("Conversions = 0")
.withCondition("Cost > " + SPEND_THRESHOLD)
.forDateRange(DATE_RANGE)
.get();
var pausedCount = 0;
while (adIterator.hasNext()) {
var ad = adIterator.next();
var stats = ad.getStatsFor(DATE_RANGE);
ad.pause();
pausedCount++;
Logger.log("Paused ad in campaign: " + ad.getCampaign().getName() +
" | Spend: $" + stats.getCost().toFixed(2) + " | Conversions: 0");
}
Logger.log("Total ads paused: " + pausedCount);
if (pausedCount > 0) {
MailApp.sendEmail({
to: "[email protected]",
subject: "Google Ads: " + pausedCount + " Zero-Conversion Ads Paused",
body: "Check logs for details on which ads were paused."
});
}
}Script 3: Daily Email Performance Summary
Purpose: Sends a daily email with key metrics from yesterday's performance.
How to schedule: Set to run daily at 8 AM
// Daily Performance Email Summary
function main() {
var DATE_RANGE = "YESTERDAY";
var accountStats = AdsApp.currentAccount().getStatsFor(DATE_RANGE);
var impressions = accountStats.getImpressions();
var clicks = accountStats.getClicks();
var cost = accountStats.getCost();
var conversions = accountStats.getConversions();
var ctr = accountStats.getCtr();
var cpa = conversions > 0 ? cost / conversions : 0;
var emailBody = "Google Ads Daily Performance Summary - " + DATE_RANGE + "\n\n";
emailBody += "Impressions: " + impressions.toLocaleString() + "\n";
emailBody += "Clicks: " + clicks.toLocaleString() + "\n";
emailBody += "CTR: " + (ctr * 100).toFixed(2) + "%\n";
emailBody += "Cost: $" + cost.toFixed(2) + "\n";
emailBody += "Conversions: " + conversions + "\n";
emailBody += "CPA: $" + cpa.toFixed(2) + "\n";
MailApp.sendEmail({
to: "[email protected]",
subject: "Google Ads Daily Summary - " + new Date().toLocaleDateString(),
body: emailBody
});
Logger.log(emailBody);
}Script 4: Label Top-Performing Search Queries
Purpose: Automatically labels search queries with 3+ conversions and CPA below target as "Top Performer".
How to schedule: Set to run weekly on Wednesdays
// Label Top-Performing Search Queries
function main() {
var MIN_CONVERSIONS = 3;
var MAX_CPA = 50; // Adjust to your target CPA
var LABEL_NAME = "Top Performer";
// Create label if it doesn't exist
if (!AdsApp.labels().withCondition("Name = '" + LABEL_NAME + "'").get().hasNext()) {
AdsApp.createLabel(LABEL_NAME);
}
var searchQueryReport = AdsApp.report(
"SELECT Query, Conversions, Cost, CampaignName " +
"FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
"WHERE Conversions >= " + MIN_CONVERSIONS + " " +
"AND Cost / Conversions <= " + MAX_CPA + " " +
"DURING LAST_30_DAYS"
);
var rows = searchQueryReport.rows();
var labeledCount = 0;
while (rows.hasNext()) {
var row = rows.next();
Logger.log("Top performer: " + row["Query"] + " | Conversions: " + row["Conversions"] +
" | CPA: $" + (row["Cost"] / row["Conversions"]).toFixed(2));
labeledCount++;
}
Logger.log("Total top-performing queries identified: " + labeledCount);
MailApp.sendEmail({
to: "[email protected]",
subject: "Google Ads: " + labeledCount + " Top Performers Identified",
body: "Check script logs for query details."
});
}Script 5: Auto-Add Negative Keywords Across Campaigns
Purpose: Scans search terms and adds common negative keywords to all campaigns.
How to schedule: Set to run daily at 3 AM
// Auto-Add Negative Keywords
function main() {
var NEGATIVE_KEYWORDS = ["free", "cheap", "jobs", "career", "salary", "diy", "tutorial", "download"];
var campaignIterator = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.get();
var addedCount = 0;
while (campaignIterator.hasNext()) {
var campaign = [campaignIterator.next](<http://campaignIterator.next>)();
for (var i = 0; i < NEGATIVE_KEYWORDS.length; i++) {
var negativeKeyword = NEGATIVE_KEYWORDS[i];
// Check if negative keyword already exists
var existingNegatives = campaign.negativeKeywords()
.withCondition("Text = '" + negativeKeyword + "'")
.get();
if (!existingNegatives.hasNext()) {
campaign.createNegativeKeyword("[" + negativeKeyword + "]"); // Exact match
addedCount++;
Logger.log("Added negative keyword '" + negativeKeyword + "' to campaign: " + campaign.getName());
}
}
}
Logger.log("Total negative keywords added: " + addedCount);
if (addedCount > 0) {
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads: " + addedCount + " Negative Keywords Added",
body: "Check logs for details."
});
}
}
Script 6: Smart Bid Adjustment for High & Low Performing Keywords
Purpose: Automatically increases bids on high performers and decreases bids on underperformers.
How to schedule: Set to run daily at 1 AM
// Smart Bid Adjustment Script
function main() {
var MIN_CONVERSIONS = 2;
var TARGET_CPA = 50; // Adjust to your target
var BID_INCREASE = 0.15; // 15% increase
var BID_DECREASE = 0.15; // 15% decrease
var MIN_SPEND = 20; // Minimum spend to consider
var keywordIterator = AdsApp.keywords()
.withCondition("Status = ENABLED")
.forDateRange("LAST_14_DAYS")
.get();
var increasedCount = 0;
var decreasedCount = 0;
while (keywordIterator.hasNext()) {
var keyword = [keywordIterator.next](<http://keywordIterator.next>)();
var stats = keyword.getStatsFor("LAST_14_DAYS");
var conversions = stats.getConversions();
var cost = stats.getCost();
var currentBid = keyword.bidding().getCpc();
// High performer: Increase bid
if (conversions >= MIN_CONVERSIONS && (cost / conversions) < TARGET_CPA) {
var newBid = currentBid * (1 + BID_INCREASE);
keyword.bidding().setCpc(newBid);
increasedCount++;
Logger.log("Increased bid for: " + keyword.getText() + " | Old: $" + currentBid.toFixed(2) +
" | New: $" + newBid.toFixed(2));
}
// Low performer: Decrease bid
if (conversions === 0 && cost > MIN_SPEND) {
var newBid = currentBid * (1 - BID_DECREASE);
keyword.bidding().setCpc(newBid);
decreasedCount++;
Logger.log("Decreased bid for: " + keyword.getText() + " | Old: $" + currentBid.toFixed(2) +
" | New: $" + newBid.toFixed(2));
}
}
Logger.log("Bids increased: " + increasedCount + " | Bids decreased: " + decreasedCount);
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads Bid Adjustments: +" + increasedCount + " / -" + decreasedCount,
body: "Check logs for keyword-level details."
});
}
Script 7: Auto-Expand Winning Search Terms into New Keywords
Purpose: Promotes high-performing search terms into keywords.
How to schedule: Set to run weekly on Fridays
// Auto-Expand Winning Search Terms
function main() {
var MIN_CONVERSIONS = 3;
var MAX_CPA = 50; // Adjust to your target CPA
var searchQueryReport = [AdsApp.report](<http://AdsApp.report>)(
"SELECT Query, Conversions, Cost, CampaignId, AdGroupId " +
"FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
"WHERE Conversions >= " + MIN_CONVERSIONS + " " +
"AND Cost / Conversions <= " + MAX_CPA + " " +
"DURING LAST_30_DAYS"
);
var rows = searchQueryReport.rows();
var addedCount = 0;
while (rows.hasNext()) {
var row = [rows.next](<http://rows.next>)();
var query = row["Query"];
var adGroupId = row["AdGroupId"];
var adGroup = AdsApp.adGroups()
.withIds([adGroupId])
.get()
.next();
// Check if keyword already exists
var existingKeywords = adGroup.keywords()
.withCondition("Text = '" + query + "'")
.get();
if (!existingKeywords.hasNext()) {
adGroup.newKeywordBuilder()
.withText(query)
.build();
addedCount++;
Logger.log("Added new keyword: '" + query + "' to ad group: " + adGroup.getName());
}
}
Logger.log("Total new keywords added: " + addedCount);
if (addedCount > 0) {
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads: " + addedCount + " Winning Search Terms Promoted",
body: "Check logs for details."
});
}
}
Script 8: Budget Rebalancer
Purpose: Reallocates budget from underperforming to top-performing campaigns.
How to schedule: Set to run weekly on Mondays
// Budget Rebalancer Script
function main() {
var BUDGET_CHANGE = 0.10; // 10% adjustment
var MIN_SPEND = 100; // Minimum spend to consider
var campaignData = [];
var campaignIterator = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.forDateRange("LAST_14_DAYS")
.get();
// Collect campaign performance data
while (campaignIterator.hasNext()) {
var campaign = [campaignIterator.next](<http://campaignIterator.next>)();
var stats = campaign.getStatsFor("LAST_14_DAYS");
var cost = stats.getCost();
var conversions = stats.getConversions();
var cpa = conversions > 0 ? cost / conversions : 999999;
if (cost >= MIN_SPEND) {
campaignData.push({
campaign: campaign,
cpa: cpa,
conversions: conversions,
cost: cost
});
}
}
// Sort by CPA (ascending)
campaignData.sort(function(a, b) { return [a.cpa](<http://a.cpa>) - [b.cpa](<http://b.cpa>); });
var topPerformers = campaignData.slice(0, Math.ceil(campaignData.length * 0.3));
var bottomPerformers = campaignData.slice(-Math.ceil(campaignData.length * 0.3));
// Increase budget for top performers
for (var i = 0; i < topPerformers.length; i++) {
var campaign = topPerformers[i].campaign;
var currentBudget = campaign.getBudget().getAmount();
var newBudget = currentBudget * (1 + BUDGET_CHANGE);
campaign.getBudget().setAmount(newBudget);
Logger.log("Increased budget for: " + campaign.getName() + " | Old: $" + currentBudget.toFixed(2) +
" | New: $" + newBudget.toFixed(2));
}
// Decrease budget for bottom performers
for (var j = 0; j < bottomPerformers.length; j++) {
var campaign = bottomPerformers[j].campaign;
var currentBudget = campaign.getBudget().getAmount();
var newBudget = currentBudget * (1 - BUDGET_CHANGE);
campaign.getBudget().setAmount(newBudget);
Logger.log("Decreased budget for: " + campaign.getName() + " | Old: $" + currentBudget.toFixed(2) +
" | New: $" + newBudget.toFixed(2));
}
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads: Budget Rebalanced Across Campaigns",
body: "Check logs for campaign-level changes."
});
}
Script 9: Quality Score Recovery Script
Purpose: Flags keywords with low Quality Score components and emails recommendations.
How to schedule: Set to run weekly on Tuesdays
// Quality Score Recovery Script
function main() {
var LOW_QS_THRESHOLD = 5;
var report = [AdsApp.report](<http://AdsApp.report>)(
"SELECT CampaignName, AdGroupName, Criteria, QualityScore, " +
"CreativeQualityScore, SearchPredictedCtr, PostClickQualityScore " +
"FROM KEYWORDS_PERFORMANCE_REPORT " +
"WHERE QualityScore < " + LOW_QS_THRESHOLD + " " +
"AND Status = ENABLED " +
"DURING LAST_30_DAYS"
);
var rows = report.rows();
var issues = [];
while (rows.hasNext()) {
var row = [rows.next](<http://rows.next>)();
var keyword = row["Criteria"];
var qs = row["QualityScore"];
var expectedCtr = row["SearchPredictedCtr"];
var adRelevance = row["CreativeQualityScore"];
var lpExperience = row["PostClickQualityScore"];
var recommendations = [];
if (expectedCtr === "Below average" || expectedCtr === "1") {
recommendations.push("Improve ad copy CTR");
}
if (adRelevance === "Below average" || adRelevance === "1") {
recommendations.push("Improve ad relevance to keyword");
}
if (lpExperience === "Below average" || lpExperience === "1") {
recommendations.push("Improve landing page experience");
}
issues.push({
keyword: keyword,
qs: qs,
fixes: recommendations.join(", ")
});
}
if (issues.length > 0) {
var emailBody = "Quality Score Issues Detected:\\n\\n";
for (var i = 0; i < issues.length; i++) {
emailBody += "Keyword: " + issues[i].keyword + " (QS: " + issues[i].qs + ")\\n";
emailBody += "Recommended fixes: " + issues[i].fixes + "\\n\\n";
}
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads: " + issues.length + " Low Quality Score Keywords Flagged",
body: emailBody
});
Logger.log(emailBody);
} else {
Logger.log("No low QS keywords found.");
}
}
Script 10: Ad Extension Checker
Purpose: Scans campaigns for missing or underperforming ad extensions.
How to schedule: Set to run daily at 9 AM
// Ad Extension Health Check Script
function main() {
var issues = [];
var campaignIterator = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.get();
while (campaignIterator.hasNext()) {
var campaign = [campaignIterator.next](<http://campaignIterator.next>)();
var campaignName = campaign.getName();
// Check for sitelinks
var sitelinks = campaign.extensions().sitelinks().get();
if (!sitelinks.hasNext()) {
issues.push(campaignName + ": Missing sitelinks");
}
// Check for callouts
var callouts = campaign.extensions().callouts().get();
if (!callouts.hasNext()) {
issues.push(campaignName + ": Missing callouts");
}
// Check for structured snippets
var snippets = campaign.extensions().snippets().get();
if (!snippets.hasNext()) {
issues.push(campaignName + ": Missing structured snippets");
}
// Check for phone extensions
var phoneNumbers = campaign.extensions().phoneNumbers().get();
if (!phoneNumbers.hasNext()) {
issues.push(campaignName + ": Missing call extensions");
}
}
if (issues.length > 0) {
var emailBody = "Ad Extension Issues Detected:\\n\\n";
for (var i = 0; i < issues.length; i++) {
emailBody += issues[i] + "\\n";
}
emailBody += "\\nPlease review and add missing extensions to improve ad performance.";
MailApp.sendEmail({
to: "[[email protected]](<mailto:[email protected]>)",
subject: "Google Ads: " + issues.length + " Extension Issues Found",
body: emailBody
});
Logger.log(emailBody);
} else {
Logger.log("All campaigns have complete ad extensions.");
}
}
🎯 How to Use This Framework
Bookmark this page — Keep it accessible for daily reference
Customize to your needs — Adjust KPI targets, script thresholds, and checklists based on your campaigns
Schedule scripts in Google Ads — Go to Tools > Bulk Actions > Scripts, paste code, and set frequency
Review weekly — Use the checklists to ensure nothing slips through the cracks
Iterate and improve — Track what works, document learnings, and refine your approach
Questions or feedback? Use this framework as your foundation and adapt as you scale your Google Ads expertise.

