DEV Community

Sravani Noothi
Sravani Noothi

Posted on Fully Autonomous

Meta Ads + Codex: Detect Creative Fatigue Without Automating the Wrong Fix

A Meta Ads MCP Codex workflow can find a tired creative quickly. The difficult part is proving that the creative is actually the problem.

Frequency may be rising because an audience is small. Click-through rate may be falling because placements shifted. Conversions may look weaker because the attribution setting changed. An agent that treats any one of those movements as “creative fatigue” can recommend the right-looking fix for the wrong diagnosis.

The safer implementation is a comparison pipeline: inventory the account, bind the analysis to exact windows, normalize the evidence, classify the signal, and propose a test without changing the live campaign.

Treat fatigue as a hypothesis

Creative fatigue is not a field returned by an advertising API. It is an interpretation of several observations.

A useful evidence object keeps those observations separate from the diagnosis:

{
  "account_id": "AD_ACCOUNT_ID",
  "ad_id": "AD_ID",
  "creative_id": "CREATIVE_ID",
  "current_window": "YYYY-MM-DD..YYYY-MM-DD",
  "baseline_window": "YYYY-MM-DD..YYYY-MM-DD",
  "current": {
    "impressions": 0,
    "frequency": 0,
    "ctr": 0,
    "cpm": 0,
    "spend": 0,
    "conversions": 0
  },
  "baseline": {
    "impressions": 0,
    "frequency": 0,
    "ctr": 0,
    "cpm": 0,
    "spend": 0,
    "conversions": 0
  },
  "diagnosis": "unclassified",
  "blocked_by": []
}
Enter fullscreen mode Exit fullscreen mode

The agent should populate diagnosis only after checking whether the two windows are comparable.

That means the same account, currency, attribution assumptions, campaign objective, ad status, and useful delivery volume. If one of those conditions changed, add it to blocked_by and stop the diagnosis.

Start with account and creative inventory

Before querying performance, list the accounts available to the authenticated connection. Require an explicit account ID when more than one is accessible.

Then collect the hierarchy that connects each creative to its delivery context:

account
└── campaign
    └── ad set
        └── ad
            └── creative
Enter fullscreen mode Exit fullscreen mode

Creative-level metrics without campaign and ad-set context are incomplete. A new budget, a different audience, a placement change, or a recently enabled ad can all change delivery without any edit to the creative itself.

Keep stable identifiers in the result. Names are useful for a report, but they are not reliable join keys.

Compare windows, not lifetime averages

Lifetime performance can hide the moment a creative changed direction. Use two adjacent windows with exact dates instead.

For example:

  • baseline: the previous seven complete days;
  • current: the latest seven complete days; and
  • comparison grain: one ad or one creative, not a campaign-wide average.

Do not include a partial current day unless both windows are aligned to the same hour. Make the account timezone explicit.

The comparison should return deltas, but it should not turn every delta into a verdict:

{
  "frequency_delta": 0.8,
  "ctr_delta_pct": -17.2,
  "cpm_delta_pct": 3.1,
  "conversion_delta_pct": -9.4,
  "signal": "review",
  "reason": "Frequency increased while CTR declined; conversion volume is too low for an automatic decision"
}
Enter fullscreen mode Exit fullscreen mode

This is intentionally cautious. A falling CTR paired with rising frequency is worth reviewing, but it does not prove causation. The account may need a creative refresh, a placement breakdown, an audience check, or no action at all.

Make the agent explain competing diagnoses

Before it proposes a change, require the agent to test at least three explanations:

  1. Creative fatigue: frequency rose and engagement declined for the same creative in comparable delivery conditions.
  2. Delivery-mix change: placement, audience, geography, device, or optimization mix shifted between windows.
  3. Measurement change: attribution, conversion configuration, or reporting completeness changed.

The output should state which evidence supports or weakens each explanation.

That prevents a common failure: observing a performance decline, naming the most familiar cause, and skipping the account change that actually produced it.

Produce a test proposal, not a pause command

Once the evidence is strong enough, generate a bounded proposal:

{
  "proposal": "creative_refresh_test",
  "keep_constant": [
    "audience",
    "budget",
    "optimization_goal",
    "placements"
  ],
  "change": [
    "creative_asset"
  ],
  "evaluation_window_days": 7,
  "success_metrics": [
    "ctr",
    "conversion_rate",
    "cost_per_conversion"
  ],
  "requires_confirmation": true
}
Enter fullscreen mode Exit fullscreen mode

This proposal is useful because it says what should remain constant. Without that constraint, a “creative test” can become a new audience, new budget, new placement mix, and new creative launched together. The result may improve, but the experiment will not explain why.

Do not let the diagnostic run pause the current ad, create a replacement, or change budget. Those are separate operations with separate approvals.

Applying the pattern with Codex

Codex plugins can bundle skills and connectors for a repeatable workflow. The agent still needs a narrow first prompt and a tool boundary that enforces it.

The current Adspirer Meta performance tool accepts an explicit account and date range and reports ad- and creative-level performance, including indicators based on frequency and declining CTR. Its documentation is a useful example of the inputs a diagnostic step should require.

For Codex installation, the Adspirer setup guide documents the plugin and authentication flow. After the connection is verified, a first analysis prompt can stay read-only:

Use Meta Ads read tools only.

1. List accessible ad accounts and stop if the target is ambiguous.
2. Use the exact baseline and current date ranges I provide.
3. Compare each active ad at the ad and creative level.
4. Report frequency, CTR, CPM, spend, conversions, status, and delivery context.
5. Test creative fatigue, delivery-mix change, and measurement change as competing explanations.
6. Return no more than three test proposals tied to the evidence.

Do not pause ads, change budget, edit targeting, create assets, or launch campaigns.
Enter fullscreen mode Exit fullscreen mode

Test the stop conditions

The workflow should stop when:

  • the account is ambiguous;
  • one comparison window has incomplete delivery;
  • the creative ID changed between windows;
  • campaign objective or optimization changed;
  • a placement or audience shift explains the movement;
  • attribution settings are not comparable; or
  • conversion volume is too thin for the proposed decision.

The strongest result from an ads agent is sometimes “the data does not isolate the cause.” That is more useful than an automatic fix attached to a weak diagnosis.

Creative fatigue detection should end with a controlled test plan. The live-account change comes later, after the evidence, variables, success criteria, and reversal are clear.


Affiliation disclosure: This article was prepared for Adspirer. Adspirer’s Meta Ads tooling is used as one concrete implementation example.

Top comments (0)