Skip to main content

Overview

Take the copy and images from ad-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

Store in 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:
Dry-run output shows:
  • 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

Response:
Extract the hash:

Batch Image Upload

Check Existing Image by Hash

If you think an image is already uploaded (check workspace/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

Response:
That 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

Always create as PAUSED first. Review in Ads Manager before activating.
Response:

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 from workspace/campaigns/{name}/ads/batch-upload.json:

Batch Upload Process

Invocation:
For each ad in the batch:
  1. Validate copy + image
  2. Upload image → get hash
  3. Create creative
  4. Create ad (PAUSED)
  5. Log result
Example Output:

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 needs ads_management scope:

Invocation Patterns

Campaign File Output

After each upload, save results:

upload.json format

Append to 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 scope
required
Meta ad account ID (format: act_123456789)

Anti-Patterns

Avoid these common mistakes:
  • 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.md for 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.json or 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