clone
Clone an existing Spotify Ads API campaign or ad set — duplicate the full hierarchy (campaign, ad sets, ads) with optional modifications to name, dates, budget, or targeting.
What this skill does
# Spotify Ads API — Campaign & Ad Set Cloning
Clone an existing campaign or ad set by reading its full hierarchy and recreating it with optional modifications.
## 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
- `campaign <campaign_id>` → Clone a full campaign hierarchy (campaign + ad sets + ads)
- `ad-set <ad_set_id>` → Clone a single ad set and its ads into an existing campaign
- If no argument, ask the user which entity to clone.
---
## Clone Campaign (`campaign <campaign_id>`)
### Step 1: Read Source Hierarchy
#### Fetch the source campaign
```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"
```
#### Fetch 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&sort_direction=DESC"
```
Paginate with `offset` if `total_results > 50`.
#### Fetch 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&sort_direction=DESC"
```
Paginate with `offset` if `total_results > 50`.
### Step 2: Display Source Tree
Present the source hierarchy in tree format:
```
Source: "Summer Promo" (REACH) — campaign_id: abc-123
├── Ad Set: "US 18-34 Audio" (AUDIO, $75/day, US, ages 18-34, Jun 1 – Jun 30)
│ ├── Ad: "30s Spot A" → SHOP_NOW → example.com [APPROVED]
│ └── Ad: "30s Spot B" → LEARN_MORE → example.com [APPROVED]
└── Ad Set: "US 25-54 Video" (VIDEO, $50/day, US, ages 25-54, Jun 1 – Jun 30)
├── Ad: "15s Video" → WATCH_NOW → example.com [APPROVED]
└── Ad: "Old Creative" → SHOP_NOW → example.com [ARCHIVED] ← will be skipped
```
Note how many entities will be cloned and how many will be skipped (ARCHIVED or REJECTED ads are skipped by default).
### Step 3: Ask for Modifications
Ask the user what to change. Default: clone as-is with " (Copy)" appended to names.
**Modification options:**
- **Name**: New campaign name (default: `"{original name} (Copy)"`)
- **Dates**: New `start_time` and `end_time` for all ad sets. If the original dates are in the past, **require** new dates — the clone will fail with past dates.
- **Budget**: Adjust budget for all ad sets. Options:
- Same as original
- Set all to a specific amount
- Increase/decrease by a percentage
- **Targeting**: Change geo, age range, platforms, or genders across all ad sets. Modifications apply to all ad sets uniformly. For per-ad-set changes, suggest cloning individual ad sets.
- **Ad set filter**: Optionally exclude specific ad sets from the clone.
### Step 4: Validate Before Execution
#### Date validation
If the user does not change dates and the source `start_time` is in the past, warn:
- If `start_time` is in the past but `end_time` is in the future: "The cloned ad sets will start delivering immediately."
- If `end_time` is in the past: "Source dates have passed. New dates are required for the clone."
#### Asset validation
For each ad that will be cloned, check that the referenced assets (`asset_id`, `logo_asset_id`, `companion_asset_id`) still exist and are in READY status:
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/assets/$ASSET_ID"
```
If any asset is ARCHIVED or REJECTED, warn the user and ask whether to skip that ad or select a replacement asset.
#### Budget type validation
If budget type is LIFETIME and the user changed dates, verify that `end_time` is still provided — LIFETIME budgets require an end time.
#### Audience estimate validation
If targeting, dates, objective, bid, or budget changed for any cloned ad set, run a pre-flight audience estimate before creating it:
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{
"ad_account_id": "<AD_ACCOUNT_ID>",
"start_date": "<start_time>",
"asset_format": "<AUDIO|VIDEO|IMAGE|CATALOG>",
"objective": "<campaign_objective>",
"bid_strategy": "<MAX_BID|COST_PER_RESULT|AUTOBID|UNSET>",
"bid_micro_amount": <bid>,
"budget": {"micro_amount": <budget>, "type": "<DAILY|LIFETIME>", "currency": "USD"},
"targets": { <SAME_OR_MODIFIED_TARGETS> }
}' \
"$BASE_URL/estimates/audience"
```
If the API returns a min-audience-threshold error, pause before creating that ad set and suggest broader targeting or a lower-threshold format.
### Step 5: Present Clone Plan
Show the full plan with changes highlighted:
```
Clone Plan:
Campaign: "Summer Promo (Copy)" (REACH) ← name changed
├── Ad Set: "US 18-34 Audio (Copy)" (AUDIO, $90/day ← was $75, US, ages 18-34, Jul 1 – Jul 31 ← was Jun 1-30)
│ ├── Ad: "30s Spot A" → SHOP_NOW → example.com
│ └── Ad: "30s Spot B" → LEARN_MORE → example.com
└── Ad Set: "US 25-54 Video (Copy)" (VIDEO, $60/day ← was $50, US, ages 25-54, Jul 1 – Jul 31)
└── Ad: "15s Video" → WATCH_NOW → example.com
Entities to create: 1 campaign, 2 ad sets, 3 ads
Skipped: 1 archived ad ("Old Creative")
```
Ask for confirmation before executing.
### Step 6: Execute Sequentially
Create entities in dependency order, passing IDs forward.
#### 6a. Create campaign
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{"name":"Summer Promo (Copy)","objective":"REACH"}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/campaigns"
```
Extract the new campaign `id` from the response. If this fails, stop — no dependent entities can be created.
#### 6b. Create ad sets (using new campaign_id)
For each source ad set (excluding any the user filtered out):
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{
"name": "US 18-34 Audio (Copy)",
"campaign_id": "<NEW_CAMPAIGN_ID>",
"start_time": "2026-07-01T00:00:00Z",
"end_time": "2026-07-31T23:59:59Z",
"budget": {"micro_amount": 90000000, "type": "DAILY"},
"asset_format": "AUDIO",
"category": "<SAME_CATEGORY>",
"targets": { <SAME_OR_MODIFIED_TARGETS> },
"bid_strategy": "<SAME>",
"bid_micro_amount": <SAME>,
"pacing": "<SAME>",
"delivery": "ON"
}' \
"$BASE_URL/ad_accounts/$AD_ACCOUNT_ID/ad_sets"
```
Extract each new ad set `id`. Map source ad set IDs to new ad set IDs for use in ad creation.
If an ad set creation fails, log the error and skip its ads. Continue with remaining ad sets.
#### 6c. Create ads (using new ad_set_ids)
For each source ad (excluding ARCHIVED/REJECTED), mapped to the correct new ad set:
```bash
curl -s -w "\nHTTP_STATUS:%{http_code}" -X POST -H "Authorization: Bearer $TOKEN" \
-H "$SDK_HEADER" \
-H "Content-Type: application/json" \
-d '{
"name": "30s Spot A",
"ad_set_id": "<NEW_AD_SET_ID>",
"tagline": "<SAME>",
"advertiseRelated 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".