/edit-meta-creative
Edit a Meta ad's creative content — landing page URL, primary text, headline, description, CTA, link description — across one ad or many. Use when the user says "change the URL on my ads", "update the copy", "swap the CTA", or anything that changes what an existing Meta ad
$ npx -y skills add markifact/markifact-mcp --agent claude-codeShips with markifact. Installing the plugin gets this command.
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/edit-meta-creative
Context preview
What this command does when you run it.
Edit a Meta ad's creative content — landing page URL, primary text, headline, description, CTA, link description — across one ad or many. Use when the user says "change the URL on my ads", "update the copy", "swap the CTA", or anything that changes what an existing Meta ad
Command definition
edit-meta-creative.mddescription: Edit a Meta ad's creative content — landing page URL, primary text, headline, description, CTA, link description — across one ad or many. Use when the user says "change the URL on my ads", "update the copy", "swap the CTA", or anything that changes what an existing Meta ad shows. Meta does not allow in-place creative edits, so this command runs the required get → modify → create → replace workflow.
disable-model-invocation: true
argument-hint: [scope, e.g. "all ads in campaign X" or "ad ABC123"]
Goal
Apply a creative-content change to one or more existing Meta ads **without losing learning, frequency caps, ad post engagement, or the ad ID**. The same `ad_id` keeps running with a new creative attached.
The Meta reality this command exists to handle
Meta does **not** allow in-place edits of creative content (URL, text, headline, image, CTA). The only way to change an existing ad's creative is:
get_ad_creative → modify payload locally → create_ad_creative → replace_ad_creative
Anything else (deleting + recreating the ad) destroys learning, frequency capping, social proof (likes/comments), and breaks any link people have to the ad post. Always use `replace_ad_creative` — never delete-and-recreate for a creative change.
Inputs to confirm (batch)
1. Account name (substring) — required. 2. **Scope** — required. One of:
- Single ad ID(s).
- All ads in a campaign / ad set (by name or ID).
- All active ads in the account matching a filter (e.g. status=ACTIVE).
3. **What to change** — required. Examples:
- Landing page URL (the most common bulk edit).
- Primary text / headline / description / link description.
- Call-to-action button.
- Display link / deep link.
4. **Old → new mapping** if it's a find-and-replace (e.g. swap `utm_campaign=spring` for `utm_campaign=summer`, or replace `oldsite.com` with `newsite.com`).
Workflow
1. **Discover** ops: `meta_ads_select_accounts`, `meta_ads_list_ads`, `meta_ads_list_adsets`, `meta_ads_list_campaigns`, `meta_ads_get_ad_creative`, `meta_ads_create_ad_creative`, `meta_ads_replace_ad_creative`. 2. **Inspect** each with `get_operation_inputs`. 3. **Resolve account** via `meta_ads_select_accounts` (substring). 4. **Resolve scope to a list of `ad_id`s** via `meta_ads_list_ads` with the right filters (campaign, ad set, status). Show the user the ad list and the count before doing anything else. 5. **For each ad in scope**: a. `meta_ads_get_ad_creative(ad_id)` → returns the raw creative payload. b. **Modify the payload locally** based on the requested change. Preserve all fields the user did not ask to change. Common fields to patch:
- `object_story_spec.link_data.link` (URL for link/single-image ads)
- `object_story_spec.link_data.message` (primary text)
- `object_story_spec.link_data.name` (headline)
- `object_story_spec.link_data.description` (link description)
- `object_story_spec.link_data.call_to_action.value.link` (CTA link)
- `object_story_spec.link_data.call_to_action.type` (CTA button type, e.g. `LEARN_MORE`, `SHOP_NOW`)
- For video ads: `object_story_spec.video_data.*`
- For carousel: each item under `object_story_spec.link_data.child_attachments[]`
c. `meta_ads_create_ad_creative(modified_payload)` → returns new `creative_id`. **Only works when the existing media (image_hash / video_id) is reused.** If the user is also swapping in fresh media that isn't already in Meta, see "Fresh media" below. d. `meta_ads_replace_ad_creative(ad_id, creative_id)` → attaches the new creative. 6. **Build a diff preview before executing.** Show the user a table of every ad with old → new for each changed field. Wait for explicit confirmation. Then run all replaces, batched into a single `request_human_approval` if approval is required. 7. **Confirm**: count succeeded, count failed (with reason), list of new `creative_id`s.
Use `safe-write-operations` for steps 5c, 5d, and 6.
Fresh media (image/video the user wants to swap in)
`meta_ads_create_ad_creative` expects media that already exists in Meta as `image_hash` or `video_id`. If the user wants brand-new media:
- **Easiest path**: use the dedicated `meta_ads_create_*_ad` op (e.g. `meta_ads_create_single_image_ad`) with `creative_only=true`. That uploads the new media and returns a `creative_id` without creating a new ad. Then call `meta_ads_replace_ad_creative` to attach it.
- Don't try to upload media inside the patched payload — `create_ad_creative` won't process it.
Platform-specific rules the model MUST respect
- **Same `ad_id` survives** the replace. Frequency caps, learning, social proof (likes/comments/shares), permalinks — all preserved. Tell the user this.
- **Replace is one creative per ad.** You cannot attach the same new creative to many ads in one call — loop one ad at a time.
- **Significant creative changes can soft-reset learning.** Meta usually keeps the ad in learning if the creative changes substantially (e.g. new image + new copy). URL-only and minor copy changes typically don't trigger a reset. Warn the user when the change is major.
- **Don't delete-then-recreate.** That loses everything and is what this command exists to prevent.
- **Carousel ads**: the modification has to handle the `child_attachments` array — patch the right index, don't replace the whole array unless the user wants every card changed.
- **Catalog (DPA) ads**: the creative is template-driven from the product catalog — to change URLs you usually edit the catalog feed, not the creative. Check if the ad uses `template_data` and route the user to fix the feed instead.
- **Some fields are not editable** even via this workflow (e.g. `object_story_spec.page_id` — to change Page you must create a new ad). If the user asks for that, say so.
Failure modes & recoveries
- `create_ad_creative` rejects payload → most common cause is referencing media not in this account. Ask user to upload the
Read more
description: Edit a Meta ad's creative content — landing page URL, primary text, headline, description, CTA, link description — across one ad or many. Use when the user says "change the URL on my ads", "update the copy", "swap the CTA", or anything that changes what an existing Meta ad shows. Meta does not allow in-place creative edits, so this command runs the required get → modify → create → replace workflow. disable-model-invocation: true argument-hint: [scope, e.g. "all ads in campaign X" or "ad ABC123"]
Goal
Apply a creative-content change to one or more existing Meta ads **without losing learning, frequency caps, ad post engagement, or the ad ID**. The same `ad_id` keeps running with a new creative attached.
The Meta reality this command exists to handle
Meta does **not** allow in-place edits of creative content (URL, text, headline, image, CTA). The only way to change an existing ad's creative is:
get_ad_creative → modify payload locally → create_ad_creative → replace_ad_creative
Anything else (deleting + recreating the ad) destroys learning, frequency capping, social proof (likes/comments), and breaks any link people have to the ad post. Always use `replace_ad_creative` — never delete-and-recreate for a creative change.
Inputs to confirm (batch)
1. Account name (substring) — required. 2. **Scope** — required. One of:
- Single ad ID(s).
- All ads in a campaign / ad set (by name or ID).
- All active ads in the account matching a filter (e.g. status=ACTIVE).
3. **What to change** — required. Examples:
- Landing page URL (the most common bulk edit).
- Primary text / headline / description / link description.
- Call-to-action button.
- Display link / deep link.
4. **Old → new mapping** if it's a find-and-replace (e.g. swap `utm_campaign=spring` for `utm_campaign=summer`, or replace `oldsite.com` with `newsite.com`).
Workflow
1. **Discover** ops: `meta_ads_select_accounts`, `meta_ads_list_ads`, `meta_ads_list_adsets`, `meta_ads_list_campaigns`, `meta_ads_get_ad_creative`, `meta_ads_create_ad_creative`, `meta_ads_replace_ad_creative`. 2. **Inspect** each with `get_operation_inputs`. 3. **Resolve account** via `meta_ads_select_accounts` (substring). 4. **Resolve scope to a list of `ad_id`s** via `meta_ads_list_ads` with the right filters (campaign, ad set, status). Show the user the ad list and the count before doing anything else. 5. **For each ad in scope**: a. `meta_ads_get_ad_creative(ad_id)` → returns the raw creative payload. b. **Modify the payload locally** based on the requested change. Preserve all fields the user did not ask to change. Common fields to patch:
- `object_story_spec.link_data.link` (URL for link/single-image ads)
- `object_story_spec.link_data.message` (primary text)
- `object_story_spec.link_data.name` (headline)
- `object_story_spec.link_data.description` (link description)
- `object_story_spec.link_data.call_to_action.value.link` (CTA link)
- `object_story_spec.link_data.call_to_action.type` (CTA button type, e.g. `LEARN_MORE`, `SHOP_NOW`)
- For video ads: `object_story_spec.video_data.*`
- For carousel: each item under `object_story_spec.link_data.child_attachments[]`
c. `meta_ads_create_ad_creative(modified_payload)` → returns new `creative_id`. **Only works when the existing media (image_hash / video_id) is reused.** If the user is also swapping in fresh media that isn't already in Meta, see "Fresh media" below. d. `meta_ads_replace_ad_creative(ad_id, creative_id)` → attaches the new creative. 6. **Build a diff preview before executing.** Show the user a table of every ad with old → new for each changed field. Wait for explicit confirmation. Then run all replaces, batched into a single `request_human_approval` if approval is required. 7. **Confirm**: count succeeded, count failed (with reason), list of new `creative_id`s.
Use `safe-write-operations` for steps 5c, 5d, and 6.
Fresh media (image/video the user wants to swap in)
`meta_ads_create_ad_creative` expects media that already exists in Meta as `image_hash` or `video_id`. If the user wants brand-new media:
- **Easiest path**: use the dedicated `meta_ads_create_*_ad` op (e.g. `meta_ads_create_single_image_ad`) with `creative_only=true`. That uploads the new media and returns a `creative_id` without creating a new ad. Then call `meta_ads_replace_ad_creative` to attach it.
- Don't try to upload media inside the patched payload — `create_ad_creative` won't process it.
Platform-specific rules the model MUST respect
- **Same `ad_id` survives** the replace. Frequency caps, learning, social proof (likes/comments/shares), permalinks — all preserved. Tell the user this.
- **Replace is one creative per ad.** You cannot attach the same new creative to many ads in one call — loop one ad at a time.
- **Significant creative changes can soft-reset learning.** Meta usually keeps the ad in learning if the creative changes substantially (e.g. new image + new copy). URL-only and minor copy changes typically don't trigger a reset. Warn the user when the change is major.
- **Don't delete-then-recreate.** That loses everything and is what this command exists to prevent.
- **Carousel ads**: the modification has to handle the `child_attachments` array — patch the right index, don't replace the whole array unless the user wants every card changed.
- **Catalog (DPA) ads**: the creative is template-driven from the product catalog — to change URLs you usually edit the catalog feed, not the creative. Check if the ad uses `template_data` and route the user to fix the feed instead.
- **Some fields are not editable** even via this workflow (e.g. `object_story_spec.page_id` — to change Page you must create a new ad). If the user asks for that, say so.
Failure modes & recoveries
- `create_ad_creative` rejects payload → most common cause is referencing media not in this account. Ask user to upload the
Showing the first part of this file.
Manage Google Ads, Meta Ads, TikTok Ads, LinkedIn Ads, Microsoft Ads, Reddit Ads, Pinterest Ads, Snapchat Ads, Amazon Ads, DV360, GA4, BigQuery, Google Search Console, Google Business Profile, Google Merchant Center, Facebook, Instagram, LinkedIn, Shopify,
Other commands on markifact.
- /diagnose-underperformer
Diagnose why a specific Google Ads or Meta Ads campaign / ad set / ad is underperforming and prescribe the next concrete action. Use when the user says something like "why is X not converting?", "this campaign is wasting money", or "why are impressions so low?". Read-only — no
Open command - /launch-google-search
Launch a complete Google Ads Search campaign — campaign, ad group, responsive search ads, keywords, sitelinks, callouts, and negatives — built paused and ready to review. Use when the user wants to spin up a new Search campaign on Google Ads.
Open command - /launch-meta-campaign
Launch a complete Meta Ads campaign — campaign, ad set, and ad(s) — built paused and ready to review. Use when the user wants a new Facebook/Instagram campaign.
Open command - /launch-pmax
Launch a Google Ads Performance Max campaign with a complete asset group, audience signals, and (for ecom) listing groups. Built paused for review. Use when the user wants a new PMax campaign.
Open command - /negative-keyword-sweep
Find wasted spend in Google Ads search terms and add negatives at the right scope (account list, campaign, or ad group). Use when the user says "find junk keywords", "stop wasting on bad searches", or wants a search-terms cleanup.
Open command - /rotate-creative
Pause fatigued ads and ship fresh creative variants in their place. Works on both Meta and Google Ads. Use when CTR is dropping, frequency is climbing, or the user says "creative is tired" / "let's refresh ads". Always starts new variants paused.
Open command

