Rule scope — which campaigns and ad sets it targets

Last updated: May 19, 2026

Rule scope — which campaigns and ad sets it targets

Two layers control which entities a rule evaluates: 1) ad_account_ids[] — which accounts the rule scans, and 2) entity_filter — narrow further by name pattern + status. The entity level (campaign / adset / ad) determines granularity of both evaluation and action.

Who is this for

Anyone building a rule that should target a specific slice of accounts (one client, one product line, one geo) instead of everything.

Why scope matters

A rule with no scope = global scope = every entity in every connected ad account. That's almost never what you want. Bad scope causes:

  • Rules acting on the wrong client's campaigns (esp. agency setups)

  • Test campaigns being killed by production-grade rules

  • Rules conflicting (e.g. two rules adjusting budget on same entity)

Tight scope avoids these.

Layer 1: ad accounts

Multi-select picker in the builder. Pick one or more ad accounts.

Use cases:

  • Single account — most common. One rule per client / per product / per geo.

  • Multi-account, same client — same client with separate accounts per platform or per geo

  • All accounts — risky; only for global guard rails (e.g. notify_only on > 90% daily budget)

Cross-platform rules (behind ENABLE_CROSS_PLATFORM_RULES flag) add platforms[] — which platforms within the chosen accounts to evaluate (default [meta]).

Layer 2: entity_filter

Narrow within the chosen accounts. Three sub-filters:

name_contains

Only evaluate entities whose name contains the substring.

Example: name_contains: "Prospecting" → only prospecting campaigns (assuming naming convention used).

name_not_contains

Exclude entities whose name contains the substring.

Example: name_not_contains: "TEST" → skip test campaigns.

status_in

Only evaluate entities in the listed statuses. Options: active, paused, archived. Default: [active].

Use case: rule targeting only active (most common) — paused / archived entities don't need evaluation.

Layer 3: entity level

Pick one:

  • campaign — evaluate campaign-level metrics, act on campaigns

  • adset — adset-level (more granular, most common for performance rules)

  • ad — per-ad (most granular, useful for creative rotation)

Granularity matters: campaign-level CPA averages out wins and losses inside; adset-level catches the losing audience inside a winning campaign.

How they combine

Final scope = entities matching (ad_account IN ad_account_ids) AND (entity_filter applies) AND (entity_level matches).

Example:

ad_account_ids: [act_123]
entity_filter:
  name_contains: "Prospecting"
  status_in: [active]
entity_level: adset

Result: every active ad set inside account act_123 whose name contains "Prospecting".

Naming conventions are critical

Without naming conventions, name_contains is useless. With them, scope becomes precise.

Recommended pattern: [Client]_[Campaign-Type]_[Audience]_[Geo]_[YYYYMM]_[Version]. E.g.

ClientA_SalesProspecting_LookalikePurchasers_IT_202611_v2

Rule scope variations:

  • name_contains: "ClientA" — only ClientA

  • name_contains: "SalesProspecting" — only prospecting type

  • name_contains: "_IT_" — only Italian geo

  • Multiple rules with different name_contains to handle different segments

See am-108 naming conventions.

Multi-account rules

For agency setups managing many clients on one Wevion workspace: pick all ad accounts in scope + use name_contains per-client convention (if your naming includes client prefix).

Alternative: one rule per client (duplicate + change scope). Simpler to audit + change per-client.

Cross-platform scope

If ENABLE_CROSS_PLATFORM_RULES is on: add platforms[] to limit which platforms in the chosen accounts are evaluated. Default [meta].

Useful when one ad account holds multiple platform integrations — restrict the rule to Meta only or Google only.

What you'll see in preview

POST /api/v1/rules/preview returns all entities evaluated (scope working) + per-entity match result. If scope is wrong:

  • No entities at all: scope too narrow (filter excludes everything) — check name_contains typos

  • Way too many entities: scope too broad (no filter at all) — add name_contains to narrow

  • Wrong entities: check the entity_level + status_in are what you intended

Common mistakes

  • No name_contains: rule scans every campaign — slower + risky

  • Naming convention not enforced: name_contains misses entities because copy used "PROSP" instead of "Prospecting"

  • status_in defaulting to [active]: rule never evaluates paused entities even when needed (e.g. "activate at 9am" rule needs paused in scope)

  • Multiple rules same scope + same action: conflicts. Use disjoint scopes or merge into one rule.

Related