πŸ€–chiliad
ClaudePricing
Back to blog
October 1, 2026Β·Dmytro Tonkikh

Google Ads Scripts Guide for 2026: Write, Test and Control Scripts with AI

google ads scripts
guide
ai
claude
testing

For thirteen years the hard part of Google Ads scripts was writing them. You needed JavaScript, a feel for Google’s object model, and the patience to debug in a tiny browser editor. In 2026 that part is close to solved: describe what you want to an AI assistant like Claude and you get working code in a minute.

Which means the hard part has moved. A script that pauses keywords, changes budgets or adds negatives is a program with write access to someone’s ad spend, and it keeps running on a schedule long after you stop thinking about it. The skills that matter now are choosing what to automate, knowing what a good script looks like, briefing it properly, testing it against real accounts, and controlling it once it is live.

This guide covers all of that, with one complete script you can paste into Google Ads today. If you have never run a script before, start with the beginner’s guide and come back β€” this one assumes you know what main() and Preview are.

In this guide:

  • Where scripts fit in 2026
  • What to automate first
  • What a modern script looks like
  • Writing scripts with AI
  • A complete example, and how to review it
  • Testing beyond Preview
  • Scheduling and limits
  • Control after launch
  • FAQ

What Changed for Scripts in 2026

  • AI writes the code. You no longer need to be a developer to get a custom script. You do need to say precisely what it should do β€” and be able to check that it does.
  • GAQL and mutate cover everything. Modern scripts read with AdsApp.search() and write with AdsApp.mutate(), which reach nearly everything the Google Ads API can, including Performance Max and Demand Gen. Scripts copied from old blog posts with AWQL report queries simply fail.
  • AI can be connected to the account. Through MCP (Model Context Protocol) connectors, an assistant can query real campaigns and read real run logs instead of guessing from your description.
  • The limits did not move. Scripts still stop after 30 minutes, still run hourly at most, and Google Ads still keeps no version history and no shared library across accounts.

Where Scripts Fit in 2026

With Smart Bidding, Performance Max and AI Max doing more of the optimization, it is fair to ask what is left for scripts. The answer is everything Google’s automation does not look at. Each of those systems optimizes inside its own campaign toward its own target. None of them will tell you that the landing page is returning a 404, that the account is 30% ahead of its monthly budget, that a feed change disapproved half the catalog, or that a negative keyword is blocking your best query.

That is where scripts earn their place today:

  • Guarding β€” broken URLs, disapprovals, budget pacing, sudden drops and spikes.
  • Visibility β€” reports Google does not give you, such as n-grams across search terms or what Performance Max is actually spending on.
  • Rules across campaigns β€” business logic that spans the account: caps, schedules, labels, cleanups.

And what they are not for: a script cannot see the auction-time signals Smart Bidding uses, cannot react faster than once an hour, and cannot supply judgment. It applies your rule exactly as written, including on the day the rule is wrong.

What to Automate First: The Risk Ladder

Not all scripts carry the same risk. Before writing anything, place the idea on this ladder and start at the lowest rung that solves the problem:

RungWhat it doesWorst caseExamples
1. ReportsReads data, writes to a sheet or emailA wrong number in a reportN-gram analysis, Quality Score tracking
2. AlertsReads data, tells you when something is offA false alarm, or a missed oneLink checker, anomaly detector, budget pacing
3. Reversible changesPauses, labels, adds negativesLost traffic until someone noticesThe keyword pauser in this guide
4. Bids and budgetsChanges how much is spentReal money, quicklyBudget caps, bid rules

Most of the value sits on the first two rungs, and they are nearly risk-free. A common and sensible path is to run a rule as an alert for a few weeks, and only promote it to making changes once its alerts have been right every time. Many ideas never need to leave rung two.

What a Modern Script Looks Like

