Feature

Google Sheets custom metrics for Meta Ads rules

Updated 20 August 2026

A custom metric in AdOps points at one Google Sheet — a spreadsheet ID, a sheet name, a lookup column and a value column — so a rule can test a live Meta Ads number against a figure a person maintains by hand, such as a target ROAS, a stock level or a margin.

A named metric bound to a Google Sheet, resolved at evaluation time, usable in conditions, budget values and campaign names.

In numbers

The figures behind this feature

Data source
Google Sheets The only custom metric source type offered in the builder
Fields per metric
4 Spreadsheet ID, sheet name, column ID, value column
In-memory cache window
2 minutes Measured from the last access, keyed by spreadsheet ID and sheet name
Fetch order
3 layers CSV export first, Google Sheets API next, MongoDB mirror last
CSV download timeout
30 seconds Applied to the direct CSV export request
Parallel sheet reads
3 per chunk Batch fetches run three spreadsheets at a time
The AdOps custom metric editor mapping a Google Spreadsheet: a spreadsheet id, a sheet name, a column to match campaigns on and a column holding the values. Sample data
Point AdOps at a sheet, name the matching column and the value column, and your own number joins the metric list. Read the details

AdOps custom metrics let a rule compare Meta’s numbers against yours. A custom metric names a Google spreadsheet ID, a sheet name, a lookup column and a value column, and AdOps resolves it at evaluation time by finding the row whose lookup column matches the campaign and reading its value column. The result behaves like any other metric.

Why put a number in a spreadsheet at all?

Because some of the numbers that should govern a campaign never appear in Ads Manager. Margin after cost of goods. Stock on hand. A target ROAS that differs by SKU because the gross margin differs by SKU. A media buyer who maintains those figures already maintains them in a sheet.

The alternative is hardcoding a threshold into every rule and re-editing every rule when the number changes. A custom metric moves that number out of the rule and into the sheet, where the person who owns it can change it without touching automation.

What does a custom metric look like?

Creating one takes a name, an optional description, and four binding fields.

FieldExampleWhat it is
Google Spreadsheet IDthe id in the sheet URLWhich spreadsheet to open
Sheet NameSheet1Which tab inside it
Column IDDateThe lookup column matched against the campaign
Value ColumnRevenueThe column whose number is returned

The builder places the hint that the spreadsheet ID is found in the spreadsheet URL, and the data source type select currently offers Google Sheets. When you save, AdOps opens the sheet and confirms that both named columns exist. If either is missing you get a red Google Sheets Validation Failed modal listing every problem and a how-to-fix checklist, rather than a rule that silently evaluates against nothing at 3 a.m.

The worked example: a target ROAS per SKU

Keep a sheet your buyer owns. One row per campaign, keyed by campaign ID in the lookup column, with the target ROAS for the SKU that campaign sells in the value column.

Then write one rule for the whole account. Set a condition on Purchase ROAS over Last 7 days, switch its compare mode to metric, and point the compared side at the custom metric. The threshold is no longer a number you typed. It is whatever the buyer put in the sheet this morning, per campaign.

Pair it with a Pause action and a name tag, and one rule now enforces per-SKU economics across an account where every SKU has a different break-even. When the merchandising team drops a price, they edit a cell, and the automation follows.

The same metric can drive a budget change directly. A budget action’s value type accepts custom_metric, so the amount written to Meta can come from a column that already holds the number your finance team agreed to.

How does AdOps read the sheet without hammering Google?

Three layers, in order.

  1. CSV export. AdOps hits Google’s direct CSV export endpoint with a 30-second timeout and parses it with a quote-aware parser. That parser tracks quoting state, handles commas inside quoted cells and escaped doubled quotes, trims header names, skips blank lines, and drops any row whose column count does not match the header. Real back-office sheets contain currency, addresses and product names with commas in them, and a naive comma split shifts every value one column left.
  2. Google Sheets API. Permission and not-found errors are surfaced immediately rather than retried; other failures fall through to the slower API download.
  3. MongoDB mirror. Every successful fetch is written to a google_sheets collection. If Google is unreachable entirely, the engine serves the last known rows from that mirror.

On top of that sits an in-memory cache keyed by spreadsheet and sheet name. A hit within 2 minutes of the last access is served from memory, so hundreds of campaigns in one batch share a single spreadsheet read. Batch fetches run 3 sheets in parallel per chunk.

Be aware of what that cache window actually means. The 2 minutes is measured from the last access, not from the last fetch. Under continuous access, which is exactly the large-batch case, the same snapshot can be served for longer than 2 minutes. Edit the sheet before a run, not in the middle of one, and treat the value as the number your team last agreed rather than a live feed.

Capabilities

What this feature does, item by item.

Each line is a behaviour you can reproduce in the product today.

