--- name: meta-ads-capi-monitor description: Meta CAPI health monitoring focused on EMQ optimization, dedup verification, event parity, and the 14 silent configuration mistakes. Programmatic monitoring via Meta Ads MCP with GA4 cross validation. ALWAYS invoke when the user says 'Meta EMQ', 'CAPI health', 'Meta tracking health', 'event match quality', 'Meta dedup', 'CAPI not working', 'Meta conversions dropping', 'check Meta tracking', 'signal quality', or any concern about Meta conversion data quality. model: opus context: fork argument-hint: "[client-name]" allowed-tools: Read, Grep, Glob, Bash, Write, Agent, mcp__meta-ads__get_pixels, mcp__meta-ads__get_insights, mcp__meta-ads__get_account_info, mcp__meta-ads__get_campaigns, mcp__google-analytics__run_report, mcp__google-analytics__get_account_summaries, mcp__google-analytics__get_property_details --- # Meta CAPI Health Monitor Focused monitoring of Meta Conversions API signal quality, Event Match Quality optimization, deduplication health, and silent configuration failures. This skill is NOT about implementation (see meta-ads-tracking for that) or general container health (see sgtm-health-monitor for that). This is about catching the Meta-specific signal quality problems that silently degrade campaign performance. ## When to Run - Monthly as part of client health checks (standard cadence) - When Meta reported conversions drop without a clear campaign change - When CPAs rise without creative fatigue or audience exhaustion - When a client's Stape container or GTM is updated - After any CAPI implementation change (new events, new parameters, migration) - When EMQ is flagged below threshold during a meta-ads-deep-audit - When modeled conversions exceed 30% of total (weak signal indicator) ## Relationship to Other Skills | Skill | What It Covers | How This Skill Differs | |---|---|---| | sgtm-health-monitor | Container uptime, error rates, CPU/memory, event flow for ALL platforms, token expiry, click ID persistence | This skill focuses exclusively on Meta signal quality: EMQ scores, Meta-specific dedup, CAPI parameter coverage, and Meta-specific configuration mistakes | | meta-ads-tracking | Implementation reference for Pixel, CAPI, Advanced Matching setup | This skill monitors ongoing health of an existing implementation, not how to build one | | meta-ads-deep-audit | Comprehensive Meta account audit including CAPI as one of 24 categories | This skill goes deeper on CAPI alone: parameter-by-parameter EMQ analysis, dedup forensics, and the full 14-mistake checklist | ## MCP Tool Strategy **Meta Ads MCP (primary):** - `mcp__meta-ads__get_pixels`: Pixel configuration, CAPI status, connected datasets, event list - `mcp__meta-ads__get_insights`: Action breakdown to verify conversion event volumes match expectations - `mcp__meta-ads__get_account_info`: Account configuration baseline - `mcp__meta-ads__get_campaigns`: Campaign optimization events to map which events feed bidding **GA4 MCP (cross validation):** - `mcp__google-analytics__run_report`: Event volumes in GA4 for parity comparison against Meta event counts **Direct API: Meta Graph API (via scripts/meta-api.js)** For EMQ and pixel stats not covered by Pipeboard MCP. Run via Bash tool: - `node scripts/meta-api.js emq-scores --dataset-id {pixel_id}`: Per event EMQ scores, match key feedback, event coverage, data freshness - `node scripts/meta-api.js pixel-stats --pixel-id {id}`: Pixel event volume by type and source - `node scripts/meta-api.js pixel-stats --pixel-id {id} --aggregation event_source`: Server vs browser event breakdown **Chrome browser (fallback for visual inspection only):** - Meta Events Manager: Parameter coverage visual inspection, event source breakdown detail - Stape dashboard: Container request logs, event forwarding status - GTM server container: Tag configuration, event_id generation logic ## Instructions ### Step 1: Load Client Context Read `clients/{client-name}/` for profile, tracking config, and history. Check for: - Pixel ID - CAPI implementation type (Stape sGTM, CAPIG, direct API, third party app) - Stape container ID and URL (if applicable) - Known tracking issues from previous sessions - Previous EMQ scores (for trend comparison) If no tracking-config.json exists, create one during this audit. ### Step 2: Pixel and CAPI Connection Status ``` mcp__meta-ads__get_pixels ``` Verify: | Check | Healthy | Flag | |---|---|---| | Pixel status | Active, receiving events | Inactive or no recent events | | CAPI connection | Connected, events flowing | Disconnected or no server events | | Domain verification | Verified | Unverified (blocks AEM event prioritization) | | Configured events | All expected standard events present | Missing events that campaigns optimize for | | Last event received | Within last 1 hour | More than 4 hours ago | **Critical:** If campaigns are optimizing for an event (e.g., Purchase) that is not firing or has zero volume, flag as CRITICAL immediately. The algorithm is optimizing blind. ### Step 3: Event Volume Trend Analysis Pull conversion event volumes for two periods: **Last 7 days:** ``` mcp__meta-ads__get_insights at account level Fields: actions (filtered for standard events) Date preset: last_7d ``` **Previous 7 days (comparison):** ``` mcp__meta-ads__get_insights at account level Fields: actions Custom date range: 8-14 days ago ``` Calculate week over week change for each event: | Event | Last 7 Days | Previous 7 Days | Change | Flag If | |---|---|---|---|---| | PageView | X | Y | Z% | >30% decline | | ViewContent | X | Y | Z% | >30% decline | | AddToCart | X | Y | Z% | >30% decline | | InitiateCheckout | X | Y | Z% | >30% decline | | Purchase | X | Y | Z% | >20% decline | | Lead | X | Y | Z% | >20% decline | A sudden decline in event volume without a corresponding decline in website traffic (check GA4) indicates a tracking failure, not a business change. ### Step 4: GA4 Cross Validation Pull GA4 event volumes for the same 7 day period: ``` mcp__google-analytics__run_report Dimensions: eventName Metrics: eventCount Date range: last 7 days ``` Compare Meta event counts against GA4 event counts: | Ratio | Interpretation | |---|---| | Meta events = 80 to 120% of GA4 | Healthy. Small variance expected due to attribution and timing differences. | | Meta events = 50 to 80% of GA4 | Signal loss. Meta is not receiving all events. Investigate CAPI path. | | Meta events < 50% of GA4 | Significant signal loss. CAPI may be down or misconfigured. | | Meta events > 150% of GA4 | Deduplication failure. Events being double counted. | **Note:** Meta and GA4 will never match exactly. Different attribution models, different collection methods. The goal is to confirm they are in the same ballpark and trending in the same direction. ### Step 5: EMQ Assessment (Direct API) Pull EMQ scores programmatically: ``` node scripts/meta-api.js emq-scores --dataset-id {pixel_id} ``` This returns per event EMQ scores (composite_score), match key feedback with coverage percentages, event coverage (CAPI parity), data freshness, and additional conversions reported (acr). For each conversion event, extract: | Data Point | API Field | |---|---| | EMQ score (0 to 10) | `event_match_quality.composite_score` | | Match key coverage | `event_match_quality.match_key_feedback[].coverage.percentage` | | Event coverage (CAPI parity) | `event_coverage.percentage` | | Data freshness | `data_freshness.upload_frequency` | | Additional conversions from CAPI | `acr.percentage` | Also pull pixel event volume stats: ``` node scripts/meta-api.js pixel-stats --pixel-id {id} --aggregation event_source ``` This provides server vs browser event breakdown. If the API returns an error (permission denied or empty response), fall back to Chrome Events Manager navigation for visual EMQ inspection. ### EMQ Targets and Scoring | Event | Target EMQ | Acceptable | Red Flag | Critical | |---|---|---|---|---| | Purchase | 8.8 to 9.3 | 7.5 to 8.7 | 6.0 to 7.4 | Below 6.0 | | AddToCart | 8.0+ | 7.0 to 7.9 | 5.5 to 6.9 | Below 5.5 | | InitiateCheckout | 7.5+ | 6.5 to 7.4 | 5.5 to 6.4 | Below 5.5 | | Lead | 7.5+ | 6.5 to 7.4 | 5.5 to 6.4 | Below 5.5 | | ViewContent | 6.5 to 7.5 | 5.5 to 6.4 | 4.5 to 5.4 | Below 4.5 | | PageView | 6.0 to 7.0 | 5.0 to 5.9 | 4.0 to 4.9 | Below 4.0 | **Impact of EMQ improvement:** Advertisers sending valid hashed email for Purchase events see approximately 59% median increase in additional conversions attributed. ### Step 6: EMQ Parameter Gap Analysis For each event where EMQ is below target, identify which parameters are missing or misconfigured. Parameters are ranked by impact tier: **Tier 1: Highest Impact (up to +4 EMQ points)** | Parameter | Field | Hashing | Notes | |---|---|---|---| | Email | em | SHA-256 after lowercase + trim | Single most impactful parameter. Always prioritize. | | Phone | ph | SHA-256 after digits only + country code | Strong second signal. Include country code. | | Facebook Click ID | fbc | NOT hashed | Comes from _fbc cookie. Must NOT be hashed. Hashing kills it. | **Tier 2: High Impact** | Parameter | Field | Hashing | Notes | |---|---|---|---| | External ID | external_id | Recommended SHA-256 | Your internal user/customer ID. Helps cross-device matching. | | Browser Pixel ID | fbp | NOT hashed | Comes from _fbp cookie. Must NOT be hashed. | **Tier 3: Supporting (incremental when combined)** | Parameter | Field | Hashing | Notes | |---|---|---|---| | First name | fn | SHA-256 after lowercase + trim | | | Last name | ln | SHA-256 after lowercase + trim | | | City | ct | SHA-256 after lowercase + remove spaces | | | State | st | SHA-256 after 2-letter code | | | Zip code | zp | SHA-256 | | | Country | country | SHA-256 after 2-letter code | | | Date of birth | db | SHA-256 after YYYYMMDD format | | | Gender | ge | SHA-256 after m or f | | **Tier 4: Baseline (required, not hashed)** | Parameter | Field | Notes | |---|---|---| | Client IP address | client_ip_address | Required for all CAPI events. NOT hashed. | | Client user agent | client_user_agent | Required for all CAPI events. NOT hashed. | **For each event below target EMQ, produce a specific recommendation:** - Which tier 1/2 parameters are missing - Estimated EMQ improvement from adding them - Technical implementation path (where in the data layer or form does this data live) ### Step 7: Deduplication Health Check Deduplication is the mechanism that prevents the same conversion from being counted twice (once by the browser Pixel, once by the server CAPI). It works by matching `event_name` + `event_id` within a 48 hour window. **What to verify:** 1. **event_id generation:** Both the browser Pixel call and the CAPI server payload must include the same event_id for the same conversion event. Check: - GTM client container: is event_id being set in the dataLayer? - GTM server container: is the same event_id being forwarded to Meta? - Are different tags generating different event_ids for the same event? (Tag sequencing issue) 2. **Dedup symptoms to detect:** - Meta conversion count is approximately 2x GA4 conversion count = dedup failing - ROAS appears inflated (30 to 100% higher than actual) = double counting conversions - CPA appears artificially low = same - Bidding algorithm receives inflated signal = makes worse auction decisions over time 3. **Common dedup failure causes:** - event_id not set at all (most common) - event_id set in browser but not forwarded to server (GTM config issue) - Different event_id generated for browser vs server (code bug) - Third party app sending CAPI events with its own event_id that doesn't match the Pixel - Multiple CAPI paths active simultaneously (e.g., CAPIG + sGTM both sending) **Verification approach:** - Compare Meta total conversions vs GA4 transactions for the same period - If Meta is 1.5x+ GA4 for the same event, investigate dedup - In Chrome, check Events Manager dedup feedback if the field is available ### Step 8: The 14 Silent CAPI Mistakes Checklist Run through each item. These issues do not produce errors. They silently degrade signal quality. | # | Mistake | How to Detect | Fix | |---|---|---|---| | 1 | Using CAPIG + sGTM simultaneously | Check if both Conversions API Gateway AND a server GTM container are sending events for the same pixel. Events Manager will show duplicate sources. | Choose one path. Disable the other. sGTM is preferred for OFM clients. | | 2 | Blocked domains in CAPIG hub | In CAPIG settings, check the domain allowlist/blocklist. Events from blocked domains are silently dropped. | Add all client domains to the allowlist. | | 3 | DNS/CNAME misconfiguration | If using a custom domain for CAPI (e.g., track.clientdomain.com), verify DNS resolves correctly. Cloudflare proxy must be OFF (grey cloud, not orange) for CAPI subdomains. | Fix DNS. Disable Cloudflare proxy for the tracking subdomain. | | 4 | Third party apps sending duplicate data | Check Events Manager event sources. If you see events from "Shopify," "Klaviyo," or other integrations alongside GTM/sGTM events, they may be double sending. | Disable CAPI from the third party app if sGTM handles it. Or disable sGTM for events the app already sends. | | 5 | Test event code expiration | Test event codes in Events Manager change every few hours. Using an expired code shows zero test events even if real events flow fine. | Generate a fresh test event code before each testing session. | | 6 | Tag sequencing causing event_id mismatches | If multiple GTM tags fire for the same conversion and they generate separate event_ids, dedup breaks. | Use a single shared event_id variable in GTM that all tags for the same event reference. | | 7 | Hashing _fbp and _fbc values | These cookie values are already identifiers. Hashing them makes them unmatchable. Check the server container tag config for these fields. | Set fbp and fbc fields to pass through raw, no hashing. | | 8 | event_time outside Meta's 7 day window | CAPI events with event_time older than 7 days are silently rejected. Can happen with delayed batch processing or timezone misconfiguration. | Ensure event_time is set at the moment of the conversion, not batch processed days later. Use UTC timestamps. | | 9 | CORS/CSP errors blocking container | Check the browser console on the client site for CORS or Content Security Policy errors related to the sGTM domain. These silently prevent events from reaching the server. | Update the site's CSP headers to allow the sGTM domain. | | 10 | SSL certificate errors after subdomain creation | When creating a custom tracking domain (sst.clientdomain.com), the SSL certificate must be provisioned and valid. Stape handles this automatically, but it can fail. | Check SSL status in Stape dashboard. Reprovision if expired. | | 11 | CAPIG errors 100.33 and 190.465 | These Meta API errors can persist silently. Check Events Manager diagnostics for error codes. | Remove the pixel from CAPIG and re-add it. This often resolves persistent API errors. | | 12 | Inconsistency between browser and server event parameters | If the Pixel sends content_ids as ["SKU-001"] but CAPI sends content_ids as ["sku-001"] (case difference) or different ID formats, product matching breaks for Dynamic Ads. | Normalize parameter formats between browser and server. Check content_type mapping (product vs product_group). | | 13 | Website updates breaking tracking | CMS updates, theme changes, checkout flow modifications, or new form builders can break dataLayer pushes or event triggers without any notification. | After any site update, run a quick event verification (check GA4 realtime and Events Manager test events). | | 14 | Not enabling "Generate _fbp cookie if not exist" | In Stape's Meta CAPI tag, this setting creates the _fbp cookie for users who have ad blockers preventing the browser Pixel from setting it. Without this, ad-blocked users have no fbp parameter. | Enable this setting in the Stape sGTM Meta CAPI tag configuration. | ### Step 9: Signals Gateway Readiness Assessment Evaluate whether the client should migrate from their current setup to Meta's Signals Gateway: | Factor | Stay on Current Setup | Migrate to Signals Gateway | |---|---|---| | Platforms served | Meta only | Meta + TikTok + Google (multi channel) | | CRM/offline data | Not needed | Need to send CRM stage changes or offline conversions | | Ad blocker impact | Acceptable signal loss | Need maximum signal recovery | | Setup complexity tolerance | Prefer simplest option | Can handle additional configuration | | Monthly event volume | Under 20K/month (free Stape tier) | Over 20K/month (need paid tier anyway) | **Signals Gateway benefits:** - Deploys first party pixel on your domain (less susceptible to ad blockers) - Advertisers using Signals Gateway Pixel + Meta Pixel + CAPI saw 23% CPA reduction - Free tier at 20K events/month via Stape - Multi channel event routing from a single integration point **Recommendation threshold:** If the client runs Meta + at least one other platform (TikTok, Google) via Stape, and their monthly event volume exceeds 20K, Signals Gateway is likely worth the migration. ### Step 10: Modeled vs Observed Conversion Analysis Check the ratio of modeled to observed conversions: ``` mcp__meta-ads__get_insights at campaign level Fields: actions (check for modeled conversion indicators) ``` Also check in Chrome: Ads Manager > Campaign > hover over conversion count > tooltip shows modeled vs observed breakdown. | Ratio | Interpretation | |---|---| | Modeled < 15% of total | Strong signal. Algorithm has good data to work with. | | Modeled 15 to 30% | Acceptable. Some signal gaps but manageable. | | Modeled 30 to 50% | Weak signal. Algorithm is guessing on a large portion. Improve CAPI and EMQ. | | Modeled > 50% | Very weak signal. Campaign optimization is significantly impaired. Urgent CAPI improvement needed. | High modeling percentages often correlate with: missing CAPI, low EMQ, iOS heavy audiences, consent denied traffic, and ad blocker prevalence. ## Output Template ``` ## Meta CAPI Health Report: [Client Name] Date: [DATE] Pixel ID: [PIXEL_ID] CAPI Implementation: [Stape sGTM / CAPIG / Direct / Third Party] ### Signal Quality Summary | Metric | Value | Status | |---|---|---| | CAPI Connection | [Connected/Disconnected] | [OK/CRITICAL] | | Domain Verification | [Verified/Unverified] | [OK/HIGH] | | Server Event Ratio | [X]% of total events | [OK if >75% / WARN if 50-75% / CRITICAL if <50%] | | Dedup Health | [Working/Suspected failure] | [OK/HIGH] | | Modeled Conversion Ratio | [X]% | [OK if <15% / WARN if 15-30% / HIGH if >30%] | ### EMQ Scores by Event | Event | EMQ Score | Target | Status | Missing Parameters | |---|---|---|---|---| | Purchase | [X] | 8.8+ | [OK/WARN/RED/CRITICAL] | [List missing tier 1/2 params] | | AddToCart | [X] | 8.0+ | [OK/WARN/RED/CRITICAL] | [List missing] | | Lead | [X] | 7.5+ | [OK/WARN/RED/CRITICAL] | [List missing] | | ViewContent | [X] | 6.5+ | [OK/WARN/RED/CRITICAL] | [List missing] | | PageView | [X] | 6.0+ | [OK/WARN/RED/CRITICAL] | [List missing] | ### Event Volume Trends (7 Day) | Event | This Week | Last Week | Change | GA4 Parity | |---|---|---|---|---| | Purchase | [X] | [Y] | [Z]% | [X]% of GA4 | | AddToCart | [X] | [Y] | [Z]% | [X]% of GA4 | | Lead | [X] | [Y] | [Z]% | [X]% of GA4 | ### Silent Mistakes Checklist | # | Check | Status | Notes | |---|---|---|---| | 1 | CAPIG + sGTM conflict | [Pass/Fail/N/A] | | | 2 | Blocked domains | [Pass/Fail/N/A] | | | 3 | DNS/CNAME config | [Pass/Fail/N/A] | | | 4 | Third party duplicate | [Pass/Fail/N/A] | | | 5 | Test code freshness | [N/A] | Verified during testing | | 6 | event_id consistency | [Pass/Fail] | | | 7 | fbp/fbc not hashed | [Pass/Fail] | | | 8 | event_time within 7 days | [Pass/Fail] | | | 9 | CORS/CSP errors | [Pass/Fail] | | | 10 | SSL certificate valid | [Pass/Fail/N/A] | | | 11 | CAPIG error codes | [Pass/Fail/N/A] | | | 12 | Parameter consistency | [Pass/Fail] | | | 13 | Recent site updates | [None/Investigated] | | | 14 | _fbp cookie generation | [Enabled/Disabled/N/A] | | ### Priority Actions 1. [CRITICAL items first] 2. [HIGH items] 3. [MEDIUM items] ### Estimated Impact | Action | Estimated EMQ Improvement | Estimated Conversion Recovery | |---|---|---| | [Action 1] | +[X] points on [event] | ~[X]% additional conversions | | [Action 2] | +[X] points on [event] | ~[X]% additional conversions | ### Signals Gateway Recommendation [Recommended/Not recommended at this time] — [Rationale] ### Next Check Scheduled for: [date, typically 30 days out] ``` ## Severity Classification | Level | Criteria | Response | |---|---|---| | CRITICAL | CAPI disconnected, pixel not firing, dedup completely broken, Purchase EMQ below 6.0 | Flag immediately. Stop other work. This is actively damaging campaign performance. | | HIGH | EMQ below target for key conversion events, >30% event volume decline, modeled conversions >30%, parameter coverage gaps in Tier 1 | Flag in current session. Include in audit findings. Recommend fix within 1 week. | | MEDIUM | EMQ marginally below target, minor volume fluctuations, missing Tier 2/3 parameters, Signals Gateway opportunity | Log and include in recommendations. Fix within 2 to 4 weeks. | | LOW | Best practice deviations, missing Tier 3 parameters only, cosmetic config issues | Note for future improvement. Include in monthly review. | ## References - Implementation guide: `.claude/skills/references/meta-ads-tracking/SKILL.md` - Container monitoring: `.claude/skills/sgtm-health-monitor/SKILL.md` - Server-side architecture: `.claude/skills/references/server-side-tracking/SKILL.md` - Deep audit integration: `.claude/skills/meta-ads-deep-audit/SKILL.md` (Category 3 and 4) - Meta CAPI auditor agent: `.claude/agents/meta-capi-auditor.md`