Whether you write it or an AI does, a good 2026 script has the same four parts, in this order:

  1. Settings at the top β€” every threshold, date range and email address as a named variable with a comment. Nothing buried in the logic.
  2. A short main() that reads like the plan: find, decide, act, report.
  3. Reads through GAQL. One query that returns exactly the rows the script will act on.
  4. Writes through mutate, behind a switch that is off by default.

Reading: AdsApp.search()

var rows = AdsApp.search(
  "SELECT campaign.name, metrics.cost_micros " +
  "FROM campaign " +
  "WHERE campaign.status = 'ENABLED' " +
  "AND segments.date DURING LAST_30_DAYS");

while (rows.hasNext()) {
  var row = rows.next();
  var cost = row.metrics.costMicros / 1000000;
  Logger.log(row.campaign.name + ": " + cost.toFixed(2));
}

Three rules explain most broken queries:

  • Field names are snake_case in the query and camelCase on the row: you select metrics.cost_micros and read row.metrics.costMicros.
  • Money comes back in micros β€” millionths of the currency unit. Divide by 1,000,000. A threshold compared against the raw value is off by a factor of a million, and that bug pauses everything or nothing.
  • Filter in the query, not in JavaScript. A WHERE clause is faster than looping over every keyword in the account, and it keeps you inside the 30-minute limit.

Writing: AdsApp.mutate()

var result = AdsApp.mutate({
  campaignOperation: {
    update: {
      resourceName: "customers/1234567890/campaigns/111222333",
      status: "PAUSED"
    },
    updateMask: "status"
  }
});
if (!result.isSuccessful()) {
  Logger.log(result.getErrorMessages().join(", "));
}

An update needs the resource name, the changed fields, and an updateMask naming those fields. For many changes at once, build an array of operations and send it with AdsApp.mutateAll(). And always check the result: a rejected change does not stop the script, it just returns an unsuccessful result that is easy to ignore.

The older selector style β€” AdsApp.keywords().withCondition(...).get() followed by keyword.pause() β€” still works and is fine for simple jobs. But it only covers the entities Google built selectors for. Search and mutate are the general tools, and they are what AI assistants write best because they map directly onto the public API documentation.

The Workflow

Every script that makes changes should go through the same five steps. Only one of them is writing code.

1. Brief rule, thresholds, cap, undo, safe default 2. Check the rule run the query on the real account 3. Generate AI writes it, you review it 4. Test Preview, dry runs, one pilot account 5. Control roll out, monitor, alert, roll back failures in production send you back to the code, not to a new script

Writing Scripts with AI

There are three ways to work with an assistant, and they differ mainly in how much it can see:

SetupHow it worksGood forLimitation
Chat and pasteDescribe the script, copy the code into the Google Ads script editorOne-off scripts, adapting an existing scriptThe AI sees nothing of your account; you carry errors back by hand
Coding agent with a repositoryClaude Code or similar, with your scripts kept in gitTeams maintaining a library of scriptsStill blind to the account unless you connect it
Connected to the accountAn MCP connector lets the assistant query account data and read run logsScripts grounded in real data, debugging from real errorsNeeds a connector you trust with that access

Whichever you use, the assistant writes the script and Google Ads runs it. The schedule is set in the Google Ads interface, not in the code, and nothing runs until you paste, authorize and schedule it.

The brief decides the result

The quality of an AI-written script is decided before any code exists. A vague request gets a script that does something reasonable on an imaginary account. Compare:

Write a Google Ads script that pauses keywords with no conversions.

with a brief that has the five things every script that makes changes needs:

  • The rule β€” what exactly qualifies, with numbers.
  • The minimum data β€” so a keyword with 3 clicks is not judged on 3 clicks.
  • A blast-radius limit β€” the most damage one run can do if the rule turns out to be wrong. For bids and budgets, also a maximum change per run, such as 20%.
  • An undo path β€” a label, a log of before and after values, anything that lets you reverse the run.
  • A safe default β€” it ships switched off.

Here is that brief as a template you can reuse. Replace the specifics and keep the structure:

