--- name: paid-ads-agent-platforms description: Build self-hosted paid-advertising agent systems where Hermes/OpenClaw-style skills operate Meta/Google/TikTok/etc. ads through official APIs/CLIs, with dashboard queues, creative studios, reporting, approvals, and strict spend-safety guardrails. version: 1.0.0 author: Hermes Agent license: MIT metadata: hermes: tags: [paid-ads, meta-ads, advertising, hermes-skills, dashboard, approvals, marketing-api, self-hosted] related_skills: [hermes-agent, vps-app-deployment, third-party-api-data-sync, writing-plans] --- # Paid Ads Agent Platforms Use this skill when building or planning an AI-agent system that manages paid ads (especially Meta/Facebook/Instagram Ads) through Hermes, OpenClaw-style skills, MCPs, official CLIs, or direct marketing APIs. This is a **class-level** skill for self-hosted ad-ops agent platforms: chat-first operation, dashboard visibility, local state, approval queues, creative generation, performance reporting, and spend-safety controls. ## Core posture for Alex Alex prefers the **build-it-ourselves** route over paid opaque SaaS wrappers for ad automation. Default architecture: 1. **Hermes-first command surface** — Alex chats with Hermes to report, draft, diagnose, and eventually execute ad changes. 2. **Dashboard as cockpit** — web app shows queues, approvals, campaign state, creative previews, reports, monitor rules, and audit logs. 3. **Official platform API/CLI as action engine** — for Meta, prefer Meta's official Ads CLI / Marketing API before third-party remote MCPs. 4. **OpenClaw-style skill ergonomics** — simple env vars, local scripts, JSON output, natural-language command mapping, and transparent references. 5. **Safety before autonomy** — read-only first, drafts second, paused writes third, active spend only after explicit approval. ## When to load this skill Load this skill when the user asks to: - Build a Meta Ads / Facebook Ads / Instagram Ads automation agent. - Create a Hermes skill for managing ad campaigns. - Design a dashboard for Hermes-managed ad operations. - Research or adapt OpenClaw/Claude/Hermes ad skills. - Integrate Meta Marketing API, Ads CLI, ad insights, campaign creation, creative generation, or approval queues. - Add ad monitoring cron jobs, spend alerts, CPA/ROAS reports, or creative fatigue checks. - Build project-aware ad creative workflows. ## Recommended architecture ```text User chat → Hermes → paid-ads skill/scripts ↓ Local app API/database ←→ Dashboard ↓ Official Ads CLI / Marketing API adapter ↓ Ad platform account hierarchy ``` Separate responsibilities clearly: - **Hermes owns orchestration:** natural language, strategy, context lookup, diagnosis, drafting, cron reports, and execution after approval. - **Dashboard owns visibility:** project mapping, ad-account tree, draft queue, creative previews, reports, monitors, and audit log. - **Adapter owns platform calls:** normalize official CLI/API operations so workflows do not depend on one transport. ## Data model pattern Mirror the ad platform hierarchy locally, then attach richer local workflow state. Minimum entities: - `projects` — local apps/products/businesses being marketed. - `locations` — optional physical locations/geos tied to a project. - `ad_accounts` — platform account metadata, not secrets. - `project_ad_links` — maps local projects to ad account/page/pixel/event IDs. - `campaigns`, `ad_sets`, `ads`, `creatives` — local cache of platform hierarchy. - `drafts` — Hermes-created changes awaiting approval. - `approvals` — explicit accept/reject/needs-changes decisions. - `insight_snapshots` — saved performance pulls. - `monitor_rules` — scheduled checks and alert/action rules. - `audit_events` — append-only record of prompts, drafts, approvals, API calls, and errors. ## Build phases ### Phase 1: Read-only proof Start by proving data access and reporting. - Validate token/account access with a minimal smoke test before building dashboard/reporting UI. - List campaigns/ad sets/ads. - Pull insights for yesterday/last 7/last 30 days. - Save snapshots. - Generate reports with spend, impressions, clicks, CTR, CPC, CPM, conversions, CPA/CAC, frequency, and warnings. Smoke-test discipline: - Keep real tokens in an uncommitted `.env`; verify `.env` is ignored and never print full tokens. - When Alex provides a new Meta system-user token, compare it to the existing token with redacted fingerprints only, update `META_ACCESS_TOKEN`, set `.env` to `0600`, remove any temporary secret-bearing backup once verification passes, and restart `hermes-ads` with `pm2 restart hermes-ads --update-env`. - If a token was pasted into chat, treat it as exposed: it is acceptable for immediate testing, but recommend rotating again after setup and entering the fresh token directly on the VPS rather than through chat/logs/screenshots/Git. - For Meta, a token shaped like `APP_ID|...` is usually an app/client token and will not read ad account data. Use a User/System User token with `ads_read` and `read_insights`. - Request only minimal ad-account fields (`id,account_id,name,account_status,currency,timezone_name`) for the baseline proof. Adding nested `business{...}` can trigger `(#100) Requires business_management permission` even when read-only ads reporting works. - Empty campaign/insight arrays are acceptable if the account has no campaigns/spend; the success criterion is the API call succeeding. Do **not** start with campaign creation. ### Phase 2: Local dashboard MVP Build a web app that displays read-only state: - Project list/detail. - Ad account/campaign tree. - Reports. - Draft queue placeholder. - Audit log. Use Alex's VPS deployment conventions from `vps-app-deployment`. ### Phase 3: Draft queue Hermes can create local drafts only: - Campaign draft. - Ad set draft. - Ad/creative draft. - Budget-change draft. - Pause/enable recommendation. Dashboard approves/rejects drafts; no platform writes yet. ### Phase 4: Paused writes after approval Only approved drafts can call the platform API/CLI. **Separate approval from execution in the UX.** A button labeled “Approve” should only record local human approval unless it explicitly says it will push to the ad platform. Use a second, unambiguous action such as **Push to Meta as PAUSED** for platform writes. After the push, persist returned platform IDs on the draft, change draft status to a pushed state (for example `pushed_paused`), show the IDs/search hint in the queue, and audit the action. This prevents the user from expecting Ads Manager objects to appear after a purely local approval. For Meta, create entities in `PAUSED` status by default where the API/CLI supports it. Treat the first write test as a full hierarchy smoke test: Campaign → Ad Set → Creative → Ad. If Campaign/Ad Set succeeds but Creative/Ad fails, preserve and report the partial success rather than retrying blindly. Meta paused-write gotchas: - A token with `ads_management` can successfully create paused Campaigns and Ad Sets while still being blocked at Creative/Ad creation. - If `adcreatives` fails with `(#100) Ads creative post was created by an app that is in development mode...` / subcode `1885183`, the fix is to switch the Meta Developer App from Development to Live/Public mode before retrying. - Page-backed creative flows may also require `pages_read_engagement`; Page access failures can appear as `Object does not exist...` even when the ID is correct. - Use explicit `TEST` + timestamp names and tiny budgets (for example `$5/day`) for smoke tests so Alex can find the objects in Ads Manager and verify they are paused. ### Phase 5: Monitoring and cron Add scheduled checks: - Spend with zero conversions. - CPA over target. - Frequency/creative fatigue. - Learning limited / delivery issues. - Status changes. Default action is alert-only. Auto-actions require explicit configuration and tight caps. ### Phase 6: Creative/context deepening Make creative generation project-aware: - Pull from correct repo/docs/site/assets/location data. - Store provenance. - Generate copy angles, hooks, briefs, and platform-specific variants. - Add competitor/ad-library inspiration only as later optional research. ## Meta Ads-specific guidance Prefer these credentials for read-only MVP: - `META_ACCESS_TOKEN` - `META_AD_ACCOUNT_ID` with `act_` prefix - Permissions such as `ads_read` and `read_insights` Write mode later needs `ads_management` and often page/pixel/business context. Important Meta hierarchy: ```text Business Manager Ad Account Campaign Ad Set Ad Creative ``` Reporting metrics to normalize: - Spend - Impressions - Reach - Frequency - CPM - CTR - CPC - Actions/conversions by event - CPA/CAC - ROAS/revenue if available Diagnosis concepts to include in references: - Breakdown Effect: avoid naïvely pausing segments because apparent CPA differs. - Learning Phase / Learning Limited: understand conversion volume and reset triggers. - Auction overlap: avoid competing against yourself. - Pacing: check delivery against budget and time window. - Creative fatigue: frequency + declining CTR/CVR. - Pixel/CAPI health: verify events exist and conversion counts are plausible. - Attribution caveats: platform-reported conversions/ROAS may be modeled or inflated relative to backend truth. ## Safety policy Default blocked or confirmation-required actions: - Activating campaigns/ad sets/ads. - Increasing budgets. - Deleting entities. - Editing pixel/CAPI/attribution settings. - Changing billing/payment/account settings. - Using unverified claims in ad copy. - Spending above project/account caps. Default allowed actions: - Read-only reporting. - Local drafts. - Local creative briefs. - Alerts/recommendations. - Creating paused platform entities after explicit approval. When a request implies spend or platform mutation, require exact target identity and explicit approval. Log every action. ## Skill/package pattern A Hermes ad-operator skill should include: ```text meta-ads-operator/ ├── SKILL.md ├── scripts/ │ ├── meta_adapter.py │ ├── report.py │ ├── diagnose.py │ ├── draft_campaign.py │ └── execute_approved.py ├── references/ │ ├── safety-policy.md │ ├── reporting-metrics.md │ ├── meta-diagnosis-framework.md │ └── creative-brief-framework.md └── templates/ ├── daily-report.md ├── campaign-draft.json └── creative-brief.md ``` Scripts should output JSON so Hermes can summarize reliably. ## Dashboard pattern Recommended screens: - Command Center - Projects - Ad Account Tree - Approval Queue - Creative Studio - Reports - Monitors - Audit Log - Settings For Alex, make the dashboard mobile-first and single-column by default. Chat remains the primary control surface. Approval queue UX for ads: - Keep queue cards compact; do not over-design them with oversized hero art, large padding, or bloated decorative sections. Alex will call this out as visually bloated. - Surface the relevant approval facts immediately: ad copy, headline, CTA, landing URL, image/asset or image prompt, campaign name/objective/status, ad set audience/budget/optimization, and safety/push state. - If only an image prompt exists, show it as a compact brief/placeholder — do not imply a real image asset exists. - Separate **Approve locally** from **Push to platform as PAUSED**; disable push until approved and show returned platform IDs after push. ## Research and session-specific references - See `references/hermes-ads-planning.md` for the Hermes Ads planning repo, session decisions, and public-skill inspiration notes. - See `references/hermes-ads-wizard-launch.md` for the first deployed internal Meta hookup wizard, live URL/PM2 details, and launch-specific deployment quirks. - See `references/hermes-ads-hookup-wizard.md` for the internal Meta hookup wizard pattern: Astral-style onboarding, official Meta links, checklist progress, safe `.env` template generation, PWA details, and deployment verification gotchas. - See `references/hermes-ads-dashboard-mvp.md` for the first deployed dashboard MVP pattern: SQLite persistence, Meta sync/report endpoints, mobile cockpit tabs, local draft/approval queue, audit events, verification commands, and the safety boundary before `ads_management` writes. - See `references/meta-readonly-smoke-test.md` for the safe token-handling and minimal Meta read-only smoke-test pattern, including app-token vs user/system-user token behavior and avoiding `business_management`-only fields. - See `references/meta-paused-write-smoke-test.md` for the first safe Meta write pattern: paused Campaign → paused Ad Set → Creative/Ad, partial-success reporting, Development Mode creative blocker (`1885183`), Live/Published-mode success, bid-strategy gotchas, public legal URL setup, and `pages_read_engagement` page-access pitfalls. - See `references/meta-system-user-token-rotation.md` for the safe Hermes Ads token update pattern: compare redacted fingerprints, update `META_ACCESS_TOKEN`, chmod `.env` to `0600`, avoid secret backups, restart PM2 with `--update-env`, and verify with `scripts/meta_readonly_smoke.py`. - See `references/hermes-ads-paused-draft-push.md` for the dashboard-driven approved-draft push pattern: separate local approval from **Push to Meta as PAUSED**, persist Meta IDs back onto drafts, audit failures/partial IDs, and keep approval queue cards compact rather than visually bloated. - See `references/openclaw-meta-ads-comparison.md` for ClawHub/OpenClaw Meta Ads skill notes: the original `meta-ads-open-cli` is read-only, OpenClaw's posture is analyze-first/recommend-second/change-last, and Meta App Review should position Hermes Ads as an internal human-approved dashboard that creates paused entities only. ## Internal Meta hookup wizard pattern When Alex asks for a setup/onboarding wizard for Meta Ads hookup, build a guide-first internal tool before full OAuth or write automation: - Use an Astral-style, Typeform-like mobile-first flow: large step copy, card inputs, progress bar, sticky bottom navigation, durable local task list. - Collect non-secret asset IDs: Business ID, `act_...` Ad Account ID, Page ID, Instagram account ID, pixel/dataset ID, and Meta App ID. - Include direct, clickable official Meta links for Business Settings, Business Info, ad accounts, Pages, Instagram accounts, Events Manager, Developers Apps, Marketing API docs, Access Token Debugger, and Graph API Explorer. Do not merely mention a destination like “Business Settings”; every destination should be an actual button/link. - Put small expandable guides directly under the relevant inputs. Each guide should explain exactly where to click, what ID/value to copy, common business-switcher pitfalls, and include the matching Meta link again so Alex can act without hunting through a separate links page. - Generate a safe `.env` template but warn that real access tokens belong only in an uncommitted VPS `.env`, not Git, logs, screenshots, or browser localStorage. - Keep the first milestone read-only (`ads_read`, `read_insights`). `ads_management` remains later, explicit-approval-gated write mode. ## Pitfalls - Do not let the existence of paid MCP/SaaS products push the architecture into opaque dependency. Use them only as pattern inspiration unless Alex explicitly chooses them. - Do not begin with autonomous writes. Read-only first. - Do not store tokens in git or log them to audit events. - Do not model local state in a way that fights the ad platform hierarchy; mirror the platform first, enrich locally second. - Do not make the dashboard the only control surface; Hermes chat should be able to operate the system end-to-end.