Preview (dry-run) — test before activating

Last updated: May 19, 2026

Preview (dry-run) — test before activating

Preview button in the rule builder + on /rules/:id. Backed by POST /api/v1/rules/preview (verified). Runs the rule's evaluation logic against current data without triggering any action. Returns the list of entities evaluated, which matched, which were skipped, and why. Mandatory step before activating a new rule.

Who is this for

Anyone building a new rule. Also: anyone changing scope / conditions of an existing rule before saving.

Why preview matters

The rule builder lets you write any combination of scope + conditions + actions. Without preview, you'd activate and only learn after the first fire whether:

  • The scope catches the right entities

  • The conditions match the entities you intended

  • Skips (cooldown, daily cap) would block expected actions

Preview surfaces all of this in seconds, with no risk.

How to preview

In the builder (new rule)

  1. Build the rule (steps 1-9 per rul-102)

  2. Before clicking Save: click Preview

  3. Modal opens with results

On existing rules

  1. Open /rules/:id

  2. Top toolbar → Preview

  3. Same modal opens

You can preview a rule in paused or active status — preview doesn't change anything.

What preview returns

POST /api/v1/rules/preview returns a JSON shape:

  • entities_evaluated — total entities scanned in scope (number)

  • entities_matched — entities passing all conditions (array with per-entity metric values + which conditions triggered)

  • entities_skipped — entities matching conditions but skipped due to a protection (array with per-entity skip reason)

  • entities_errored — entities where evaluation failed (e.g. missing metric for that platform)

In the UI, results render as a table:

Entity name

Status

Matched?

Metric values

Skip reason

Adset Prospecting US v3

active

roas=1.2, spend=120

Adset Retarget IT v2

active

roas=2.1, spend=80

conditions not met

Adset Prospecting DE v1

active

roas=1.3, spend=90

cooldown_active (until 14:30)

Reading the results

Empty entities_evaluated

Scope returns nothing. Common causes:

  • Wrong ad account selected

  • name_contains typo

  • status_in: [active] but all entities are paused

  • Entity level mismatch (entities are adsets but rule targets campaigns)

Fix: re-check scope.

Lots of entities_matched

If 50 entities match: scope or conditions too loose. Tighten one:

  • Add spend gt N guard (filter out low-volume)

  • Tighten thresholds

  • Add name_contains filter

Lots of entities_skipped

Most common reasons:

  • cooldown_active — entity acted on recently (by this rule or another)

  • daily_cap_reached — rule hit max_executions_per_day

  • pending_action_exists — in-flight action in 30-min window

  • entity_state_conflict — e.g. relaunch requires active ad; entity is paused

Often expected. Skip reasons are informational.

entities_errored

Usually missing data:

  • Metric not available on the platform (e.g. frequency on Google in some contexts)

  • Time range has no data (very new account)

  • Postback metric not yet seeded

Worked example

Building "Kill losers — CPA > 30 / 7d, adset level, ClientA only":

ad_account_ids: [act_clientA]
entity_filter: {name_contains: "ClientA", status_in: [active]}
entity_level: adset
condition_logic: AND
conditions:
  - {metric: cpa, operator: gt, value: 30, time_range: last_7d}
  - {metric: spend, operator: gt, value: 50, time_range: last_7d}
actions: [pause]
cooldown_minutes: 360
max_executions_per_day: 5

Preview returns:

  • evaluated: 42 adsets

  • matched: 4 (with CPA values 35, 38, 42, 55 + spend > 50)

  • skipped: 0

  • errored: 0

Result is reasonable. Activate.

Vs the same rule with spend gt 5 (instead of 50):

  • evaluated: 42

  • matched: 18 — including low-spend tests where CPA is misleading (1 conversion in $10 spend)

Tighten the spend guard back. Re-preview. Then activate.

Preview vs first real fire

Preview uses the current metric snapshot. Real fire uses metrics at the time of the cron tick (within 15 min of preview, in practice). Small drift is expected.

Preview does NOT consume from max_executions_per_day counter. You can preview unlimited times.

Best practice workflow

  1. Build draft

  2. Preview

  3. Adjust scope / conditions

  4. Preview again

  5. Repeat until matches make sense

  6. Save (status remains paused)

  7. Optional: temporarily change action to notify_only for first 24-48h of active status

  8. Validate notifications match expected entities

  9. Switch action back to pause / increase_budget_pct / etc.

This "preview → notify_only → real action" ramp catches both logic bugs and unexpected real-world behavior.

Common mistakes

  • Skipping preview: rule activates against wrong scope → unexpected actions on production campaigns

  • Previewing only happy path: also preview at edge times (end of week, after weekend) where metrics behave differently

  • Ignoring entities_skipped: high skip count often means rule won't act much in practice — adjust cooldown or daily cap

Related