# Rule automation

> Conditions on live Meta metrics paired with actions the engine executes on your campaigns, with an execution log behind every run.

Source: https://adops.id/features/rule-automation/
Last updated: 2026-08-20
Publisher: AdOps (https://adops.id) — an independent product, not affiliated with Meta Platforms, Inc.

---

## Key facts

- **Dispatch interval:** Every 10 seconds (Cron sweep with overlap prevention, so one tick never re-enters a sweep already running)
- **Comparison operators:** 6 (greater than, less than, greater than or equal, less than or equal, equal, not equal)
- **Targeting levels:** 2 (Campaigns and ad sets)
- **Pre-filter fields:** 3 (campaign.id, campaign.name, campaign.effective_status)
- **Queue fan-out:** 1 job per ad account (Enqueued onto a Redis-backed BullMQ queue named facebook_queue)
- **Entity fetch retries:** 3 total attempts (Waits 1 second, then 2 seconds, before skipping that ad account)

## Capabilities

### Conditions in plain arithmetic

Each condition is a metric, a reporting period, one of 6 operators, and a number. A task combines its conditions with a single AND or OR. Nothing about the logic is hidden from you.

### Two targeting levels

A rule runs at campaign level or ad set level. The level is stored on every result row, and the engine issues its Meta Insights reads at that level.

### Pre-filters before evaluation

Scope a rule by campaign ID, campaign name or campaign status before any metric is read, so a rule only ever sees the campaigns you meant it to see.

### Many tasks in one rule

A rule holds an array of tasks. Each task carries its own action, its own conditions and its own cooldown, so one rule can scale winners, pause losers and tag both.

### A dispatcher that cannot change your ads

The producer that decides which rules are due only issues GET requests to the Meta Graph API. Every write happens in the separate worker process.

AdOps automates Meta Ads through rules you write yourself. A rule pairs conditions on live campaign metrics with an action AdOps executes against Meta's Graph API. Each rule targets campaigns or ad sets, combines its conditions with AND or OR, and writes an evidence row for every campaign it evaluated, whether or not anything changed.

## What is an AdOps rule made of?

A rule carries a name, the ad accounts it covers, a level, a set of pre-filters, a schedule, and a list of tasks. The rule builder hints that you select up to 5 ad accounts per rule.

A task is the working unit. Each one holds a single action, its own condition set, and an optional cooldown. Because tasks live in an array, one rule can encode a whole playbook instead of forcing you to create three rules that fight each other. A rule sits in `DRAFT` until you set it live, and only `ACTIVE` rules are ever picked up by the dispatcher.

## How do conditions combine?

Every condition is four things: a metric, a reporting period, an operator, and a value. AdOps ships 45 Meta Ads metrics and 11 reporting periods, so `Purchase ROAS` over `Last 7 days` is one condition and `Spend` over `Today` is another.

Six operators are available on each condition.

| Operator | Symbol | Menu label |
| --- | --- | --- |
| `GREATER_THAN` | `>` | greater than |
| `LESS_THAN` | `<` | less than |
| `GREATER_THAN_EQUAL` | `>=` | greater than equal |
| `LESS_THAN_EQUAL` | `<=` | less than equal |
| `EQUAL` | `=` | equal |
| `NOT_EQUAL` | `!=` | not equal |

The conditions inside one task are combined by a single group operator, `AND` or `OR`, which you toggle by clicking it. A condition's right-hand side is normally a number, but switching its compare mode to `metric` lets you test one metric against another, each with its own reporting period.

## Which campaigns does a rule touch?

Two things decide that. First the level, which is either `campaign` or `adset`. Second the pre-filters, which run before any metric is read.

| Pre-filter field | Operators | Values |
| --- | --- | --- |
| `campaign.id` | equal, not equal | a campaign ID |
| `campaign.name` | contains, does not contain | free text |
| `campaign.effective_status` | is, is not | `ACTIVE`, `PAUSED` |

As you change the level or the filters, the builder calls the estimate endpoint after a 500 ms debounce and shows an `Estimated match: N Campaigns` readout, with a per-account breakdown on hover. You see the blast radius before the rule is live.

## What happens between the tick and the action?

The engine is split into a producer and a worker so that the part deciding what to run is not the part allowed to change anything.

1. A cron sweep fires every 10 seconds and selects every `ACTIVE` rule whose next execution time has passed and whose date window is open. The cron is configured with overlap prevention, so a slow sweep is never re-entered by the following tick.
2. The producer pulls matching entities from the Meta Graph API, 1000 per page, following Meta's own paging cursors. An ad account whose fetch fails is retried up to 3 total attempts, waiting 1 second and then 2 seconds, then skipped rather than blocking the rest.
3. One job per ad account is enqueued onto a Redis-backed BullMQ queue named `facebook_queue`.
4. The worker groups the rule's conditions by reporting period, unions the Meta Insights fields those periods need, and issues them as a single Graph batch request. Every Insights call is sent with `use_unified_attribution_setting=true`, so the numbers the rule judges are the numbers your ad set's attribution window reports.
5. Conditions are evaluated, actions are executed, and results are persisted as one `rule_result` per campaign per task plus a `rule_benchmark` roll-up for the batch.

Batch progress is reported back to the queue as a whole percentage after each campaign finishes, so a run in flight shows a real figure rather than a spinner.

## What are the honest limits?

The 10-second tick is how often AdOps looks for due work, not a promise about end-to-end latency. A sweep processes due rules one after another, and a large account with many pages of campaigns takes as long as Meta takes to answer. Treat the check interval as the floor on how often a rule can be considered, not as a service level.

The dispatcher's blast radius is worth stating plainly, because it is verifiable rather than aspirational. That process only issues GET requests to Meta and writes two scheduling timestamps to its own database. It never calls a Meta write endpoint, so a bad deploy of the dispatcher cannot alter a campaign.

## Where do you start if you do not want a blank rule?

AdOps ships 10 rule templates across 4 categories, tagged budget, status, naming or monitoring. Opening the Templates modal shows each template's task count and a preview of every action, frequency, value and condition it contains before you import it. Importing drops those tasks into the rule you are editing, where they behave like tasks you wrote by hand.