Write a Google Ads script using AdsApp.search and AdsApp.mutate.

Goal: pause Search keywords that spend without converting.
Rule: zero conversions in the last 30 days, ending yesterday.
Minimum data: at least 50 in spend AND at least 30 clicks.
Limit: never pause more than 25 keywords in one run.
Undo: label every keyword it pauses.
Report: email me a summary of what it did.
Safety: change nothing until I set DRY_RUN to false. In Preview
  mode, change nothing and mark the email as a dry run.
Settings: every number above as a named variable at the top.
Account: single account, EUR, Search campaigns on Target CPA.

Before writing code, list your assumptions about my account.

The last two lines do more than they look. Telling the assistant about currency, campaign types and bidding strategies removes its most common wrong guesses. Asking for assumptions first surfaces the rest while they are still a sentence to correct rather than code to debug.

Check the rule against real data before you build on it

Is 50 the right spend threshold? On one account that is a rounding error; on another it is a week of budget. Before the full script exists, run just the query: ask for a read-only version that only logs the matching keywords, paste it into Google Ads and click Preview.

This does two jobs at once. You see the consequences of the rule before it can act: if the list contains your best brand keyword, the rule is wrong, not the script. And the query itself gets tested. The most common failure in AI-written scripts is a GAQL field that sounds right but does not exist, or two resources that cannot be queried together. A query that has already returned rows from your account cannot have that problem.

chiliad tip: with the chiliad connector for Claude, Claude can run read-only GAQL against your connected accounts itself. You ask “which keywords would this rule catch in Acme Store?” and get the list back in the conversation, with no copy-pasting between Claude and Google Ads.

A Complete Example

Here is the full script from that brief. It runs as-is when pasted into Google Ads, and it changes nothing until you set DRY_RUN to false.

/**
 * @name        Zero Conversion Keyword Pauser
 * @description Pauses Search keywords that spent above a threshold with
 *              zero conversions. Runs in dry-run mode until DRY_RUN is set
 *              to false, caps changes per run and labels what it pauses.
 * @author      Dmytro Tonkikh
 * @schedule    Weekly
 */

// ─── Configuration ───────────────────────────────
// How many days of data to evaluate
var LOOKBACK_DAYS = 30;
// Spend (account currency) with zero conversions before a keyword is paused
var SPEND_THRESHOLD = 50;
// Minimum clicks, so low-traffic keywords are left alone
var MIN_CLICKS = 30;
// Hard cap on how many keywords one run may pause
var MAX_PAUSES_PER_RUN = 25;
// Label applied to everything the script pauses (your undo list)
var PAUSED_LABEL = "Paused by script: zero conversions";
// Comma-separated recipients for the summary email (blank = no email)
var EMAIL_RECIPIENTS = "";
// When true, log intended changes without applying them
var DRY_RUN = true;

// ─── Main ────────────────────────────────────────
function main() {
  var dryRun = DRY_RUN || AdsApp.getExecutionInfo().isPreview();
  var candidates = findCandidates();
  var batch = candidates.slice(0, MAX_PAUSES_PER_RUN);

  Logger.log(candidates.length + " keywords match, acting on " + batch.length +
    (dryRun ? " (dry run, nothing will change)" : ""));
  batch.forEach(function (k) {
    Logger.log((dryRun ? "Would pause: " : "Pausing: ") + k.text + " | " +
      k.campaign + " | cost " + k.cost.toFixed(2) + " | clicks " + k.clicks);
  });

  var error = (!dryRun && batch.length > 0) ? pauseAndLabel(batch) : "";
  sendSummary(batch, candidates.length, dryRun);
  // Fail loudly: a thrown error marks the run as failed in the script history
  if (error) throw new Error(error);
}

