API Reference › Google Ads › explain_performance_anomaly
explain_performance_anomaly
Google Ads
Read
Explain why a performance metric changed using statistical analysis and historical context
Endpoint
POST https://api.adspirer.ai/api/v1/tools/explain_performance_anomaly/execute
Headers
Authorization: Bearer sk_live_... — your Adspirer API key (required)
Content-Type: application/json (required)
Idempotency-Key: <uuid> — recommended for write operations to make retries safe
Description
Explain why a performance metric changed using statistical analysis and historical context.
⚠️ IMPORTANT: This tool retrieves READ-ONLY data. Safe to call multiple times. Uses statistical analysis only (no ML models).
🎯 **What This Tool Does (Performance Agent - Phase 1 Feature 4):**
- Explains why metrics changed (ROAS, CTR, CPC, conversions, conversion rate)
- Compares current period to historical averages (30/60/90-day)
- Identifies contributing factors with severity levels
- Detects campaign changes (paused, new, budget changes)
- Finds similar historical periods (seasonality detection)
- Provides actionable recommendations to address issues
**Returns comprehensive anomaly explanation:**
- Current metric value vs historical averages
- Deviation percentages (how much it changed)
- Contributing factors:
- CPC changes (>15% = auction competition shifts)
- Conversion rate changes (>10% = landing page/seasonality issues)
- Campaign changes (paused high-performers, new campaigns, budget changes)
- Day-of-week patterns (weekend vs weekday effects)
- Similar historical periods for context
- Assessment (normal variation vs requires action)
- Specific recommendations to fix the issue
🔍 **How Anomaly Detection Works:**
**Historical Comparison:**
- Compares current period to 30/60/90-day averages
- ±15% deviation considered "normal variation"
- >15% deviation flagged as requiring attention
**Contributing Factor Detection:**
1. **CPC Changes** (>15% threshold)
- Increased CPC = auction competition increased
- Decreased CPC = auction competition decreased or bid adjustments
2. **Conversion Rate Changes** (>10% threshold)
- Decreased = landing page issues, seasonality, audience quality
- Increased = landing page improved, better targeting
3. **Campaign Changes:**
- Paused high-performers (ROAS > 3.0x) = lost revenue driver
- New campaigns (>$1K spend) = learning phase affecting overall performance
- Budget changes (>20%) = delivery and auction participation affected
4. **Day-of-Week Patterns:**
- Weekend-heavy periods often show different performance
- Normal for B2C (higher weekend conversion)
- Normal for B2B (lower weekend conversion)
5. **Seasonality Detection:**
- Finds similar historical periods (±10% metric value)
- Helps identify if drop is seasonal vs real issue
**Parameters:**
- metric: 'roas', 'ctr', 'cpc', 'conversions', 'conversion_rate' (REQUIRED)
- period_start: Start date in YYYY-MM-DD format (REQUIRED)
- period_end: End date in YYYY-MM-DD format (REQUIRED, max 30 days period)
- customer_id: Optional (uses connected account if omitted)
**Execution time:** 2-4 seconds (statistical analysis + database queries)
**Data source:** campaign_daily_metrics table (updated nightly, 120-day retention)
**Analysis method:** Statistical comparison (no ML models)
**Trigger:** Reactive (user asks "why?"), not proactive alerts
**Use this tool when:**
- User asks "why did my ROAS drop?"
- User asks "why did my CTR increase?"
- User notices unexpected metric changes
- User wants to understand performance fluctuations
- After seeing performance changes in dashboards
Request body
All tool arguments are wrapped in an arguments object.
| Field | Type | Description |
metric | string required | Metric to explain: 'roas' (Return on Ad Spend), 'ctr' (Click-Through Rate), 'cpc' (Cost Per Click), 'conversions', or 'conversion_rate' |
period_start | string required | Start date of the anomaly period (ISO format: YYYY-MM-DD, e.g., '2025-01-15') |
period_end | string required | End date of the anomaly period (ISO format: YYYY-MM-DD, e.g., '2025-01-21'). Maximum 30 days between start and end. |
customer_id | string optional | Google Ads customer ID. Required for multi-account users. Get from get_connections_status. |
raw_data | boolean optional | If true, return ONLY raw metrics as a JSON code block (no severity labels, suggested bids/budgets, industry benchmarks, or optimization recommendations). Use when you run your own attribution model or want to minimize token usage. default: false |
Example request
{
"arguments": {
"metric": "string",
"period_start": "string",
"period_end": "string",
"customer_id": "string",
"raw_data": false
}
}
Example responses
200 — Success
{
"success": true,
"data": {
"text": "(tool-specific textual output for explain_performance_anomaly)",
"quota": {
"used": 42,
"limit": 150,
"tier": "plus",
"period_end": "2026-05-01"
}
},
"tool": "explain_performance_anomaly"
}
400 — Tool-level error (bad arguments / multi-account selection)
{
"success": false,
"error": "You have 25 meta_ads accounts connected. Please specify which account to use by passing the ad_account_id parameter:\n - Acme Holdings (ad_account_id=\"act_123456789\")\n - Acme EU (ad_account_id=\"act_987654321\")",
"is_error": true,
"tool": "explain_performance_anomaly"
}
402 — Quota exhausted
{
"success": false,
"error": "\ud83d\udea8 Monthly limit reached (150/150 tool calls on Plus tier).\nUpgrade to Pro at https://adspirer.ai to keep building.",
"is_error": true,
"tool": "explain_performance_anomaly",
"quota": {
"used": 150,
"limit": 150,
"tier": "plus",
"period_end": "2026-05-01",
"upgrade_url": "https://adspirer.ai"
}
}
Try it live
Adspirer REST API — get an API key at adspirer.ai/keys ·
adspirer.ai