← Ad SuperpowersCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Ad Superpowers
Snapshot Sep 30, 2026 · 23:07 UTC · version 2.3.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "meta-ad-launch-playbook",
"description": "This skill should be used when the user wants to launch a Meta campaign end to end, create a batch of Meta ads, turn a folder of creatives into ads, go \"from creatives to live ads\", \"set up a campaign, ad set and ads\", or \"make ads with a different ratio per placement\". It is the single guided runbook from zero to live ads using the Ad Superpowers MCP write tools (meta_create, meta_create_ad), and it routes to the specialist skills for depth. Do NOT use for: getting a file into Meta / image_hash / hosting (use media-upload-guide), choosing a bid strategy in depth (use bid-strategy-selector), CBO vs ABO theory (use campaign-structure-advisor), writing the copy (use ad-copy-generator), creative testing matrices (use creative-diversification-generator), catalog / DPA strategy (use catalog-optimizer).",
"included_files": [],
"skill_md_contents": "---\nname: meta-ad-launch-playbook\ndescription: \"This skill should be used when the user wants to launch a Meta campaign end to end, create a batch of Meta ads, turn a folder of creatives into ads, go \\\"from creatives to live ads\\\", \\\"set up a campaign, ad set and ads\\\", or \\\"make ads with a different ratio per placement\\\". It is the single guided runbook from zero to live ads using the Ad Superpowers MCP write tools (meta_create, meta_create_ad), and it routes to the specialist skills for depth. Do NOT use for: getting a file into Meta / image_hash / hosting (use media-upload-guide), choosing a bid strategy in depth (use bid-strategy-selector), CBO vs ABO theory (use campaign-structure-advisor), writing the copy (use ad-copy-generator), creative testing matrices (use creative-diversification-generator), catalog / DPA strategy (use catalog-optimizer).\"\n---\n# Meta Ad Launch Playbook\n\nThe end-to-end runbook for going from \"I have some creatives\" to live (paused) ads with the Ad Superpowers MCP tools. It owns the **orchestration** — the order of operations and the decisions that trip people up — and hands the deep mechanics to the specialist skills. Follow it top to bottom.\n\n## The journey at a glance\n\n```\n[0] Page & Instagram → confirm the client profile resolves a Page (+ IG)\n │\n[1] Campaign → meta_create(entity_type=\"campaign\") (budget → CBO)\n │\n[2] Ad set → meta_create(entity_type=\"adset\") (+ creative-mode decision)\n │\n[3] Creatives → ads → meta_create_ad(...) per ad (paced batch)\n │\n[4] Verify → meta_query / meta_get_creatives\n```\n\nEverything is created **PAUSED** by default. Nothing spends until you flip it to ACTIVE in review.\n\n## §0 Before you start: Page & Instagram\n\nEvery ad needs a Facebook Page, and Instagram placements need an Instagram account. You usually do **not** pass these by hand — `meta_create_ad` resolves them from the client profile:\n\n- **Auto-resolution.** If the client has a `facebook_page_id` (and optionally `instagram_user_id`) stored, `meta_create_ad` uses them. You only pass `page_id` / `instagram_user_id` to override.\n- **Set them once** with `clients_update` if they are missing, so every future ad just works.\n- **Facebook-only ads.** Pass `facebook_only=true` to deliberately skip Instagram (page-only creative). Do not also pass an Instagram id — that conflicts.\n- **Error `1815199`** (\"ad account has no access to this Instagram account\") means the stored IG account is not linked to this ad account. Fix the link in Business settings or correct `instagram_user_id`; this is surfaced as a real error now rather than a silent page-only fallback.\n\nDiscover what is available:\n\n```python\nmeta_query(account_id=\"act_...\", entity_type=\"promotepages\") # Pages this account can advertise\n```\n\n## §1 Create the campaign\n\n```python\nmeta_create(\n account_id=\"act_...\",\n entity_type=\"campaign\",\n name=\"Spring Launch\",\n objective=\"OUTCOME_TRAFFIC\", # or OUTCOME_SALES / _LEADS / _ENGAGEMENT / _AWARENESS / _APP_PROMOTION\n daily_budget=2000, # cents (€20.00/day). A budget is REQUIRED — pass daily_budget OR lifetime_budget.\n status=\"PAUSED\",\n)\n```\n\nTwo things to internalize:\n\n- **A campaign budget is required, which means every campaign is CBO** (Campaign Budget Optimization). The budget lives on the campaign and the ad sets share it. (ABO / per-ad-set budgets are not creatable through the tool yet.)\n- **`bid_strategy` defaults to `LOWEST_COST_WITHOUT_CAP`.** You normally omit it. This is also why your ad sets do **not** need a `bid_amount` (see §2). Only set a different strategy if you have a real reason:\n - `LOWEST_COST_WITH_BID_CAP` or `COST_CAP` → require a `bid_amount` (set on the ad set).\n - `LOWEST_COST_WITH_MIN_ROAS` → needs a minimum-ROAS target that `meta_create` cannot set today, so this strategy is not configurable through the tool yet (set it in Ads Manager).\n - For the \"which strategy and what number\" decision, `use bid-strategy-selector`. For CBO vs ABO and budget-split theory, `use campaign-structure-advisor`.\n\n## §2 Create the ad set\n\n```python\nmeta_create(\n account_id=\"act_...\",\n entity_type=\"adset\",\n campaign_id=\"<from step 1>\",\n name=\"NL · 25-45 · interests\",\n targeting={\"geo_locations\": {\"countries\": [\"NL\"]}, \"age_min\": 25, \"age_max\": 45},\n optimization_goal=\"LINK_CLICKS\", # must fit the campaign objective\n status=\"PAUSED\",\n)\n```\n\n- **No budget here.** Under CBO the ad set inherits the campaign budget; passing one is rejected.\n- **No `bid_amount` needed** with the default `LOWEST_COST_WITHOUT_CAP`. Only supply `bid_amount` if you deliberately chose a cap strategy in §1.\n- `advantage_audience` defaults sensibly; some objectives require it (the tool tells you if so).\n\n### The creative-mode decision (do this before §3)\n\nThis is the choice that quietly breaks launches. Pick one:\n\n| You want… | Ad set setup | How you build the ad in §3 |\n|-----------|--------------|----------------------------|\n| **One creative concept, the right ratio per placement** (the common case) | **Standard ad set** (leave `is_dynamic_creative` off) | `placement_assets` on `meta_create_ad` |\n| **Meta to auto-optimize across multiple text/creative variants** | **Dynamic Creative ad set**: `meta_create(entity_type=\"adset\", ..., is_dynamic_creative=true)` | `body_variants` (and/or asset combos) on `meta_create_ad` |\n\nTwo things people get wrong:\n\n- **`placement_assets` is NOT Dynamic Creative.** It builds an `asset_feed_spec` with placement `asset_customization_rules`, but that is just placement customization and runs on a **standard** ad set. Using `placement_assets` does not require — and should not be confused with — Dynamic Creative.\n- **`body_variants` requires a Dynamic Creative ad set.** Today, if you pass `body_variants` to an ad on a standard ad set, `meta_create_ad` returns success — and even appends a note like \"Meta will A/B test these variants\" — but Meta drops the extra variants. **Do not trust that note unless the ad set was created with `is_dynamic_creative=true`.** So decide here: if you want multiple text variants, create the ad set with `is_dynamic_creative=true`; if you just want one message shown well across placements, stay standard and use `placement_assets`.\n\n## §3 Creatives → ads\n\nThis is where the playbook earns its keep: **orchestration**. The file-handling mechanics (how to upload, URL vs hash, filename→ratio matching, the full placement list) live in `media-upload-guide` — `use media-upload-guide` for those and do not re-derive them here.\n\n### Group, then build\n\n```\n1. Group your creatives by CONCEPT (a concept = one message/offer, in its various ratios).\n2. One ad per concept.\n3. Within a concept, bundle the aspect ratios via placement_assets (one ad serves the\n right ratio per placement, and keeps a single engagement post across placements).\n4. Split into separate ads when:\n - the copy differs per ratio (placement_assets shares one body/headline), or\n - you are mixing image and video (Meta rejects mixed media in one ad), or\n - it is a genuinely different creative concept (that is a new ad).\n```\n\nA single concept with multiple ratios → one ad:\n\n```python\nmeta_create_ad(\n account_id=\"act_...\",\n adset_id=\"<from step 2>\",\n headline=\"Spring launch\",\n body=\"One message, shown well everywhere.\",\n link_url=\"https://example.com\",\n image_hash=\"<1x1 hash>\", # primary / catch-all fallback (1:1 is safe anywhere)\n placement_assets=[\n {\"image_hash\": \"<9x16 hash>\",\n \"placements\": [\"instagram_stories\", \"facebook_stories\", \"instagram_reels\"]},\n {\"image_hash\": \"<4x5 hash>\",\n \"placements\": [\"instagram_feed\", \"facebook_feed\"]},\n ],\n status=\"PAUSED\",\n)\n```\n\nOther creative types, same `meta_create_ad` call:\n- **Single image / single video** — pass one of `image_url` / `image_hash` / `video_url` / `video_id` (exactly one).\n- **Carousel** — pass `slides=[{image_hash, name, link}, ...]` (2–10 cards).\n- **Per-placement carousel variants** — `placement_assets` entries of the shape `{slides, placements}`.\n\n### Batch pacing (important)\n\nThere is **no bulk-create tool** — a batch is several `meta_create_ad` calls. But writes are throttled:\n\n- **15 writes per hour, per ad account**, and **uploads count as writes**. So 5 image uploads + 5 ad creates = 10 writes.\n- Do **not** fan out an unbounded burst of parallel calls. Pace them within the limit; for a big drop, spread creation across hours, or pre-upload with `media-upload-guide`'s bulk path and create ads later.\n- If one ad in a paced batch hits a **Meta API** error, the others still succeed — that call returns a structured error result rather than aborting the run, so you can retry just the failures. Bad **inputs** are different: invalid media combinations, missing placements, a malformed carousel, or a `facebook_only` + Instagram conflict raise a validation error before the API call, so check each call's inputs before firing the batch.\n\n## §4 Verify + honest limits\n\nRead back what you created:\n\n```python\nmeta_query(account_id=\"act_...\", entity_type=\"ads\", fields=[\"id\",\"name\",\"status\",\"adset_id\"])\n# inspect the creative copy + placements (creative_id comes from the meta_create_ad response)\nmeta_get_creatives(account_id=\"act_...\", scope=\"single\", creative_id=\"<creative_id>\")\n```\n\nCommon stumbles and the fix:\n- \"Bid amount required\" on the ad set → you (or an inherited strategy) chose a cap strategy without a `bid_amount`. With the default `LOWEST_COST_WITHOUT_CAP` this should not happen; if it does, omit the strategy or supply `bid_amount`.\n- Instagram error `1815199` → see §0.\n- `body_variants` \"did nothing\" → the ad set was standard, not Dynamic Creative (see §2).\n- Mixed image + video rejected → split into separate ads.\n\n**Honest limits (today):**\n- **Catalog / Advantage+ catalog ads** cannot be created through MCP: this release ships no catalog tool, so catalog data is not reachable either. Build catalog ads in Ads Manager; `use catalog-optimizer` for the strategy.\n- **No bulk-create tool** — batch = paced `meta_create_ad` calls (see §3).\n\n## Complementary skills\n\n- `use media-upload-guide` — get files into Meta (URL vs hash, hosting, filename→ratio, the full placement list).\n- `use bid-strategy-selector` — pick the bid strategy and the number when you override the default.\n- `use campaign-structure-advisor` — CBO vs ABO, budget splits, account structure.\n- `use ad-copy-generator` / `use video-script-writer` — produce the copy/script before you build.\n- `use creative-diversification-generator` — plan the creative matrix (concepts × angles) feeding §3.\n- `use catalog-optimizer` — catalog / DPA strategy (creation is Ads-Manager-only for now).\n\n## Account integrity reminder\n\nEvery `meta_create_ad` and every upload is a write, and the protection stack caps you at **15 writes per hour per ad account**. Plan batches accordingly; everything ships PAUSED so you can review before any spend.\n"
}SHA-256: 75ee4bb3bfdf19740b33d0963adcae8ea2bffd8f20a5eb64a0fa868a223b65a0