ads-meta
Skill1 starsChanged 5 days agoMITView on GitHub
Use when wiring Meta Pixel plus Conversions API purchase tracking, building a Custom Audience or Lookalike, debugging zero or phantom Purchase events, or when the Meta Ads MCP will not authenticate in Claude Code or a token returns no ad accounts.
- Reads credentials
12 other projects use a version of this.
Adopted by
Most recently taken up by
- oivanfelipe/claude-skillstheir own version, first seen Nov 8, 2026
- pooriaarab/skillsword for word, first seen Nov 7, 2026
- Hainrixz/claude-adstheir own version, first seen Nov 1, 2026
- AgriciDaniel/claude-adstheir own version, first seen Oct 25, 2026
- hackjpn/claude-skillstheir own version, first seen Oct 11, 2026
- chriswestt/claude-skillstheir own version, first seen Oct 9, 2026
Used with
Projects with it also use ads-test, ads-dna and 7 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
chriswesttSkillads-test
A/B test design and experiment planning for paid advertising. Structured hypothesis framework, statistical significance calculator, test duration estimator, sample size calculator, and platform-specific experiment setup guides (Meta Experiments, Google Experiments, LinkedIn A/B). Use when user says A/B test, split test, experiment design, test hypothesis, statistical significance, sample size, or test duration.
Also in 5 projects that use this
chriswesttSkillads-dna
Brand DNA extractor for paid advertising. Scans a website URL to extract visual identity, tone of voice, color palette, typography, and imagery style. Outputs brand-profile.json to the current directory. Run before /ads create or /ads generate for brand-consistent creative. Triggers on: brand DNA, brand profile, extract brand, brand identity, brand colors, what is the brand voice, analyze brand, brand style guide.
Also in 6 projects that use this
OpenAISkillgsap
GSAP animation reference for HyperFrames. Covers gsap.to(), from(), fromTo(), easing, stagger, defaults, timelines (gsap.timeline(), position parameter, labels, nesting, playback), and performance (transforms, will-change, quickTo). Use when writing GSAP animations in HyperFrames compositions.
Also in 3 projects that use this
OpenAISkillhyperframes-cli
HyperFrames CLI tool — hyperframes init, lint, inspect, preview, render, transcribe, tts, doctor, browser, info, upgrade, compositions, docs, benchmark. Use when scaffolding a project, linting, validating, inspecting visual layout in compositions, previewing in the studio, rendering to video, transcribing audio, generating TTS, or troubleshooting the HyperFrames environment.
Also in 3 projects that use this
- +5 more from chriswestt
Other versions12 projects use a version of this.
Word for word · 1
- pooriaarab/skills★ 1100% same
Edited · 0
None found.
Wrote their own version · 11
- AgriciDaniel/claude-ads★ 10ksame name
- Hainrixz/claude-ads★ 102same name
- coopersimson96/ai-content-system★ 17same name
- megastep/codex-skills★ 4same name
- Maxymize/maxym-ai-ads★ 2same name
- get-proofpilot/claude-skills-catalog★ 1same name
- giovani-junior-dev/trafego-pack★ 1same name
- Biznomad/claude-skills★ 0same name
- chriswestt/claude-skills★ 0same name
- hackjpn/claude-skills★ 0same name
1 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository325 other files it gives its agents.
- AGENTS.mdAGENTS.md
- accept-x402-paymentsSkill
- ad-auto-optimizerSkill
- ad-conversion-hubSkill
- ad-creative-generationSkill
- ad-creative-templatesSkill
- ad-experimentsSkill
- ad-image-prompt-librarySkill
- adobe-express-addonSkill
- ad-platform-credentialsSkill
- ads-amazonSkill
- ads-apple-searchSkill
- ads-baiduSkill
- ads-bilibiliSkill
- ads-chatgptSkill
- ads-copilotSkill
- ads-criteoSkill
- ads-discordSkill
- ads-douyinSkill
- ads-googleSkill
- ads-hotstarSkill
- ads-kakaoSkill
- ads-kuaishouSkill
- ads-lgSkill
- ads-lineSkill
- ads-linkedinSkill
- ads-mercadolibreSkill
- ads-meta-aiSkill
- ads-microsoftSkill
- ads-mojSkill
- ads-naverSkill
- ads-nextdoorSkill
- ads-outbrainSkill
- ads-perplexitySkill
- ads-pinterestSkill
- ads-quoraSkill
- ads-redditSkill
- ads-rokuSkill
- ads-samsungSkill
- ads-sharechatSkill
- ads-shopeeSkill
- ads-snapchatSkill
- ads-spotifySkill
- ads-stackadaptSkill
- ads-stravaSkill
- ads-taboolaSkill
- ads-tencentSkill
- ads-tiktokSkill
- ads-trade-deskSkill
- ads-twitchSkill
- ads-vkSkill
- ads-wazeSkill
- ads-weiboSkill
- ads-xiaohongshuSkill
- ads-xSkill
- ads-yahoo-japanSkill
- ads-yandex-directSkill
- ads-yelpSkill
- agent-avatar-systemSkill
- agent-browser-consolesSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 5 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 10 edited versions we read keep these.
5
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 81
Always add client_ip_address + client_user_agent server-side — they materially improve match rate and are only available on the server.
- Very specific: line 137
If me works but adaccounts is [], go back and do layer 3.
- Distinctive: line 141
Lookalike: create a custom audience seeded off your highest-value users, then a 1%-of-country lookalike from it.
- Distinctive: line 161
Reels / Stories: Use full-bleed 9:16 creative.
- Distinctive: line 162
Feed: Use 4:5 or 1:1 creative. Make it thumb-stopping but legible with muted playback.
- Distinctive: line 163
Right column / Audience Network: Create their own variants with smaller ratios suited to those placements.
- Distinctive: line 194
Prefer these over the Events Manager UI's "Test Events" tab when you need a durable count rather than a live poke.
- Very specific: line 203
Run one narrow audience × geo × creative per experiment, prove the cheapest conversion (free signup) first, and judge results on …
- Very specific: line 233
Use the shared conversion-hub contract: emit one canonical event, use a stable event_id, send the event after the payment provider confirms …
“Common” is measured: kept by at least 6 in 10 of the 10 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
ads-meta
Meta conversion tracking has two halves — a client-side Pixel (fires in the browser on page load and on purchase) and a server-side Conversions API (CAPI) call (fires from your backend after the charge actually happens, e.g. a payment webhook). Ship both together with a shared dedup key, or purchases get double-counted.
When to use
- Triggers: 'Meta pixel', 'Conversions API', 'CAPI', 'Purchase events missing', 'phantom Purchase on signup', 'Lookalike audience', 'Meta Ads MCP URL Blocked', 'System User token', 'empty adaccounts'.
- Client Pixel (fbq base plus Purchase) and server CAPI (Graph /{pixel-id}/events) with a shared event_id dedup key; the unset CAPI token that silently no-ops; firing on hashed-email match, not fbclid, so organic purchases report; advanced matching.
- App-capability 400s (Advanced Access for ads_management, promotable Page); Lookalikes from a hashed-email Custom Audience (USER_PROVIDED_ONLY, EMAIL_SHA256, 100 matched-user floor); a Purchase on free signup is usually the Automatic Events setting; verification via Graph stats and last_fired_time.
- Meta Ads MCP in the CLI: the hosted mcp.facebook.com/ads OAuth fails with 'URL Blocked / redirect_uris not registered' (works only on claude.ai web or Desktop); the token fix with pipeboard-co/meta-ads-mcp and META_ACCESS_TOKEN; the Business Settings path to a non-expiring System User token (app role, scopes with SMS 2FA, ad-account assignment).
Setup, in order
- Meta Events Manager → create a dataset / pixel. The pixel id is a numeric string, safe to expose client-side (it's not a secret).
- Generate a CAPI access token — Events Manager → your dataset → Settings → Conversions API → Generate access token. This is a secret; server-side only.
- Attach a promotable Facebook Page to the ad account (needed later for creating ads).
Client-side Pixel
Standard fbq base + a Purchase event on the confirmation page:
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '<PIXEL_ID>');
fbq('track', 'PageView');
</script>Fire the purchase with an event_id — this is the dedup key that pairs with the server event:
fbq('track', 'Purchase', { value: 25, currency: 'USD' }, { eventID: '<shared-dedup-id>' });Note the client SDK's param is eventID (in the fourth options arg); the server CAPI payload below uses event_id. Same value, different casing — don't typo one into the other.
Server-side Conversions API (Graph)
POST https://graph.facebook.com/v19.0/{pixel-id}/events?access_token=<CAPI_ACCESS_TOKEN>
Content-Type: application/json{
"data": [{
"event_name": "Purchase",
"event_time": 1700000000,
"event_id": "<shared-dedup-id>",
"action_source": "website",
"user_data": {
"em": ["<sha256 of lowercased-trimmed email>"],
"external_id": ["<sha256 of your stable user id>"],
"client_ip_address": "<request ip>",
"client_user_agent": "<request user-agent>",
"fbc": "<_fbc cookie value, only if present>",
"fbp": "<_fbp cookie value, if present>"
},
"custom_data": {
"value": 25,
"currency": "USD",
"content_ids": ["plan_pro"],
"content_type": "product"
}
}]
}event_timeis epoch seconds (not milliseconds).- If the CAPI access token is unset, the call silently no-ops — 0 server events, no throw. This is the #1 pitfall. An
if (!token) returnguard makes it worse: the code runs, the guard takes the empty branch, nothing is sent. - Always add
client_ip_address+client_user_agentserver-side — they materially improve match rate and are only available on the server.
Do NOT gate CAPI on a click id
Fire the server event on hashed-email match (em), not on the presence of fbclid/fbc. If you only fire when a Facebook click id is present, every organic/direct/email/SEO purchase never reports — which is most of them for many apps.
- Include
fbc/fbclidonly when present (it sharpens attribution for ad-driven purchases) but never make it a requirement for firing. fbclidfrom the landing-page URL survives via Meta's own_fbccookie (the Pixel writes it), so read_fbcserver-side rather than trying to thread the rawfbclidthrough your whole checkout.
Match quality (advanced matching)
- Advanced matching — hashed email
emandexternal_id(your stable user id, hashed) — is what lets Meta attribute a server event to a real person. Send whatever you have; more identifiers = higher match quality score in Events Manager. - Hash
em/external_idwith SHA-256 after lowercasing and trimming; never send raw PII. content_ids+content_typeoncustom_dataimprove catalog/dynamic-ads attribution.
App-capability pitfalls (creating ads via the API)
- Uploading ad images (
POST /act_{ad-account-id}/adimages) and creating ads can 400 with "(#3) Application does not have the capability" until your app has Advanced Access forads_management— or you run the calls as a user who has a role on the ad account (Standard/dev-mode access only covers app-role users). Request Advanced Access in the App Review flow, or test as an app-role user first. - A promotable Facebook Page must be attached to the ad account — ad creation fails without one.
- Escape hatch — use the official hosted ads MCP. A self-built app on the Limited Marketing API tier keeps hitting
(#3)on campaign/ad create, and getting Advanced Access requires App Review + Business Verification (days, frequently stalls). Meta's official hosted ads MCP endpoint uses standard Business-account OAuth and bypasses the app-review/capability gate entirely — you create and manage campaigns without owning a reviewed app. If you're blocked on(#3), stop fighting App Review and drive the official MCP instead. BUT in Claude Code CLI the official MCP's OAuth is broken — see the next section; use a token-based MCP there.
Meta Ads MCP in Claude Code — token auth, not OAuth
The official hosted MCP (https://mcp.facebook.com/ads) authenticates fine from claude.ai web and Claude Desktop but fails from the Claude Code CLI. The CLI uses Dynamic Client Registration (RFC 7591) with a localhost loopback redirect (http://localhost:<port>/callback); Meta's OAuth client only whitelists the fixed claude.ai / Desktop redirect URIs. The handshake dies before login with "URL Blocked … redirect URI is not whitelisted" (a.k.a. redirect_uris are not registered for this client). It is server-side (Meta's app config) — no CLI flag fixes it. Confirmed open in many claude-code issues.
Fix for the CLI: run a token-based MCP that talks straight to the Graph API — no OAuth redirect, so no whitelist to fail. pipeboard-co/meta-ads-mcp reads META_ACCESS_TOKEN with highest precedence and, when set, bypasses Pipeboard's proxy and hits Meta directly (verify: auth.py checks the env var first). byadsco/meta-ads-mcp (Node, npx @byadsco/meta-ads-mcp --transport stdio) is an equivalent. Global config in ~/.claude.json → applies to every worktree; use an absolute interpreter path (Claude Code gives spawned MCP servers a minimal PATH):
"meta-ads": {
"type": "stdio",
"command": "/opt/homebrew/bin/pipx",
"args": ["run", "meta-ads-mcp"],
"env": { "META_ACCESS_TOKEN": "${META_ACCESS_TOKEN}" }
}${META_ACCESS_TOKEN} expands from Claude Code's own process env at MCP launch — so export it in ~/.zshrc and fully restart Claude Code (a running session won't see a zshrc edit). Never hardcode a work-account token into ~/.claude.json if you can export it instead.
Mint a non-expiring System User token (Business Settings clickpath)
A System User token never expires and is the right credential for a headless MCP. Meta gates it behind a three-layer chain — each is a prerequisite for the next, and the token-generation wizard blocks at layer 1 with "No permissions available — Assign an app role to the system user" if you skip it:
- App role on the system user. Business Settings → Accounts → Apps → your app → Assign people → check the system user → toggle Manage app (Full control) → Assign. (The picker lists system users alongside people. Assigning yourself to the app does nothing for the system user — this is the common trap.) This is what unlocks the token wizard at all.
- Token scopes. Back on Users → System users → select the system user → Generate token → pick the app → expiration Never → Assign permissions: check
ads_read+ads_management(+business_managementfor account-level). → Generate token. Meta then demands an SMS 2FA code to the account phone before it mints the token — a human must enter it; this step can't be automated. Copy the token immediately (shown once). - Ad-account assignment. Accounts → Ad accounts → the account → Assign people → check the system user → Manage ad accounts (Full access) → Assign. Without this,
me/adaccountsreturns{"data":[]}— the token generates fine but every ads call sees no account.
account_id visibility is layer 3, not layer 2 — a valid token that returns an empty adaccounts list means the ad account isn't assigned yet, not that the token is bad.
Verify the token end-to-end (Graph, before trusting the MCP)
GET /v21.0/me?fields=id,name → {"id":"…","name":"<system user name>"} (token valid)
GET /v21.0/me/adaccounts?fields=name,account_id,account_status,currency
→ data[] populated with account_status:1 (layer 3 done)If me works but adaccounts is [], go back and do layer 3. Store the token in ~/.zshrc (for the MCP) and any app's gitignored .env.local (as a labelled stash) — never commit it.
Campaign + audience setup (lookalike, small budget)
- Lookalike: create a custom audience seeded off your highest-value users, then a 1%-of-country lookalike from it. Set
targeting_automation.advantage_audience = 0to keep it a hard lookalike — otherwise Meta quietly broadens delivery beyond the lookalike. - Budget hard-stop: a campaign-level
spend_cap(with CBO) is a native hard stop — no external budget-reaper cron needed. Two gotchas: (1) you can't lowerspend_capbelow already-pending charges (the error quotes the current floor, often a few dollars above your target); (2) editingspend_cap/ budget / targeting auto-pauses the campaign/ad set — you must re-activate it after any such edit. - Creatives are immutable. To swap an ad's image/copy you create a new creative + new ad, activate it, and pause the old — there is no in-place edit. Do the swap while spend is ~0 to avoid losing a read.
ads_create_adtakes no status arg — it's born PAUSED; activate as a separate call.ads_update_entitycannot delete — it force-pauses (returnsstatus_forced_to_paused). A true delete needs the Ads Manager UI.
Bake tracking + dynamic macros into the creative at create time
A creative's link, url_tags, media, copy, and CTA are immutable — creative-update only changes name/status/labels. To change any of them you create a new creative, which resets the ad's learning phase. So get tracking right up front: put UTMs and dynamic URL macros in url_tags when creating the creative, e.g.
utm_source=meta&utm_medium=paid_social&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{adset.name}}&utm_placement={{placement}}&src={{site_source_name}}Meta expands the {{...}} macros on every click — auto-tagging each ad and capturing placement (feed / reels / stories), attribution you're otherwise blind to. (This is the tracking counterpart to "creatives are immutable" above: swap the whole creative to fix a bad tag, so don't ship a bad tag.)
Per-surface creative optimization
This applies to all social ad platforms. Make one creative for each placement and build it for that surface. Never use one asset everywhere.
- Reels / Stories: Use full-bleed 9:16 creative. Design for sound-on viewing, a native or UGC feel, and a hook in the first ~1 second.
- Feed: Use 4:5 or 1:1 creative. Make it thumb-stopping but legible with muted playback.
- Right column / Audience Network: Create their own variants with smaller ratios suited to those placements.
- Across all placements: Make the creative feel native, not ad-like. It should read as content, not a banner. Prefer video first.
More API/launch gotchas (each one bites)
LANDING_PAGE_VIEWSoptimization underOUTCOME_TRAFFICrejectspromoted_object{pixel_id}("Promoted Object Invalid") — omitpromoted_objectfor that combo.- CTA
GET_STARTEDis rejected for some Pages →SIGN_UPworks. - The image-upload endpoint may be un-rolled-out for an account → skip it and pass
image_urlto creative-create; Meta server-fetches the image. - Payment method must be on the AD ACCOUNT, not just the business portfolio — otherwise delivery fails with "No Payment Method" (subcode 1359188) even though a card is "on the account" at the portfolio level.
location_typesis deprecated (2026) — the geo "unpublished edits" red herring. Specifyinghome/recent/traveling_iningeo_locations.location_typestrips a soft draft-validation error (Meta code#1870194, surfaced as "Unpublished edits" when you open the ad-set editor). It is NOT delivery-blocking — the errors endpoint returns empty and the ad set keeps serving; the editor just spawns a draft that re-flags it. Fix: setgeo_locationswithcountriesonly and OMITlocation_types(Meta applies its current single default). Partial values like["home","recent"]don't clear it —recentis also a removed option.
Custom Audience → Lookalike (seeding from your own users)
To target people similar to your users, upload a Custom Audience of hashed emails, then build a Lookalike from it:
- Custom Audience:
customer_file_source = USER_PROVIDED_ONLY, schemaEMAIL_SHA256, members = emails normalized (trim + lowercase) then SHA-256 hex. - Lookalike:
subtype = LOOKALIKE,origin_audience_id = <the custom audience>, and alookalike_specwith country + ratio (0.01= top 1%, the closest match). - A lookalike needs ≥100 matched users in the seed to serve. After a ~50-70% match rate, a raw seed near 100 fails the size floor — size the seed above it. Catch the under-size rejection per-segment; don't let one small seed abort a multi-segment run. Seed-sizing strategy and the PII-export authorization boundary are in
ad-experiments.
A "Purchase on free signup" is usually a console setting, not your code
Before hunting for a stray fbq('track','Purchase'): a real CAPI Purchase only fires on a confirmed paid charge. A Purchase that misfires on a free signup almost always comes from Meta's Automatic Events / Advanced Matching setting (Events Manager → dataset → Settings) synthesizing a Purchase from price text on the page — not from your code. Check that console toggle first; turning off automatic-event detection stops the phantom Purchase with no code change.
Detecting delivery-blocking errors (don't trust the entity read)
The standard ad-entity read returns effective_status (e.g. ACTIVE) plus the targeting object but does NOT surface review/validation warnings — an ad set can read ACTIVE + valid targeting while the UI shows a publish/review error. To catch real blockers, query the dedicated errors endpoint (ads_get_errors / the entity's issues_info / recommendations), not just the entity fields. Poll it in any delivery monitor. An empty errors response = no real blocker — e.g. the location_types draft-validation nag above reads as an editor warning but never appears here.
Verification (server-side truth, not "the pixel is on the page")
GET /{pixel-id}?fields=last_fired_time— confirms the pixel/dataset fired anything recently.GET /{pixel-id}/stats?aggregation=event— counts by event type, and includes CAPI server events. This is authoritative. If you see onlyPageViewand noPurchase, the purchase event isn't firing — regardless of what the browser looks like.- Prefer these over the Events Manager UI's "Test Events" tab when you need a durable count rather than a live poke.
Browser caveat
Some automation/headless browsers (and privacy tooling) block fbevents.js, so the Pixel looks dead in your test tooling while working fine in real browsers. Don't conclude the Pixel is broken from a headless run — always cross-check server-side via /stats.
Small-budget campaign setup (cross-platform)
- On a small test budget with no conversion history, don't pick a conversion-optimized objective yet — Meta's delivery has a learning phase that needs a steady flow of conversions to optimize, which a small budget won't produce, so it never learns. Start with a traffic/click objective to fill the funnel, and move to conversion optimization once real conversions accumulate. (Same trap as Google Smart Bidding's learning phase.)
- Run one narrow audience × geo × creative per experiment, prove the cheapest conversion (free signup) first, and judge results on server-side truth (
/stats+ payment provider), not the dashboard. See thead-experimentsskill for the full methodology.
Cross-cutting lessons (the ones that actually bite)
- Timing: a Purchase count of 0 over a window that predates the tracking deploy is expected, not a bug. Check the deploy date before debugging — there are no events from before the Pixel existed.
- Build-scoped env: if the pixel id / CAPI token are baked into a generated module at build time (common on serverless/edge), setting them in your dashboard does nothing until the next deploy. Redeploy after adding — match wherever your other working analytics secrets are imported from rather than assuming a runtime
process.envread works. - Ground truth: cross-check Meta's server-side event counts (
/stats) against your payment provider's actual succeeded-charge count. Real succeeded charges > 0 with Meta Purchase events = 0 means tracking is broken, full stop — the payment provider is the source of truth, the Pixel/CAPI is the thing under test. - Silent failure is the norm: these integrations fail by sending nothing (an early return on a missing access token, a click-id gate that never matches organic traffic), not by throwing. Verify with server-side truth —
/stats,last_fired_time, the payment provider — never "I saw fbq load in the browser."
Common pitfalls
- CAPI access token unset → server events silently no-op (0 events, no error).
- Gating CAPI on
fbclid/fbc→ organic and direct purchases never report; fire on hashedeminstead, addfbconly when present. - Mismatched dedup key casing — client
eventIDvs serverevent_id, same value. event_timein milliseconds instead of seconds.- Sending raw (unhashed) email or user id in
user_data— always SHA-256, lowercased + trimmed. - Concluding the Pixel is dead from a headless/automation browser that blocks
fbevents.js— cross-check/statsserver-side. (#3) capability400s on/adimagesor ad creation because the app lacks Advanced Access forads_management, or no promotable Page is attached.- Trusting
effective_status: ACTIVEfrom the entity read — it hides review/validation warnings; poll the errors endpoint (ads_get_errors/issues_info/recommendations) for real blockers. location_types: [home/recent/...]→#1870194"Unpublished edits" draft nag (deprecated in 2026, not delivery-blocking); setgeo_locations.countriesonly and omitlocation_types.- Editing a creative's link /
url_tags/ media / copy / CTA in place — those fields are immutable (update only touches name/status/labels); you must make a new creative, which resets learning. Bake UTMs +{{...}}macros intourl_tagsat create.
Security — the Pixel is the official first-party vendor script
https://connect.facebook.net/en_US/fbevents.js is Meta's own first-party Pixel bootstrap — the standard, required loader every Meta advertiser embeds, not arbitrary third-party code. Load it only from the official connect.facebook.net origin over HTTPS (never a mirror or CDN copy). The CAPI access token stays server-side in an env var — no secret is placed in the client snippet.
Hub conventions and official references
Use the shared conversion-hub contract: emit one canonical event, use a stable
event_id, send the event after the payment provider confirms the charge, and
make an absent META_PIXEL_ID or META_CAPI_TOKEN a logged no-op. Keep the
platform adapter product-agnostic. See ad-conversion-hub and ad-experiments
for canonical events, consent, hashing, seed sizing, and ground-truth checks.
Official references checked 2026-08-11:
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