// ─── Helpers ─────────────────────────────────────
function findCandidates() {
  var query =
    "SELECT ad_group_criterion.resource_name, ad_group_criterion.keyword.text, " +
    "campaign.name, metrics.cost_micros, metrics.clicks " +
    "FROM keyword_view " +
    "WHERE campaign.advertising_channel_type = 'SEARCH' " +
    "AND campaign.status = 'ENABLED' AND ad_group.status = 'ENABLED' " +
    "AND ad_group_criterion.status = 'ENABLED' " +
    "AND segments.date BETWEEN '" + daysAgo(LOOKBACK_DAYS) + "' AND '" + daysAgo(1) + "' " +
    "AND metrics.conversions = 0 " +
    "AND metrics.clicks >= " + MIN_CLICKS + " " +
    "AND metrics.cost_micros >= " + Math.round(SPEND_THRESHOLD * 1000000) + " " +
    "ORDER BY metrics.cost_micros DESC";

  var found = [];
  var rows = AdsApp.search(query);
  while (rows.hasNext()) {
    var row = rows.next();
    found.push({
      resourceName: row.adGroupCriterion.resourceName,
      text: row.adGroupCriterion.keyword.text,
      campaign: row.campaign.name,
      cost: row.metrics.costMicros / 1000000,
      clicks: Number(row.metrics.clicks),
    });
  }
  return found;
}

function pauseAndLabel(batch) {
  var label = getOrCreateLabel(PAUSED_LABEL);
  var operations = [];
  batch.forEach(function (k) {
    operations.push({
      adGroupCriterionOperation: {
        update: { resourceName: k.resourceName, status: "PAUSED" },
        updateMask: "status",
      },
    });
    operations.push({
      adGroupCriterionLabelOperation: {
        create: { adGroupCriterion: k.resourceName, label: label },
      },
    });
  });

  var failed = AdsApp.mutateAll(operations).filter(function (result) {
    return !result.isSuccessful();
  });
  if (failed.length === 0) return "";
  return failed.length + " of " + operations.length + " operations failed: " +
    failed[0].getErrorMessages().join(", ");
}

function getOrCreateLabel(name) {
  var rows = AdsApp.search(
    "SELECT label.resource_name FROM label WHERE label.name = '" + name + "'");
  if (rows.hasNext()) return rows.next().label.resourceName;

  var result = AdsApp.mutate({ labelOperation: { create: { name: name } } });
  if (!result.isSuccessful()) {
    throw new Error("Could not create label: " + result.getErrorMessages().join(", "));
  }
  return result.getResourceName();
}

function sendSummary(batch, totalMatches, dryRun) {
  if (!EMAIL_RECIPIENTS || batch.length === 0) return;
  // Email is NOT sandboxed in Preview, so the subject says what really happened
  var subject = (dryRun ? "[DRY RUN] " : "") + batch.length + " zero-conversion keywords " +
    (dryRun ? "would be paused" : "paused") + " in " + AdsApp.currentAccount().getName();
  var lines = batch.map(function (k) {
    return k.text + " | " + k.campaign + " | cost " + k.cost.toFixed(2) + " | clicks " + k.clicks;
  });
  if (totalMatches > batch.length) {
    lines.push("", (totalMatches - batch.length) + " more matched but were held back by MAX_PAUSES_PER_RUN.");
  }
  MailApp.sendEmail(EMAIL_RECIPIENTS, subject, lines.join("\n"));
}

function daysAgo(days) {
  var date = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
  return Utilities.formatDate(date, AdsApp.currentAccount().getTimeZone(), "yyyy-MM-dd");
}

How to review a script you did not write

You do not need to read JavaScript fluently to review this. You need to find the answers to six questions:

  • Are all the numbers at the top? Every value from the brief is a named setting. If a threshold is hiding inside the logic, ask for it to be moved.
  • What switches the changes on? Here there are two independent locks: the script stays in dry-run mode if DRY_RUN is true or if it is running in Preview.
  • What is the most one run can change? MAX_PAUSES_PER_RUN limits the batch before anything happens, and the log says how many matched versus how many were acted on.
  • How do I undo it? The label. Filter keywords by it in Google Ads and re-enable them in one bulk edit.
  • What data window does it judge on? The last 30 days ending yesterday, so a half-finished today does not skew the numbers.
  • What happens when something fails? There is no catch-all try/catch hiding errors. If the query breaks, the run fails visibly. If some changes are rejected, the script still sends its summary and then throws, so the run is marked as failed.

