performance-marketer
Use for Drip Performance Marketer work. Performance Marketer turns a generated Builder drop-site URL plus selected product images into one paused Facebook-only drop-of-week ad artifact, writes perform
SKILL.mdagent/codex-agent/.agents/skills/performance-marketer/SKILL.md
GitHubPerformance Marketer
Performance Marketer creates one paused Facebook ad artifact for the generated Drip drop site. It does not discover trends, generate fashion mockups, activate ads, read performance, run optimization loops, or build storefronts.
The caller can stay lean:
Use $performance-marketer to create one paused Facebook drop-of-week ad for this Builder website and these selected product images: [...]
Inputs
Accept a Builder website URL plus selected product images directly in the prompt or from a provided artifact. Infer safe defaults when omitted.
destinationUrl: required for normal product runs; use the Builder immutable deployment URLselectedMocks: selected product/image records from Fashion DesignerbuilderArtifact: optional Builder output JSON, used for site title, URL, and drop copyimages: selected product image paths or URLs; use all provided selected images as the visual set for the single adinput: optional artifact path, default/vercel/sandbox/agent-workspace/builder-output.jsonassetDir: default/vercel/sandbox/agent-workspace/performance-marketer-assetsoutput: default/vercel/sandbox/agent-workspace/performance-marketer-output.jsonbudgetMinorUnits: default0for draft planning unless the prompt explicitly asks to create real paused Meta objectscurrency: infer from ad account when possible, otherwise recordunknowntargetingCountries: defaultINunless prompt says otherwiseobjective: alwaysoutcome_trafficfor this v1 recipecallToAction: defaultshop_nowwhen supported, otherwiselearn_more
For explicit sandbox smoke prompts only, if no real image paths exist and the
prompt says to create smoke input images, create simple local JPEG files
under /vercel/sandbox/agent-workspace/performance-marketer-smoke-input/ and
record input.syntheticSmokeImages: true. Do not use synthetic images in
normal product runs. Use Python plus Pillow, already installed in the sandbox
base image, to generate realistic square RGB JPEGs at 1080x1080 or larger.
Never use 1x1 fixtures or tiny byte literals for Meta smoke tests; Meta may
reject them during image upload or creative creation. Do not install npm/Python
packages for smoke images. Copy the files into assetDir, validate with
extension plus JPEG/PNG/WebP magic bytes in Node, and for smoke images also
record their width and height in the artifact notes. Do not rely on the file
binary; it is not guaranteed in the sandbox base image.
Workflow
- Parse the Builder destination URL and selected product images. If more images are provided than a single ad can use, keep the strongest practical carousel set and record omissions. Do not split the images into test variants or separate experiments.
- Verify every normal input image path exists, is under the agent workspace,
has a PNG/JPEG/WebP extension, and is suitable for a static ad. For smoke
inputs, require square RGB JPEG/PNG assets at least 1080px on each side.
Copy or convert accepted images into
assetDirwhen needed. - Build a compact ad brief containing the Builder website URL, product names, image paths, drop-of-week positioning, Page requirement, and safety rules.
- Ask
facebook-ad-copywriterfor JSON only. It must fill the single-ad copy schema and do nothing else. - Ask
facebook-ad-operatorto use$meta-ads-cliand create the exact v1 paused drop-of-week recipe only when the prompt explicitly asks for real paused Meta object creation. The work order should contain the copywriter JSON, image paths, destination URL, budget, and country only. Do not describe command strategy in the work order;$meta-ads-cliowns the exact command recipe.- one paused Facebook traffic campaign
- one paused ad set for the drop-of-week audience
- one creative/ad using the generated website link and selected product image set
- no activation and no insights readback
- Convert the operator response into the final artifact. If the operator
fails, preserve its sanitized
stage,errorCode,errorSubcode,errorType, and redactederrorMessagefields so the blocker is actionable without exposing raw IDs, tokens, or dashboard URLs. Do not spawn a second Meta agent. Do not ask for a second status pass. Use the operator's sanitized creation evidence and configured paused states. - Write
performance-marketer-output.json, replacing any previous file. - Validate the JSON parses and the output records
facebookOnly: true,activationPerformed: false,insightsReadbackPerformed: false, andabTestingPerformed: falseas a compatibility safety flag. - Return a short status with the output path and paused-draft evidence, not raw IDs or dashboard URLs.
If named subagents are unavailable, spawn generic subagents with the same work orders. Keep Meta execution delegated to the operator; the main thread owns the artifact and final safety judgment.
Output
Write:
/vercel/sandbox/agent-workspace/performance-marketer-output.json
Use this schema:
{
"schemaVersion": "performance-marketer.facebook-campaign.v1",
"generatedAt": "ISO timestamp",
"input": {
"source": "fashion-designer-output.json or prompt",
"destinationUrl": "https://immutable-builder-url.vercel.app",
"selectedImageRefs": ["idea_01-cap-01", "idea_02-sock-01"],
"syntheticSmokeImages": false,
"omittedImageRefs": []
},
"safety": {
"facebookOnly": true,
"allCreatedPaused": true,
"abTestingPerformed": false,
"activationPerformed": false,
"insightsReadbackPerformed": false,
"rawMetaIdsPersisted": false
},
"campaign": {
"name": "Campaign name",
"safeRef": "campaign:<redacted-or-hash>",
"objective": "outcome_traffic",
"budgetMinorUnits": 0,
"currency": "INR",
"configuredStatus": "PAUSED",
"effectiveStatus": "PAUSED"
},
"adSets": [
{
"dropRef": "drop-of-week",
"name": "Ad set name",
"safeRef": "adset:<redacted-or-hash>",
"targetingCountries": ["IN"],
"configuredStatus": "PAUSED",
"effectiveStatus": "PAUSED"
}
],
"ads": [
{
"dropRef": "drop-of-week",
"imageRefs": ["idea_01-image-01", "idea_02-image-01"],
"imagePath": "/vercel/sandbox/agent-workspace/performance-marketer-assets/idea_01-image-01.jpg",
"creativeName": "Creative name",
"adName": "Ad name",
"creativeSafeRef": "creative:<redacted-or-hash>",
"adSafeRef": "ad:<redacted-or-hash>",
"headline": "Short headline",
"body": "Short body copy.",
"destinationUrl": "https://immutable-builder-url.vercel.app",
"callToAction": "shop_now",
"configuredStatus": "PAUSED",
"effectiveStatus": "PENDING_REVIEW"
}
],
"verification": {
"verifiedAt": "ISO timestamp",
"source": "facebook-ad-operator-created-object-evidence",
"campaignCount": 1,
"adSetCount": 1,
"creativeCount": 1,
"adCount": 1,
"pausedObjectCount": 3,
"issues": []
},
"strategy": {
"subagentsUsed": [
"facebook-ad-copywriter",
"facebook-ad-operator"
],
"notes": []
}
}
Validate it parses:
node -e 'JSON.parse(require("node:fs").readFileSync("/vercel/sandbox/agent-workspace/performance-marketer-output.json", "utf8")); console.log("json-ok")'
Safety
- Use
$meta-ads-clifor all Meta CLI command knowledge. - Keep Performance Marketer-specific campaign counts and Drip output shape in this skill and its subagents.
- Never print tokens, raw account IDs, raw Page IDs, raw campaign/ad set/ad IDs, raw creative IDs, dashboard URLs, or private env values.
- Remember that command stdout/stderr is streamed into Convex events. Require the operator to wrap Meta CLI calls so raw IDs, Page access tokens, and raw JSON never print to the event stream.
- There is no second Meta status agent in this flow. It is too slow for the hackathon path and duplicates evidence the operator already has from created objects.
- Do not run
meta ads insightsin v1. - Do not update any object to active.
- If campaign creation fails before a campaign ID is returned, stop with a
sanitized blocker and do not request a focused retry of
meta ads campaign create. The only valid campaign-create path in this sandbox is the$meta-ads-cliGraph fallback withspecial_ad_categories=[]. - If Meta reports configured active delivery, stop and report failure rather than continuing.