monitor
Check Spotify Ads API campaign health — pacing, delivery issues, budget burn rate, stalled campaigns, and underpacing alerts. Use for one-shot health checks or recurring monitoring when the host supports scheduled automations.
What this skill does
# Spotify Ads API — Campaign Health Monitor
Diagnose delivery problems across active campaigns. Goes beyond the dashboard by running diagnostic checks and recommending specific actions.
## Setup
1. Read `access_token`, `ad_account_id`, and `auto_execute` from the active platform settings file:
- Codex: prefer `.codex/spotify-ads-api.local.md`, then fall back to `.claude/spotify-ads-api.local.md`.
- Claude: prefer `.claude/spotify-ads-api.local.md`, then fall back to `.codex/spotify-ads-api.local.md`.
2. Base URL: `https://api-partner.spotify.com/ads/v3`
3. If neither settings file exists, instruct the user to run `/spotify-ads-api:configure` first.
4. Read the active platform manifest for the plugin `version`: `.codex-plugin/plugin.json` on Codex or `.claude-plugin/plugin.json` on Claude.
5. Set `SDK_PRODUCT` to `codex-plugin` on Codex or `claude-code-plugin` on Claude. Set `SDK_HEADER="X-Spotify-Ads-Sdk: $SDK_PRODUCT/$PLUGIN_VERSION"` and include `-H "$SDK_HEADER"` on all API requests.
## Parsing Arguments
- No argument or `--all` → Health check all active campaigns
- `<campaign_id>` (UUID) → Deep health check on a specific campaign (includes ad set and ad level diagnostics)
- If ambiguous, ask the user.
---
## Account-Wide Health Check (default)
### API Calls
Execute these calls to gather the data needed for diagnostics:
#### 1. Active campaigns
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/campaigns?statuses=ACTIVE&limit=50&sort_direction=DESC"
```
#### 2. Active ad sets
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?statuses=ACTIVE&limit=50&sort_direction=DESC"
```
#### 3. Today's campaign metrics
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/aggregate_reports?\
entity_type=CAMPAIGN&\
fields=IMPRESSIONS&fields=SPEND&fields=REACH&fields=CLICKS&fields=CTR&fields=FREQUENCY&\
granularity=DAY&\
report_start=$(date -u +%Y-%m-%dT00:00:00Z)&\
report_end=$(date -u +%Y-%m-%dT00:00:00Z)&\
entity_status_type=CAMPAIGN&\
statuses=ACTIVE&\
limit=50"
```
#### 4. Lifetime campaign metrics (for pacing)
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/aggregate_reports?\
entity_type=CAMPAIGN&\
fields=IMPRESSIONS&fields=SPEND&fields=REACH&fields=CLICKS&\
granularity=LIFETIME&\
entity_status_type=CAMPAIGN&\
statuses=ACTIVE&\
limit=50"
```
### Health Checks
Run these diagnostics against the fetched data:
#### 1. Pacing Check
For each active campaign, compare spend progress to flight progress:
- **DAILY budgets**: Sum the daily budgets of all active ad sets under the campaign. Compare today's spend to the total daily budget.
- Display: `$142.50 / $200.00 daily (71%)`
- **LIFETIME budgets**: Compare total lifetime spend to total lifetime budget, and compare against elapsed flight percentage.
- `elapsed_pct = (today - start_date) / (end_date - start_date) * 100`
- `spend_pct = total_spend / total_budget * 100`
- Display: `$2,100 / $5,000 lifetime (42% spent, 35% of flight elapsed)`
**Alert levels:**
- **OK**: Spend % and elapsed % within 20 points of each other
- **WARNING**: 20-40 point gap between spend % and elapsed %
- **CRITICAL**: >40 point gap, OR zero spend with >24 hours elapsed since campaign start
#### 2. Stalled Delivery Check
- If an ACTIVE campaign has zero impressions today AND its start_time is more than 4 hours ago, flag as **STALLED**.
- Exclude campaigns that started within the last 4 hours (they may still be ramping up).
#### 3. Budget Exhaustion Check
For LIFETIME budgets, project when the budget will run out at the current daily burn rate:
- `daily_burn = lifetime_spend / days_elapsed`
- `days_remaining_at_pace = (budget - spend) / daily_burn`
- `projected_end = today + days_remaining_at_pace`
Flag if:
- Budget will exhaust **before** the scheduled `end_time` → "May exhaust budget early"
- Budget will be **>20% unspent** at `end_time` → "Likely to underspend"
### Display Format
```
=== Campaign Health Check ===
Checked: 3 active campaigns, 7 active ad sets
Time: 2026-05-14 14:30 UTC
| Campaign | Status | Spend Today | Pacing | Issues |
|----------|--------|-------------|--------|--------|
| Summer Promo | OK | $142.50 / $200 daily (71%) | On track | — |
| Q2 Brand | WARNING | $28.00 / $100 daily (28%) | Underpacing | 1 stalled ad set |
| Podcast Launch | CRITICAL | $0.00 / $75 daily (0%) | Stalled | No delivery today |
Issues Found (2):
1. [WARNING] Q2 Brand: Spending at 28% of daily budget with 62% of day elapsed
→ Consider increasing bid or broadening targeting. Run: /spotify-ads-api:dashboard <campaign_id>
2. [CRITICAL] Podcast Launch: Zero impressions today (campaign started 2026-05-12)
→ Campaign may have delivery issues. Check ad approval status with: /spotify-ads-api:monitor <campaign_id>
```
If no issues are found:
```
All 3 active campaigns are healthy. No issues detected.
```
---
## Deep Campaign Health Check (`<campaign_id>`)
### API Calls
#### 1. Campaign details
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/campaigns/$CAMPAIGN_ID"
```
#### 2. All ad sets under the campaign
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets?campaign_ids=$CAMPAIGN_ID&limit=50"
```
#### 3. All ads under the campaign
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ads?campaign_ids=$CAMPAIGN_ID&limit=50"
```
Extract active and paused ad set IDs from Step 2 and build repeated query parameters before fetching ad set metrics:
```bash
AD_SET_IDS_QUERY="entity_ids=<AD_SET_ID_1>&entity_ids=<AD_SET_ID_2>"
```
Use the ad set IDs directly because non-`LIFETIME` aggregate reports require `entity_ids_type` to match `entity_type`. If the campaign has more than 50 ad sets, chunk report requests in groups of 50.
#### 4. Today's ad set metrics
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/aggregate_reports?\
entity_type=AD_SET&\
fields=IMPRESSIONS&fields=SPEND&fields=CLICKS&fields=REACH&fields=CTR&fields=FREQUENCY&fields=COMPLETES&\
granularity=DAY&\
report_start=$(date -u +%Y-%m-%dT00:00:00Z)&\
report_end=$(date -u +%Y-%m-%dT00:00:00Z)&\
${AD_SET_IDS_QUERY}&\
entity_ids_type=AD_SET&\
entity_status_type=AD_SET&\
limit=50"
```
#### 5. Lifetime ad set metrics
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/aggregate_reports?\
entity_type=AD_SET&\
fields=IMPRESSIONS&fields=SPEND&fields=CLICKS&fields=REACH&fields=FREQUENCY&\
granularity=LIFETIME&\
${AD_SET_IDS_QUERY}&\
entity_ids_type=AD_SET&\
entity_status_type=AD_SET&\
include_parent_entity=true&\
limit=50"
```
### Additional Health Checks (Deep Mode)
In addition to the pacing, stalled, and exhaustion checks from the account-wide mode, the deep check adds:
#### 4. Ad Health Check
- **Rejected ads**: Ads with status `REJECTED` — flag with recommendation to review and re-create.
- **Pending ads**: Ads with status `PENDING` where `created_at` is more than 24 hours ago — flag as unusually slow approval.
- **Delivery OFF**: Ads with `delivery: OFF` under an ACTIVE ad set — flag as potentially unintentional.
#### 5. Audience Fatigue Check
- **High frequency**: If lifetime frequency > 3.0 on any ad set, warn about potential audience fatigue. Suggest expanding targetingRelated in Ads & Marketing
ads
IncludedMulti-platform paid advertising audit and optimization skill. Analyzes Google, Meta, YouTube, LinkedIn, TikTok, Microsoft, and Apple Ads. 250+ checks with scoring, parallel agents, industry templates, and AI creative generation.
banana
IncludedAI image generation Creative Director powered by Google Gemini Nano Banana models. Use this skill for ANY request involving image creation, editing, visual asset production, or creative direction. Triggers on: generate an image, create a photo, edit this picture, design a logo, make a banner, visual for my anything, and all /banana commands. Handles text-to-image, image editing, multi-turn creative sessions, batch workflows, and brand presets.
rpg-migration-analyzer
IncludedAnalyzes legacy RPG (Report Program Generator) programs from AS/400 and IBM i systems for migration to modern Java applications. Extracts business logic from RPG III/IV/ILE source code, identifies data structures (D-specs), file operations (F-specs), program dependencies (CALLB/CALLP), and converts RPG constructs to Java equivalents. Generates migration reports, complexity estimates, and Java implementation strategies with POJO classes, JPA entities, and service methods. Use when modernizing AS/400 or IBM i legacy systems, analyzing RPG source files (.rpg, .rpgle, .RPGLE), converting RPG to Java, mapping data specifications to Java classes, planning legacy system migration, or when user mentions RPG analysis, Report Program Generator, RPG III/IV/ILE, AS/400 modernization, IBM i migration, packed decimal conversion, or mainframe application rewrite.
brand-library-architect
IncludedBuild a complete brand library for a product — visual asset render pipeline, brand documentation set (BRAND, COPY, MANIFESTO, BIOS, FAQ, GLOSSARY, TONE, PRICING), open-source convention files (README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT), and a self-contained press kit. This skill should be used when the user asks to "build a brand library / brand kit / press kit / brand assets" for a product, "set up a brand library workflow," "create a positioning manifesto plus visual identity," or any combination of brand documentation + visual asset pipeline. Apply phase-by-phase or run end-to-end. Templates are product-agnostic and use {{TOKEN}} placeholders the skill prompts the user to fill.
writing-tech-post
IncludedAuthors engineering blog posts end-to-end: launch deep-dives, incident postmortems, architecture migrations, performance case studies, tutorials, AI/agent system writeups, security disclosures, and research-to-product translations. Picks the correct archetype, plans the abstraction ladder, enforces an evidence cadence (diagrams, benchmarks, profiles, traces, code, ablations), tunes voice against publisher house styles (Datadog, Vercel, GitHub, AWS, Meta, Cloudflare, Jane Street), and runs a pre-publish gate for narrative momentum and disclosure ethics. Use when drafting a new engineering post, restructuring a draft that feels flat, deciding which evidence form belongs where, validating that depth and product context are balanced, or preparing a postmortem, migration, or performance narrative for external publication. Do not use for API reference documentation, README authoring, marketing copy, release notes, generic SEO content, ghost-written executive thought leadership, or non-engineering long-form essays.
blog-google
IncludedGoogle API integration for blog performance: PageSpeed Insights, CrUX Core Web Vitals with 25-week history, Search Console performance, URL Inspection, Indexing API, GA4 organic traffic, NLP entity analysis for E-E-A-T, YouTube video search for embedding, and Google Ads Keyword Planner. Progressive feature availability based on credential tier (API key, OAuth/service account, GA4, Ads). Shares config with claude-seo at ~/.config/claude-seo/google-api.json. Use when user says "google data", "page speed", "core web vitals", "search console", "indexation", "GA4", "keyword research", "nlp entities", "blog performance", "youtube search", "google api setup".