From metaflow-marketing-skills
Implement and validate Meta Pixel + Conversions API (CAPI) for maximum signal quality — the single biggest lever for Meta Ads performance via the Andromeda ranking system.
How this skill is triggered — by the user, by Claude, or both
Slash command
/metaflow-marketing-skills:meta-ads-tracking-setupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Meta's Andromeda deep learning architecture uses signal quality as its primary input for ad delivery optimization. Weak tracking = weak signals = poor delivery = wasted spend. Getting Pixel + CAPI right is foundational — do this before any campaign optimization.
Meta's Andromeda deep learning architecture uses signal quality as its primary input for ad delivery optimization. Weak tracking = weak signals = poor delivery = wasted spend. Getting Pixel + CAPI right is foundational — do this before any campaign optimization.
event_id between Pixel and CAPI to prevent double-countingAsk these questions in order:
Q1: What platform runs the website?
action_source: system_generatedQ2: What's the technical budget?
| Method | Cost | Dev Effort | Best For |
|---|---|---|---|
| Native platform integration (Shopify, WooCommerce plugins) | Free–$50/mo | Low | Ecommerce on supported platforms |
| CAPI Gateway | $10–$400/mo hosting | Low–Medium | Teams wanting managed solution |
| Server-side GTM | $10–$50/mo (GCP) | Medium | Teams already using GTM |
| Manual API implementation | $500–$5K+ dev time | High | Custom platforms, maximum control |
Q3: Are there offline/CRM conversions?
fbc values (see fbclid Capture Workflow below)action_source set to physical_store or system_generated| Dimension | Meta Pixel (Client-Side) | Conversions API (Server-Side) |
|---|---|---|
| How it fires | JavaScript in browser | Server-to-server HTTP POST |
| Blocked by ad blockers | Yes | No |
| Blocked by iOS ATT | Partially | No (server-side) |
| Blocked by cookie restrictions | Yes (3P cookies) | No |
| Data freshness | Real-time | Near real-time (seconds) |
| Data quality control | Limited | Full (you control the payload) |
| Events supported | Web events only | Web + offline + CRM + in-store |
| Required for | Baseline tracking | Signal recovery + offline events |
| Typical signal recovery | Baseline | Recovers 20–30% of events lost to browser restrictions |
Both are required. Pixel alone misses 20-30% of events. CAPI alone misses real-time behavioral signals. Together they give Meta's algorithm the fullest picture.
When both Pixel and CAPI fire for the same event, Meta must know they're the same event to avoid double-counting.
How it works:
event_id on your server or in the browser (UUID or timestamp-based)event_id to both the Pixel event AND the CAPI eventevent_name (e.g., both say Purchase)event_id + event_nameImplementation pattern:
// Browser: Pixel fires with event_id
fbq('track', 'Purchase', {value: 99.99, currency: 'USD'}, {eventID: 'order_abc123'});
// Server: CAPI fires with same event_id
POST to graph.facebook.com with event_id: 'order_abc123'
Validation: In Events Manager, check "Overview" tab → deduplication should show matched events. If CAPI event count far exceeds Pixel, deduplication may be failing.
Event Match Quality (EMQ) measures how well Meta can match your sent events to Meta user profiles. Higher EMQ = better attribution = better ad delivery.
Targets:
Matching keys to send (priority order):
| Key | Parameter | Impact | Notes |
|---|---|---|---|
| Email (hashed) | em | Highest | SHA-256 hash, lowercase, trimmed |
| Phone (hashed) | ph | High | SHA-256 hash, include country code, digits only |
| fbc (click ID) | fbc | High | Captured from fbclid URL parameter — critical for offline conversions |
| fbp (browser ID) | fbp | Medium | Read from _fbp first-party cookie |
| IP address | client_ip_address | Medium | User's IP, not server IP |
| User agent | client_user_agent | Medium | Browser user agent string |
| First name (hashed) | fn | Lower | SHA-256 hash, lowercase |
| Last name (hashed) | ln | Lower | SHA-256 hash, lowercase |
| City (hashed) | ct | Lower | SHA-256 hash, lowercase |
| State (hashed) | st | Lower | SHA-256 hash, lowercase, 2-char code |
| Zip code (hashed) | zp | Lower | SHA-256 hash |
| Country (hashed) | country | Lower | SHA-256 hash, 2-char ISO code |
| Date of birth (hashed) | db | Lower | SHA-256 hash, YYYYMMDD format |
| Gender (hashed) | ge | Lower | SHA-256 hash, 'm' or 'f' |
| External ID (hashed) | external_id | Lower | Your system's user ID, hashed |
Rules:
references/capi-event-parameters.md for full parameter specifications and hashing requirementsFor CRM and offline events sent hours/days/weeks after the ad click, the fbc value is the critical link connecting the downstream conversion to the original ad.
Step-by-step:
?fbclid=xyz in URLfbclid from the URLfbclid alongside the lead record in your CRM/database_fbp cookie valuefbc parameter: fb.1.{timestamp}.{fbclid_value}fbc valueEvery CAPI event requires an action_source telling Meta where the event originated:
| Value | Use When |
|---|---|
website | Event happened on your website (most common for web CAPI) |
app | Event happened in your mobile app |
phone_call | Event was a phone conversion |
chat | Event originated from a messaging conversation |
email | Event resulted from an email campaign |
physical_store | In-store purchase or offline event at a physical location |
system_generated | CRM event, backend event, or any system-triggered conversion |
other | Doesn't fit above categories |
Post-May 2025 migration: If you were using the Offline Conversions API, change your integration to standard CAPI and set action_source to physical_store (for in-store events) or system_generated (for CRM/backend events).
Using Meta Test Events Tool:
event_idCommon validation failures:
| Symptom | Likely Cause | Fix |
|---|---|---|
| CAPI events not appearing | Server not sending, API auth error | Check server logs, verify access token |
| Double-counted events | Missing or mismatched event_id | Ensure same event_id in Pixel and CAPI calls |
| Low EMQ despite sending keys | Hashing errors, wrong format | Verify SHA-256 hashing, check lowercase/trim |
| CAPI events far exceed Pixel | Pixel blocked but no dedup issue | Normal — CAPI recovers blocked events. Verify dedup still works for events both capture |
| Events delayed >7 days | Exceeds acceptance window | Speed up CRM-to-CAPI pipeline. Events must fire within 7 days |
When asked to help with Meta tracking setup, produce this deliverable:
## Meta Tracking Implementation Plan
### Current State Assessment
- Pixel status: [Active/Inactive/Not installed]
- CAPI status: [Active/Inactive/Not configured]
- EMQ score: [X.X / 10]
- Event deduplication: [Working/Not configured/Failing]
- Events tracked: [List of standard and custom events]
- Missing matching keys: [List]
### Implementation Steps
1. [Step with specific technical action]
2. [Step with specific technical action]
...
### Matching Keys Action Plan
| Key | Current Status | Action Required |
|-----|---------------|-----------------|
| em (email) | Sending | None |
| ph (phone) | Not sending | Add to CAPI payload |
...
### Validation Checklist
- [ ] Pixel fires on all conversion pages
- [ ] CAPI fires for all conversion events
- [ ] event_id matches between Pixel and CAPI
- [ ] Deduplication confirmed in Test Events
- [ ] EMQ score ≥ 6.0 (target 8.0+)
- [ ] All available matching keys sending
- [ ] SHA-256 hashing verified (no raw PII)
- [ ] action_source set correctly per event type
- [ ] CRM events firing within 7-day window
- [ ] fbclid capture and storage working
### Expected Impact
- Estimated signal recovery: [X]% of currently lost events
- EMQ improvement: [current] → [projected]
- Timeline to stable data: 7-14 days post-implementation
Input: "We're running Meta ads for a B2B SaaS company. We have the Pixel installed but no CAPI. Our EMQ is 4.2 and we track leads via a CRM. Some leads close 2-3 weeks after the ad click. How do we fix this?"
Output:
event_id for each Lead event. Pass it to both the Pixel fbq('track', 'Lead', {}, {eventID: 'lead_xyz'}) and the server-side CAPI tag.fbclid from landing page URLs. Store it in a hidden form field so your CRM records it on the contact. Also capture the _fbp cookie value.Purchase event (or custom ClosedWon event) with action_source: system_generated, the stored fbc value, hashed email, and hashed phone.| Key | Current Status | Action Required |
|---|---|---|
| em (email) | Not sending via CAPI | Add to CAPI payload, SHA-256 hashed |
| ph (phone) | Not sending | Add to CAPI payload, SHA-256 hashed |
| fbc | Not capturing | Add fbclid capture to landing pages + CRM |
| fbp | Not sending | Read _fbp cookie, pass to server GTM |
| IP | Not sending | Auto-captured by server-side GTM |
| User agent | Not sending | Auto-captured by server-side GTM |
action_source: physical_store or system_generated. Discontinued May 2025.7d_view and 28d_view attribution windows are no longer returned in the Ads Insights API. Update any reporting that pulls these windows.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub narayan-metaflow/metaflow-marketing-skills --plugin metaflow-marketing-skills