Four fields, one number
A custom metric names a Google spreadsheet ID, a sheet name, a lookup column and a value column. AdOps finds the row whose lookup column matches the campaign and reads the value column.
Validated before you save
On save the builder reads the sheet and checks that both columns really exist. A failure opens a Google Sheets Validation Failed modal listing every problem plus a how to fix checklist.
Usable in four places
A custom metric can be the metric in a condition, the metric a condition compares against, the value driving a budget change, or a token expanded into a campaign name.
Cached in memory, mirrored in the database
Rows are held in memory for 2 minutes from last use, keyed by spreadsheet and sheet name, and every successful fetch is mirrored to MongoDB so a Google outage does not stop a run.
A CSV parser that survives real sheets
The fast path uses Google's CSV export with a quote-aware parser that handles commas inside quoted cells and drops rows whose column count does not match the header.
A column in a Google Sheet becomes a condition you can rule on. Map it once and the builder treats it like any Meta metric. No sound. 7 sec No sound

Questions

Asked about this feature.

Direct answers, with the numbers attached.

What is an AdOps custom metric?

An AdOps custom metric is a named number that AdOps reads out of a Google Sheet at evaluation time. The metric stores a spreadsheet ID, a sheet name, a lookup column and a value column, and AdOps returns the value column of the row whose lookup column matches the campaign being evaluated.

Where can a custom metric be used in AdOps?

A custom metric can be used in four places: as the metric in a rule condition, as the metric a condition compares against, as the value type driving an increase, decrease or set budget action, and as a token expanded into a campaign name.

What happens if Google Sheets is unreachable?

AdOps tries Google's direct CSV export first and falls back to the Google Sheets API. If both fail, it serves the last successful copy of the rows from its own MongoDB mirror, so a spreadsheet-driven rule keeps evaluating rather than silently skipping.

How fresh is the spreadsheet data a rule sees?

AdOps holds a sheet's rows in memory for 2 minutes measured from the last time they were used, so a sheet read continuously across a large batch can be served from the same snapshot for longer than 2 minutes. Edit the sheet before the run, not during it.

Does AdOps validate my sheet before saving a custom metric?

Yes. When you save a custom metric, AdOps reads the spreadsheet and confirms that both the lookup column and the value column exist. If either is missing, it opens a Google Sheets Validation Failed modal listing each problem alongside a how to fix checklist.

Write this rule against your own account.

Every feature on this page is available on every plan. Connect one ad account, copy a template, and read the log after the first run.

Contact us See pricing

14 days free · no card · billed in Rupiah

Inside the product

What the screens actually look like

Nine screens from the working dashboard — the rule builder, the metric picker, the dayparting grid and the log that records what happened. Scroll the strip.

  • The AdOps Performance Dashboard showing a Purchase ROAS card at 2.380x and an Aggregated ROAS card at 2.088x, both badged Profitable, a Monthly Budget card at Rp 155jt, and a Spend Breakdown ranking the top five ad accounts against a budget utilisation bar at 45.5 per cent.
    Performance Dashboard. Two ROAS figures to three decimals, a budget meter, and spend ranked by ad account — over Today, Last 7 days, Last 30 days or This month.
  • The AdOps rule list showing twelve automation rules, each with an on/off toggle, the ad accounts it manages, and when it last triggered — some minutes ago, others on a dated timestamp.
    Rule List. Every rule, what it manages and when it last fired. The toggle is the only thing between draft and live.
  • The AdOps condition builder showing a task with time-of-day conditions across seven day tags, a nested AND group holding a lifetime spend condition under 400,000, and a second task with four stacked metric conditions.
    Conditions. Metric, period, operator, value — joined with AND or OR, and nestable, so a rule can say something a dropdown cannot.
  • The AdOps metric picker open over a condition row: a panel with Meta Ads and Custom metrics tabs, a search box, and a scrolling list of metrics with Spend selected.
    Metric picker. Forty-five Meta metrics and your own sheet columns in the same list, each carrying a reporting period and any of six operators.
  • The AdOps dayparting timetable: a grid of hours against the seven days of the week, with the daytime hours filled navy for every day and the night hours and weekend evenings left empty.
    Dayparting grid. Or draw the hours instead. Anything outside the shape you fill in simply does not run.
  • An AdOps execution log detail: one campaign, two action panels badged Not Executed, each listing the action parameters and every condition evaluated with its actual value, its expected value and a Pass or Fail badge.
    Rule Log detail. Why a rule did nothing is recorded as carefully as why it did something — actual against expected, condition by condition.
  • The AdOps activity log listing budget increases and campaign renames, each row naming the affected campaign by id, the rule that caused it and how long ago it happened.
    Activity Log. One row per change AdOps made in your account, naming the campaign and the rule responsible.
  • The AdOps ad account list: eighteen Meta ad accounts with on/off toggles, account ids, Active or Inactive badges and this month’s spend in rupiah.
    Ad Accounts. Accounts discovered from Meta arrive switched off. Nothing is read, and nothing is changed, until you turn one on.
  • The AdOps custom metric editor mapping a Google Spreadsheet: a spreadsheet id, a sheet name, a column to match campaigns on and a column holding the values.
    Custom metric. Point AdOps at a sheet, name the matching column and the value column, and your own number joins the metric list.

Every figure is rebuilt from the product’s own interface and filled with invented data — no customer name, ad account or spend figure appears anywhere on this site. See how a run works