Overview
Take the copy and images fromad-copy-generator and push them straight to Meta. No copy-paste into Ads Manager. No manual creative setup. Just: generate, review, upload.
This skill handles the full upload chain: image → hash → creative (with asset_feed_spec) → ad.
Brand Memory Integration
Reads
optional
Stored ad account ID, default ad set IDs, target CPA
optional
Index of existing creatives and their IDs
optional
Past upload patterns, what’s worked
Writes
Appends uploaded creative IDs and ad IDs
Full API response — creative ID, ad ID, status
Setup
Token
Ad Account
workspace/brand/stack.md so you don’t set these every time:
The Upload Chain
Every ad goes through four steps:Step 1: Validate Before Uploading
Run validation before touching the API. Catch errors locally.Copy Validation
Valid Meta CTA Types
Image Validation
Dry-Run Mode
Add--dry-run to any operation to see exactly what would be sent without hitting the API:
- Validation results
- Exact JSON payload that would be sent to each endpoint
- Estimated creative/ad names
- No API calls made, no IDs returned
Step 2: Upload Images
Single Image Upload
Batch Image Upload
Check Existing Image by Hash
If you think an image is already uploaded (checkworkspace/brand/assets.md):
Step 3: Create Ad Creative (asset_feed_spec)
This is Meta’s Degrees of Freedom format. You provide multiple headlines, bodies, descriptions, and images — Meta automatically tests combinations across placements.Full asset_feed_spec Creative
id is your CREATIVE_ID for Step 4.
Multiple Images in asset_feed_spec
3 images × 3 headlines × 3 bodies = 27 combinations. Meta’s algorithm finds the winners.
Verify Creative Was Created
Step 4: Create Ad
Create New Ad
Create Ad with Tracking Spec
Activate an Ad (after review)
Update Existing Ad (Copy Refresh)
When a creative is fatigued, don’t rebuild from scratch — swap in fresh copy.Step 1: Get Current Creative
Step 2: Create New Creative with Fresh Copy
Run Step 3 above with updated bodies/titles/descriptions.Step 3: Attach New Creative to Existing Ad
You’re replacing the creative on the existing ad. The ad ID stays the same (metrics history preserved). The old creative still exists — it’s just detached from this ad.
Batch Mode
Upload copy for multiple ads in one session.Batch Input Format
Reads fromworkspace/campaigns/{name}/ads/batch-upload.json:
Batch Upload Process
Invocation:- Validate copy + image
- Upload image → get hash
- Create creative
- Create ad (PAUSED)
- Log result
Error Handling
Common Graph API Errors
Token Expiry (Error 190)
Rate Limits (Error 294)
Meta’s Marketing API uses a score-based rate limit, not a simple per-minute cap. Back off with exponential retry:Permission Issues (Error 200)
Token needsads_management scope:
Invocation Patterns
Campaign File Output
After each upload, save results:upload.json format
workspace/brand/assets.md:
Integration with Other Skills
This skill is the downstream piece of the Meta Ads Copilot ecosystem:- Upstream (required):
ad-copy-generator— produces the asset_feed_spec JSON and copy variants - Upstream (trigger):
ad-creative-monitor— detects creative fatigue and flags ads that need copy refresh - Downstream:
meta-ads— monitor performance of the ads this skill just created
Typical Full Workflow
Environment Variables
required
Facebook access token with
ads_management scoperequired
Meta ad account ID (format:
act_123456789)Anti-Patterns
- Activating ads immediately — Always create as PAUSED, review in Ads Manager first
- Uploading without dry-run on first use — Use dry-run until you’ve confirmed the chain works end-to-end
- Ignoring validation errors — Headline truncation kills CTR; fix it before uploading
- Uploading duplicate images — Check
workspace/brand/assets.mdfor existing hashes first - One-size copy across all placements — asset_feed_spec exists so Meta can optimize per placement; give it options (3+ bodies, 3+ titles)
- Using WebP images — Meta accepts them sometimes but rejects them in specific placements; stick to JPG/PNG
- Hard-coding token in scripts — Always read from
~/.social-cli/config.jsonor env var; never commit tokens - Skipping the page ID — Creative will fail without a valid Facebook Page ID in
object_story_spec - Not saving upload responses — If you don’t save the creative ID and ad ID, you can’t update or monitor later
- Creating new ad for copy refresh — Update the creative on the existing ad to preserve metric history and delivery algorithm learning
Next Steps
- Ad Copy Generator — Generate the asset_feed_spec JSON that feeds this skill
- Meta Ads — Monitor performance of uploaded ads
- Ad Creative Monitor — Detect when ads need copy refresh