If you cannot find an answer, ask the assistant: “list every change this script can make to the account, and the most it can change in a single run.” A good script makes that answer short.

Testing: Preview Is Only the First Stage

Most guides stop at “always click Preview”. Preview is necessary and not sufficient. Use four stages, each catching a different kind of problem:

StageWhat it catchesWhat it misses
1. Query checkWrong rule, invalid GAQL fields, thresholds that do not fit the accountAnything about the write path
2. PreviewRuntime errors, authorization problems, the exact list the script would act onSchedules, other accounts, behaviour over time
3. Scheduled dry runs for a few daysTimeouts, day-to-day drift in what gets selected, noisy emailsWhether the real changes are accepted
4. Live on one pilot accountRejected changes, policy errors, real-world side effectsAccount-specific surprises elsewhere

What Preview does not protect

Preview sandboxes changes to the Google Ads account and nothing else. In Preview mode a script still sends real emails, writes to real Google Sheets, creates real Drive files and calls real URLs. A script that logs its changes to a sheet will happily record changes that never happened; one that posts to Slack will announce them.

A well-built script therefore asks Google which mode it is in and adjusts its side effects too:

var isPreview = AdsApp.getExecutionInfo().isPreview();

In the example above, the email subject is prefixed with [DRY RUN] so nobody mistakes a rehearsal for the real thing. For any script that writes outside Google Ads, ask the assistant directly: “what does this script do differently in Preview, and what does it still do for real?”

Dry runs on a schedule, then one account

Preview is a single run that you watch. Real scripts run unattended, on different days, against data that changes. So schedule the script with DRY_RUN still true and let it run for three or four days. Read the logs each time: did it finish, how long did it take, is the list it selects stable or does it jump around?

When the dry runs are boring, go live on exactly one account. Review what it labelled after a week. Then widen it, account by account.

chiliad tip: in chiliad the script’s settings are stored per account, so the pilot is a settings change rather than a second copy of the code: set DRY_RUN to false for one account and leave the rest in dry run. Run history for every account is in one place, and Claude can read it for you β€” “summarize the last week of runs, anything failing or slow?”

Scheduling and Limits

Run a script as often as its data changes and no more. Running a weekly analysis every hour does not make it better, it just burns the run time and floods your inbox.

FrequencyUse forWhy
HourlyBudget caps, spend spikes, landing page and site checksEvery hour of delay costs money
DailyDisapprovals, pacing reports, search term review, anomaly checksYesterday’s data is complete; today’s is not
WeeklyN-gram analysis, Quality Score, link audits, cleanup rules like the pauser aboveThe data needs time to accumulate before a decision means anything

Hourly is the floor: Google Ads cannot schedule a script more often, and a run starts at some point within its hour rather than on the minute. The other limits worth knowing before you design a script, from Google’s documentation:

LimitValueWhat it means in practice
Run time30 minutesThe script is cut off, possibly with half its changes applied
Manager script with parallel execution and a callback60 minutesEach account still gets 30 minutes of its own
Accounts per parallel run50Larger manager accounts need batching across runs
Rows from one iterator50,000 by defaultFilter in the query; do not page through an entire large account
IDs in one selector10,000Split long ID lists into chunks
Log output100 KBLog summaries, not every row; long logs are truncated
Authorized scripts per account250Rarely a problem, but a reason not to keep dead scripts around

The 30-minute limit is the one that bites. A script that takes 4 minutes on a small account can take 40 on a large one, and it will pass every test on the small one. When you brief a script for a big account, say so, and ask how it behaves if it is stopped halfway.

Control: What Happens After Launch

