Back to Case Study

User Stories & Acceptance Criteria

Status Draft v1.0
Owner Product
Series
Ad Copilot Portfolio Doc

Stories are grouped by epic, mapped to PRD Functional Requirements (FR-#), with Gherkin-style acceptance criteria. Points are rough t-shirt-to-Fibonacci estimates for planning illustration.

Epic 1: Account Connection & Setup

US-1 — Connect ad account

As a performance marketer, I want to connect my Meta Ads account via OAuth so that Ad Copilot can read my campaign data.

  • Given I am on the onboarding screen, when I click “Connect Meta Ads,” then I am redirected to Meta’s OAuth consent screen.
  • Given I grant permission, when I return to Ad Copilot, then my last 90 days of campaign, ad set, and ad-level performance data begins syncing.
  • Given the sync is in progress, when I view the dashboard, then I see a sync-status indicator rather than an empty or misleading state.
  • Given I deny permission or the OAuth flow fails, when I return to Ad Copilot, then I see a clear error message and a retry option.

US-2 — Set performance targets per campaign

As a performance marketer, I want to set a target ROAS or CPA per campaign so that the system knows when performance has drifted.

  • Given I’ve connected an account, when I open a campaign’s settings, then I can input a target ROAS or target CPA (not both).
  • Given no target is set, when drift monitoring runs, then that campaign is excluded from recommendations and marked “no target set.”

Epic 2: Creative Generation

US-3 — Generate ad copy variants on demand

As a performance marketer, I want to generate new ad copy variants for a specific ad set so that I can replace fatiguing creative quickly.

  • Given I select an ad set and click “Generate variants,” when generation completes, then I see 3–5 headline/primary-text/CTA combinations.
  • Given variants are generated, when I view them, then each displays a confidence score.
  • Given the product feed is missing required fields, when I attempt generation, then I receive a specific error naming the missing field.

US-4 — Scheduled creative refresh

As a performance marketer, I want to schedule automatic variant generation for ad sets that show fatigue signals so that I don’t have to manually monitor for decay.

  • Given I enable “auto-refresh” on an ad set, when fatigue is detected (e.g. CTR decline), then new variants are generated into the review queue.
  • Given auto-refresh is enabled, when no fatigue signal occurs, then no unnecessary generation calls are made.

US-5 — Brand-safety filtering on generated copy

As a brand/compliance stakeholder, I want to screen generated ad copy against a wordlist so that non-compliant or off-brand copy never reaches a reviewer.

  • Given a generated variant contains a blocked term, when generation completes, then that variant is suppressed and never appears in the review queue.
  • Given a variant is suppressed, when an admin views generation logs, then the suppressed variant and matched term are visible for audit.

Epic 3: Monitoring & Recommendations

US-6 — Detect performance drift

As a system, I want to compare live performance against campaign targets hourly so that drift is caught before days of wasted spend.

  • Given a campaign has a target CPA, when actual CPA exceeds target by more than the configured threshold for the configured duration, then a recommendation is generated.
  • Given the ad platform API is rate-limited or returns stale data, when the sync job runs, then the system retries with backoff and flags data as stale rather than acting on incomplete data.

US-7 — Receive a budget/bid recommendation with reasoning

As a performance marketer, I want to see why a recommendation was made so that I can evaluate it instead of blindly trusting or distrusting it.

  • Given a recommendation is generated, when I open it, then I see the triggering metric, current vs target value, and proposed action.
  • Given a recommendation is generated, when I open it, then I see a confidence score and plain-language explanation — not just raw model output.

Epic 4: Review Lanes & Human-in-the-Loop

US-8 — Lane assignment for AI actions

As a system, I want to classify every AI action into Auto-apply, Suggest, or Escalate so that risk is proportional to autonomy.

  • Given confidence score and blast radius are calculated, when lane assignment runs, then the action is placed in exactly one lane.
  • Given an account is new (below data-volume threshold), when any action is generated, then it is placed in Suggest or Escalate — never Auto-apply.

US-9 — Review and act on a queued recommendation

As a performance marketer, I want to approve, reject, or edit a queued recommendation so that I retain control over budget-impacting actions.

  • Given a Suggest-lane item, when I click Approve, then the action executes against the ad platform API and is logged.
  • Given a Suggest-lane item, when I click Edit, then I can modify the proposed value before approving.
  • Given I reject a recommendation, when I do so, then I can optionally provide a reason stored to improve future scoring.

US-10 — Audit log and rollback

As a performance marketer, I want to see a full history of AI actions and roll them back so that I never lose visibility or control.

  • Given any AI action has been taken, when I view the audit log, then I see action, timestamp, lane, confidence, and status.
  • Given an Auto-apply action was taken within the last 5 minutes, when I click Rollback, then the prior budget/bid is restored and logged.

US-11 — Configure lane thresholds per account

As a admin user, I want to adjust confidence/blast-radius thresholds so that the system’s risk tolerance matches our account’s needs.

  • Given I am an admin, when I raise the Auto-apply confidence threshold, then fewer actions qualify going forward.
  • Given I attempt a threshold that allows unbounded budget risk, when I save, then the system blocks the change and explains why.

Epic 5: Cost Controls

US-12 — Enforce monthly generation caps

As a business, I want to cap LLM generation calls per account per month so that AI cost doesn’t scale unpredictably against plan tier.

  • Given an account has reached its monthly cap, when further generation is attempted, then the request is blocked with a clear message and upgrade option.
  • Given an account crosses 80% of its cap, when this threshold is crossed, then the account owner receives a proactive notification.

US-13 — Tiered model routing

As a system, I want to use a lower-cost model for first-pass and reserve the higher-cost model for top candidates so that generation cost stays proportionate.

  • Given a generation request produces an initial candidate set, when top-N are selected, then only those N are refined with the higher-cost model.
  • Given refinement fails or times out, when this occurs, then first-pass candidates are still surfaced rather than failing silently.

US-14 — Cache reuse for unchanged inputs

As a system, I want to reuse prior generation outputs when product-feed input hasn’t changed so that we avoid redundant model calls.

  • Given a product feed entry is unchanged within the caching window, when a new generation request is made, then cached outputs are served.
  • Given cached outputs are served, when the user views them, then they carry no “stale” stigma in the UI.

Backlog summary

EpicStoriesP0Points
Account Connection & Setup228
Creative Generation3218
Monitoring & Recommendations2213
Review Lanes & HITL4321
Cost Controls3218

Suggested MVP cut: all P0 stories (13 stories, ~72 points), deferring US-4, US-11, and US-14 (P1) to Phase 2.