Testing answers “does it work today?”. Control answers “what happens when it stops working in three months, on an account I am not looking at?”. These are the layers, and what each one is for:

ControlProtects againstHow to get it
Minimum-data thresholdsDecisions made on noiseSettings in the script
Per-run cap on changesA wrong rule doing unlimited damageSettings in the script
Maximum change sizeA bid or budget moving too far in one stepA percentage limit, such as 20% per run
Labels on everything changedNot knowing what the script didThe script applies them
Before and after valuesNot being able to restore the old stateSummary email or a log sheet
Failure alertsA script that silently stopped workingAlert-and-rethrow pattern below
Version historyA bad edit with no way backKeep every version outside Google Ads
Explicit account listA manager script running on clients it was never meant forSelect accounts by ID or label, never “all”

If all of that fails, Google Ads keeps a Change history for the account, which records what a script changed and lets you undo some of it. Treat it as the last resort, not the plan: finding one script’s changes among everything else in a busy account is slow, which is exactly why the label and the log exist.

Make failures loud

A broken script looks exactly like a quiet one. Failures are easy to miss: they sit in each account’s script history until somebody looks. A script that has been failing since a campaign was renamed in June protects nothing, and you find out when the client does.

The simplest fix is to alert and rethrow. Rename your real entry point to run() and wrap it:

function main() {
  try {
    run();
  } catch (e) {
    MailApp.sendEmail(ALERT_EMAIL,
      "Script failed: " + AdsApp.currentAccount().getName(), e.message);
    throw e; // keep the run marked as failed
  }
}

The throw e matters. Without it the error is swallowed and the script history shows a successful run β€” the worst outcome, because now even someone who looks sees nothing wrong.

Scripts break quietly over time

A script that worked at launch stops working for reasons that have nothing to do with its code:

  • The person who authorized it leaves. A script runs with the access of the user who authorized it. When that user is removed from the account, the script stops.
  • The account changes under it. Campaigns are renamed, labels deleted, a spreadsheet moved or unshared.
  • The account grows. More campaigns and keywords push a comfortable run past 30 minutes.
  • Google changes the API. Fields are renamed or retired, and a query that ran for two years starts returning an error.

Put a monthly check in the calendar: open the script history, confirm each script ran recently and successfully, and delete the ones nobody needs. Five minutes, and it catches all four.

Keep every version

Saving over a working script in the Google Ads editor destroys the old one. Before any edit β€” yours or an AI’s β€” keep the previous code somewhere: a git repository, a dated document, anything. When you ask an AI to change a script, ask for the change as a diff and an explanation, not just a new file to paste over the old one.

Manager accounts multiply everything

A manager (MCC) script can run the same logic across client accounts with AdsManagerApp.accounts().executeInParallel(), 50 accounts per run. That is efficient, and it also means one wrong line affects every client at once. Two habits prevent most of the damage: select accounts explicitly by ID or label instead of taking all of them, and keep per-account thresholds in a settings object or sheet rather than forcing one number onto very different accounts.

chiliad tip: this section is the part chiliad automates. You paste a small loader into Google Ads once; the script itself lives in chiliad with full version history and one-click rollback. On a manager account the loader runs only on the accounts you assigned the script to, each with its own settings. Every run reports back, and failures alert you by email or Slack. With the Claude connector, a fix is a conversation: Claude reads the real error, proposes a change, and the corrected version runs on every account next time β€” nothing to re-paste.

What to Keep in Mind

The mistakes below are the ones that survive a successful Preview. They apply to any script, AI-written or not.

  • Plausible is not correct. AI-written code can use fields, metrics or methods that do not exist, or that Google retired years ago. Run it against a real account before you trust it.
  • Thresholds are in the account’s currency. 50 means something different in EUR, UAH and JPY. Across a mixed book of accounts, set thresholds per account.
  • Conversion lag is real. A keyword with zero conversions in the last 7 days may simply not have had its conversions reported yet. With a long sales cycle, use a longer window or exclude the most recent days.
  • Scripts and Smart Bidding can fight. A script that changes bids on campaigns using Target CPA or Target ROAS is either ignored or actively disruptive. Say which bidding strategies are in play.
  • The same run may happen twice. Schedules overlap and people click Run. A script should produce the same result if it runs again: check whether the negative exists before adding it.
  • New campaigns are not like old ones, and December is not like March. A rule tuned on mature campaigns in a normal month will misjudge a launch or a peak season. Exclude anything younger than your data window, and switch change-making scripts to dry run around major promotions.
  • You own the outcome. The AI writes the script and Google runs it, but the account is yours or your client’s. Understand the rule, read what changed, and keep the off switch within reach.

Prompts Worth Saving

WhenAsk the AI
Before writingList your assumptions about my account before you write any code.
Checking the ruleGive me a read-only version that only logs what this rule would match.
Adapting a scriptHere is a script I use. Explain what it does, then change only [this] and show me the diff.
Reviewing codeList every change this script can make, and the most it can change in one run.
Before PreviewWhat does this script do for real even in Preview mode?
Before going liveWhat happens if this script is stopped halfway, or runs twice in a row?
On failureHere is the error from the log. Explain the cause and propose a fix before changing anything.

FAQ

Do I need to know JavaScript to use Google Ads scripts in 2026?

Not to get one written. You do need to be able to state the rule precisely and to review the result β€” the six questions in the review section are enough for most scripts. Reading code gets easier quickly once you have reviewed a few.

Are AI-written scripts safe to run?

As safe as the brief and the testing behind them. The risk is rarely that the code crashes; it is that the script does exactly what was asked on an account where that was the wrong thing to ask. A dry-run default, a per-run cap and a pilot account cover most of it.

Can a script break my account?

A script can only do what the authorizing user could do by hand, but it can do it to thousands of entities in seconds. Reports and alerts cannot change anything. For scripts that do, use the controls above, and remember that Change history can reverse some changes after the fact.

How often should a script run?

As often as its data changes: hourly for spend and site checks, daily for monitoring, weekly for analysis and cleanup. See scheduling and limits.

Do scripts work with Performance Max?

Yes. Through GAQL a script can report on asset groups, placements and search term categories, which is more than the interface shows by default. Through mutate it can also create and change Performance Max campaigns and assets β€” that is how our PMax Bulk Builder works. What no script can do is see or steer how Google allocates spend inside the campaign.

What is the difference between an account script and a manager script?

An account script runs inside one Google Ads account. A manager (MCC) script runs once and works across client accounts, which saves maintaining a copy per client but multiplies the effect of any mistake. Start in a single account, and move to the manager level once the script is proven.

Where to Go from Here

Take one rule you already apply by hand every week, find its rung on the ladder, write the brief, and walk it through the stages above. The first script takes an afternoon, mostly spent on checking and testing rather than writing. That is the right proportion.

You also do not have to start from zero. The chiliad marketplace has 130+ scripts to install or to use as a starting point for your own. And when you are running scripts across more than a handful of accounts, chiliad handles the control layer β€” versions, per-account settings, monitoring and alerts β€” with a Claude connector for building and fixing scripts in conversation.

In 2026 anyone can get a script written. The scripts worth having are the ones somebody tested, limited and kept watching.

Ready to Automate Your Google Ads?

Install scripts with one click and manage them across all your accounts from a single dashboard.

πŸ€–chiliad

The platform for managing and automating Google Ads scripts at scale. Built for PPC agencies and freelancers.

chiliad β€” Google Ads Script Management - Monitor and manage Google Ads scripts across every account | Product Hunt

Product

  • Use Cases
  • Features
  • Claude connector
  • Pricing
  • Marketplace
  • Blog
  • About
  • Roadmap
  • Changelog

Support

  • Contact Us
  • Help Center
  • Terms of Service
  • Privacy Policy

Β© 2026 chiliad. All rights reserved.