Meta Capi logo

Meta Capi

Organization
cognyai
meta-capi

Meta Conversions API (CAPI) Setup Reference — architecture, event types, customer information hashing, deduplication, implementation examples, AEM, and testing

Overview

Publishercognyai
Repositoryclaude-code-marketing-skills
Skill namemeta-capi
Stars
111
Forks
15
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by cognyai on GitHub. Read the source before you install it.

Installation

Install the Meta Capi AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/cognyai/claude-code-marketing-skills/tree/main/skills/meta-capi
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/cognyai/claude-code-marketing-skills.git /tmp/claude-code-marketing-skills
mkdir -p .claude/skills
cp -r /tmp/claude-code-marketing-skills/skills/meta-capi .claude/skills/meta-capi
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Meta Capi in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Meta Capi on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Meta Capi is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Meta Conversions API (CAPI) Setup Reference

Complete technical reference for Meta Conversions API: architecture, all standard event types with parameters, customer information hashing, implementation methods, event deduplication, testing, and Aggregated Event Measurement.

Full docs: https://cogny.com/docs/meta-conversions-api

Usage

/meta-capi                          # Full CAPI overview
/meta-capi deduplication            # Event dedup strategy
/meta-capi purchase event           # Purchase event parameters
/meta-capi emq                      # Improve Event Match Quality
/meta-capi aem                      # Aggregated Event Measurement
/meta-capi node.js                  # Node.js implementation example
/meta-capi gtm server-side          # GTM SS container setup

Instructions

You are a Meta Conversions API expert. Use this reference to help users implement CAPI correctly, debug event tracking issues, improve Event Match Quality, configure deduplication, and understand Aggregated Event Measurement.

When the user asks a question, find the relevant section below and provide precise, actionable answers with ready-to-use code examples.

If the user provides a specific topic as an argument, focus on that area. Otherwise, provide an overview of the CAPI architecture and key implementation steps.

If Cogny MCP tools are available, use them to inspect the user's actual Pixel configuration, ad account setup, and campaign data to provide contextual recommendations.

Works with

Works with zero accounts (reference and code). When connected:

JobPrimaryEnhanced when connected
Which pixel to send toMeta tool_list_ad_accounts → tool_get_pixels—
Is the browser Pixel already in GTM (and does it set event_id)?—GTM tool_search_tags (search_term: "Meta" / "Facebook")
CAPI coverage: Meta purchases vs real ordersMeta tool_get_insightsShopify tool_list_orders, WooCommerce get_sales_report
Same server-side pattern on other platforms—TikTok, Snapchat, Reddit, LinkedIn, X (see "Other Platforms' Server-Side APIs")

tool_get_pixels returns source: ad_account or business_manager; only the first is assigned to the account. CAPI to a Business-only pixel won't feed this account's ads.


Architecture: Browser Pixel vs Server-Side CAPI

                         User's Browser
                        +------------------------------+
                        |  Meta Pixel (fbevents.js)     |
                        |  - Fires on page interaction  |
                        |  - Sets _fbp / _fbc cookies   |
                        |  - Sends event_id for dedup   |
                        +----------+-------------------+
                                   |  HTTPS (browser -> Meta)
                                   v
                        +------------------------------+
                        |       Meta Servers            |
                        |  - Receives Pixel events      |
                        |  - Receives CAPI events       |
                        |  - Deduplicates via event_id  |
                        |  - Matches users (EMQ)        |
                        |  - Feeds ad optimization      |
                        +------------------------------+
                                   ^
                                   |  HTTPS (server -> Meta)
                        +----------+-------------------+
                        |  Your Server / GTM SS         |
                        |  - Conversions API endpoint   |
                        |  - POST /{ver}/{pixel_id}/    |
                        |    events                     |
                        |  - Hashes PII before sending  |
                        |  - Sends same event_id        |
                        +------------------------------+

Why both matter:

  • Pixel only: Subject to ad blockers (15-30% signal loss), ITP cookie expiry (7-day cap on Safari), and network failures.
  • CAPI only: Misses real-time browser interactions and cannot set first-party cookies.
  • Pixel + CAPI (recommended): Redundant data paths with deduplication. Recovers 10-25% of lost conversions.

Standard Events

Purchase

Fired when a transaction is completed.

ParameterTypeRequiredDescription
valuefloatYesTotal transaction value
currencystringYesISO 4217 code (e.g., USD, EUR)
content_idsarrayRecommendedProduct IDs from catalog
content_typestringRecommendedproduct or product_group
contentsarrayRecommendedArray of {id, quantity, item_price}
content_namestringOptionalProduct or page name
content_categorystringOptionalProduct category
num_itemsintegerOptionalNumber of items
order_idstringOptionalInternal order ID

AddToCart

ParameterTypeRequiredDescription
valuefloatRecommendedItem value
currencystringRecommendedISO 4217 code
content_idsarrayRecommendedProduct IDs
content_typestringRecommendedproduct or product_group
contentsarrayRecommended{id, quantity, item_price}
content_namestringOptionalProduct name
content_categorystringOptionalProduct category

InitiateCheckout

ParameterTypeRequiredDescription
valuefloatRecommendedCart value
currencystringRecommendedISO 4217 code
content_idsarrayRecommendedProduct IDs in cart
content_typestringRecommendedproduct or product_group
contentsarrayRecommended{id, quantity, item_price}
num_itemsintegerOptionalNumber of items

CompleteRegistration

ParameterTypeRequiredDescription
valuefloatOptionalRegistration value
currencystringOptionalISO 4217 code
content_namestringOptionalForm or page name
statusstringOptionalRegistration status

Lead

ParameterTypeRequiredDescription
valuefloatOptionalEstimated lead value
currencystringOptionalISO 4217 code
content_namestringOptionalLead form name
content_categorystringOptionalLead category

ViewContent

ParameterTypeRequiredDescription
valuefloatRecommendedContent value
currencystringRecommendedISO 4217 code
content_idsarrayRecommendedContent/product IDs
content_typestringRecommendedproduct or product_group
content_namestringOptionalContent name
content_categorystringOptionalContent category

Search

ParameterTypeRequiredDescription
search_stringstringRecommendedThe search query
valuefloatOptionalAssigned value
currencystringOptionalISO 4217 code
content_idsarrayOptionalResult IDs
content_categorystringOptionalResult category

AddPaymentInfo

ParameterTypeRequiredDescription
valuefloatOptionalCart value
currencystringOptionalISO 4217 code
content_idsarrayOptionalProduct IDs
content_typestringOptionalproduct or product_group
content_categorystringOptionalPayment method category

AddToWishlist

ParameterTypeRequiredDescription
valuefloatOptionalItem value
currencystringOptionalISO 4217 code
content_idsarrayOptionalProduct IDs
content_namestringOptionalProduct name
content_categorystringOptionalProduct category

Contact

Fired when a user initiates contact (phone, SMS, email, chat). No required or recommended parameters beyond customer information.

CustomizeProduct

ParameterTypeRequiredDescription
content_idsarrayOptionalProduct IDs
content_typestringOptionalproduct or product_group
content_namestringOptionalProduct name

Donate

ParameterTypeRequiredDescription
valuefloatRecommendedDonation amount
currencystringRecommendedISO 4217 code

FindLocation

ParameterTypeRequiredDescription
content_namestringOptionalLocation name or query
content_categorystringOptionalLocation type

Schedule

ParameterTypeRequiredDescription
content_namestringOptionalAppointment type
content_categorystringOptionalService category

StartTrial

ParameterTypeRequiredDescription
valuefloatRecommendedPredicted trial value
currencystringRecommendedISO 4217 code
content_namestringOptionalTrial plan name

SubmitApplication

ParameterTypeRequiredDescription
content_namestringOptionalApplication type
content_categorystringOptionalApplication category

Subscribe

ParameterTypeRequiredDescription
valuefloatYesSubscription value
currencystringYesISO 4217 code
content_namestringOptionalPlan name

Custom Events

Custom events cover actions not mapped to standard events. Used for audience building and custom conversions but cannot power standard optimization objectives.

Naming rules:

  • Max 50 characters (a string; Meta's own example is ShareDiscount)
  • Use the exact same name, including case, in the Pixel (fbq('trackCustom', ...)) and the CAPI event_name, or the two won't deduplicate. Pick one convention (e.g. snake_case)
  • Must not use reserved names (standard event names, fb_, _fb prefixes)
  • Examples: qualified_lead, demo_booked, pricing_page_scroll_50

Customer Information Parameters

Customer info parameters enable Meta to match events to user profiles. Higher match quality improves ad optimization.

Available Parameters

ParameterKeyFormat Before Hashing
EmailemLowercase, trim whitespace
PhonephDigits only with country code (e.g., 14155551234)
First NamefnLowercase, trim, no punctuation
Last NamelnLowercase, trim, no punctuation
CityctLowercase, trim, no punctuation, no spaces
Statest2-letter abbreviation, lowercase (e.g., ca)
Zip CodezpTrim. US: 5-digit only
Countrycountry2-letter ISO 3166-1 alpha-2, lowercase (e.g., us)
Date of BirthdbYYYYMMDD format
GendergeSingle letter: m or f
External IDexternal_idAny string. Hash recommended but not required

Hashing Requirements

The PII parameters in the table above (em, ph, fn, ln, ct, st, zp, country, db, ge) must be SHA-256 hashed before sending via CAPI; external_id is hash-recommended. The Pixel hashes automatically; CAPI does not.

Never hash: client_ip_address, client_user_agent, fbp, fbc (also subscription_id, lead_id, fb_login_id, anon_id). Send them raw; hashing them breaks matching.

Procedure: Normalize (lowercase, trim) -> SHA-256 -> lowercase hex string (64 chars)

javascript
// Node.js
const crypto = require('crypto');
function hashForMeta(value) {
  if (!value) return null;
  return crypto.createHash('sha256')
    .update(value.toString().trim().toLowerCase())
    .digest('hex');
}
python
# Python
import hashlib
def hash_for_meta(value):
    if not value:
        return None
    return hashlib.sha256(str(value).strip().lower().encode('utf-8')).hexdigest()

Common mistakes:

  • Hashing before normalizing (uppercase in input)
  • Double-hashing an already-hashed value
  • Including whitespace in hash input
  • Missing country code on phone numbers
  • Using MD5 instead of SHA-256

Event Match Quality (EMQ)

EMQ is a 1-10 score indicating how well Meta matched an event to a user profile.

EMQ ScoreQualityImpact
1-3PoorMost events unmatched
4-5FairPartial matching
6-7GoodStrong matching
8-10ExcellentFull optimization potential

How to improve EMQ:

  1. Send em (email) with every event -- single biggest impact
  2. Add ph (phone) as second identifier
  3. Include fn + ln to disambiguate common emails
  4. Pass external_id for cross-device matching
  5. Forward fbp and fbc cookies from browser to server
  6. Ensure correct normalization and hashing

Implementation Methods

Direct API Integration

Endpoint: POST https://graph.facebook.com/{API_VERSION}/{pixel_id}/events

API version: use the current Graph/Marketing API version from the changelog (v26.0 as of 2026-10). Don't copy an old pinned version from a tutorial: Marketing API versions expire and calls to them fail. Keep it in one constant and bump it when Meta deprecates it.

Auth: access_token query parameter (System User token with ads_management permission)

Node.js Example
javascript
const crypto = require('crypto');

const PIXEL_ID = 'YOUR_PIXEL_ID';
const ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';
const API_VERSION = 'v26.0'; // current version: developers.facebook.com/docs/graph-api/changelog

function hash(value) {
  if (!value) return undefined;
  return crypto.createHash('sha256')
    .update(value.toString().trim().toLowerCase())
    .digest('hex');
}

async function sendEvent(eventName, eventData, userData, eventId = null) {
  const payload = {
    data: [{
      event_name: eventName,
      event_time: Math.floor(Date.now() / 1000),
      event_id: eventId || crypto.randomUUID(),
      event_source_url: eventData.source_url,
      action_source: 'website',
      user_data: {
        em: hash(userData.email),
        ph: hash(userData.phone),
        fn: hash(userData.firstName),
        ln: hash(userData.lastName),
        ct: hash(userData.city),
        st: hash(userData.state),
        zp: hash(userData.zipCode),
        country: hash(userData.country),
        external_id: hash(userData.externalId),
        client_ip_address: userData.ipAddress,
        client_user_agent: userData.userAgent,
        fbp: userData.fbp,   // raw cookie value, not hashed
        fbc: userData.fbc,   // raw cookie value, not hashed
      },
      custom_data: eventData.customData || {},
    }],
  };

  const url = `https://graph.facebook.com/${API_VERSION}/${PIXEL_ID}/events?access_token=${ACCESS_TOKEN}`;
  const response = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const err = await response.json();
    throw new Error(`CAPI error: ${JSON.stringify(err)}`);
  }
  return response.json();
}

// Example: Purchase event
await sendEvent('Purchase', {
  source_url: 'https://example.com/checkout/thank-you',
  customData: {
    value: 99.99,
    currency: 'USD',
    content_ids: ['SKU-123', 'SKU-456'],
    content_type: 'product',
    order_id: 'ORDER-789',
    num_items: 2,
  },
}, {
  email: 'john@example.com',
  phone: '14155551234',
  firstName: 'John',
  lastName: 'Doe',
  ipAddress: '203.0.113.50',
  userAgent: 'Mozilla/5.0 ...',
  fbp: 'fb.1.1612345678901.1234567890',
  fbc: 'fb.1.1612345678901.AbCdEfGhIjKl',
  externalId: 'user-12345',
}, 'evt_purchase_abc123');
Python Example
python
import hashlib, time, uuid, requests

PIXEL_ID = 'YOUR_PIXEL_ID'
ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN'
API_VERSION = 'v26.0'  # current version: developers.facebook.com/docs/graph-api/changelog

def hash_value(value):
    if not value:
        return None
    return hashlib.sha256(str(value).strip().lower().encode('utf-8')).hexdigest()

def send_event(event_name, event_data, user_data, event_id=None):
    url = f'https://graph.facebook.com/{API_VERSION}/{PIXEL_ID}/events'
    payload = {
        'data': [{
            'event_name': event_name,
            'event_time': int(time.time()),
            'event_id': event_id or str(uuid.uuid4()),
            'event_source_url': event_data.get('source_url'),
            'action_source': 'website',
            'user_data': {k: v for k, v in {
                'em': hash_value(user_data.get('email')),
                'ph': hash_value(user_data.get('phone')),
                'fn': hash_value(user_data.get('first_name')),
                'ln': hash_value(user_data.get('last_name')),
                'ct': hash_value(user_data.get('city')),
                'st': hash_value(user_data.get('state')),
                'zp': hash_value(user_data.get('zip_code')),
                'country': hash_value(user_data.get('country')),
                'external_id': hash_value(user_data.get('external_id')),
                'client_ip_address': user_data.get('ip_address'),
                'client_user_agent': user_data.get('user_agent'),
                'fbp': user_data.get('fbp'),
                'fbc': user_data.get('fbc'),
            }.items() if v is not None},
            'custom_data': event_data.get('custom_data', {}),
        }],
        'access_token': ACCESS_TOKEN,
    }
    response = requests.post(url, json=payload)
    response.raise_for_status()
    return response.json()

# Example: Purchase event
send_event('Purchase', {
    'source_url': 'https://example.com/checkout/thank-you',
    'custom_data': {
        'value': 99.99,
        'currency': 'USD',
        'content_ids': ['SKU-123'],
        'content_type': 'product',
    },
}, {
    'email': 'john@example.com',
    'phone': '14155551234',
    'first_name': 'John',
    'last_name': 'Doe',
    'ip_address': '203.0.113.50',
    'user_agent': 'Mozilla/5.0 ...',
    'fbp': 'fb.1.1612345678901.1234567890',
    'external_id': 'user-12345',
}, event_id='evt_purchase_abc123')

GTM Server-Side Container

  1. Deploy a GTM server-side container (Cloud Run, AWS, etc.)
  2. Create a Meta Conversions API tag in your server container
  3. Configure:
    • Pixel ID and API Access Token
    • Action Source: website
    • Event Name: Map from incoming event
    • User Data: Map email, phone, etc. from event data
    • Event ID: Must match browser Pixel's eventID for dedup
  4. Set trigger on relevant forwarded events

Key tag fields:

Tag Type:          Meta Conversions API
Pixel ID:          {{Meta Pixel ID}}
API Access Token:  {{Meta CAPI Token}}
Event Name:        {{Event Name}}
Action Source:     website

User Data:
  Email:           {{User Email - Hashed}}
  Phone:           {{User Phone - Hashed}}
  IP Address:      {{Client IP}}  (auto-populated in SS GTM)
  User Agent:      {{Client User Agent}}  (auto-populated)
  FBP:             {{FBP Cookie}}
  FBC:             {{FBC Cookie}}

Event Parameters:
  Event ID:        {{Event ID}}  (must match browser Pixel eventID)
  Event Source URL: {{Page URL}}
  Value:           {{Event Value}}
  Currency:        {{Event Currency}}

Partner Integrations

PlatformMethodNotes
ShopifyNative Meta channel appAuto dedup; standard e-commerce events
WooCommerceFacebook for WooCommerce pluginRequires configuration
BigCommerceNative Meta integrationVia app
MagentoMeta Business ExtensionServer-side events

Event Deduplication

When running Pixel + CAPI, the same conversion can be reported twice. Meta deduplicates using event_id + event_name.

How It Works

  1. Browser Pixel fires with eventID: "evt_abc123" and Purchase
  2. Server sends CAPI with event_id: "evt_abc123" and Purchase
  3. Meta matches on both fields, counts one conversion
  4. If one path fails (ad blocker, server error), the other still delivers

Dedup Pattern

javascript
// Browser: generate event_id, fire Pixel, send to server
const eventId = crypto.randomUUID();

fbq('track', 'Purchase', {
  value: 99.99,
  currency: 'USD',
}, { eventID: eventId });

navigator.sendBeacon('/api/meta-capi', JSON.stringify({
  event_name: 'Purchase',
  event_id: eventId,
  custom_data: { value: 99.99, currency: 'USD' },
}));

// Server: forward to CAPI with same event_id

fbp and fbc Cookies

_fbp (Facebook Browser ID): Set by Pixel on first load. Format: fb.1.{timestamp}.{random}. Persists 90 days. Send raw (not hashed).

_fbc (Facebook Click ID): Set on Meta ad click. Format: fb.1.{timestamp}.{fbclid}. If missing, construct from URL: fb.1.{timestamp_ms}.{fbclid}. Send raw (not hashed).

javascript
// Extract from cookies server-side
const fbp = req.cookies['_fbp'] || null;
const fbc = req.cookies['_fbc'] || null;

// Construct fbc from fbclid if cookie missing
function constructFbc(fbclid) {
  return fbclid ? `fb.1.${Date.now()}.${fbclid}` : null;
}

Common Dedup Failures

ProblemFix
Different event_id on Pixel vs CAPIGenerate in browser, pass to server
event_id missing from PixelAdd { eventID: id } as 4th arg to fbq('track')
event_id missing from CAPIInclude event_id in payload
Different event_name casingUse exact standard names (Purchase, not purchase)
CAPI sent hours laterSend within minutes, not in delayed batches (48h dedup window)

Testing and Validation

Test Events Tool

  1. Events Manager > Your Pixel > Test Events tab
  2. Copy the Test Event Code (e.g., TEST12345)
  3. Add test_event_code to your CAPI payload
  4. Send events -- they appear in real time
  5. Remove test_event_code before production (test events are not processed for ads)
javascript
const payload = {
  data: [{ /* event data */ }],
  test_event_code: 'TEST12345',
};

Event Match Quality Dashboard

Events Manager > Data Sources > Your Pixel > Event Match Quality:

  • Per-event EMQ scores
  • Parameter frequency breakdown
  • Improvement recommendations
  • Trend over time

Common Error Codes

CodeMessageFix
190Invalid OAuth access tokenRegenerate system user token
100Invalid parameterCheck required: event_name, event_time, action_source, user_data
2804003Timestamp too oldevent_time must be within 7 days
2804004Invalid event_timeMust be Unix seconds, not milliseconds
2804001Missing user_dataInclude at least one customer info parameter
368Temporarily blockedRate limiting; use exponential backoff
2804002Invalid action_sourceUse: website, app, phone_call, chat, email, in_store, other
803Permission deniedSystem user needs ads_management permission

Coverage Check Against Real Orders (enhanced when connected)

If Cogny isn't connected, skip this and note what connecting adds.

After CAPI goes live, compare 7 complete days:

  1. Meta: tool_get_insights (ad_account_id, level: account, date_preset: last_7d): purchase actions.
  2. Store: Shopify tool_list_orders (query_filter: "created_at:>=YYYY-MM-DD") or WooCommerce get_sales_report (date_min, date_max).

Meta attributes only ad-driven purchases, so it should be below total orders. Meta above total orders means dedup is failing (event_id mismatch between Pixel and CAPI). A sharp rise in Meta purchases right after launch with flat orders is the same bug. For a full cross-platform table, use /conversion-debug.

Other Platforms' Server-Side APIs

The architecture, hashing (SHA-256, normalised) and event_id dedup above carry over. Check the platform's pixel before building:

PlatformServer-side APIDedup keyRead the pixel with
TikTokEvents APIevent_id (same as Pixel)TikTok_Ads tool_get_pixels (advertiser_id)
SnapchatConversions APIclient_dedup_id / event_idSnapchat_Ads tool_list_pixels (ad_account_id)
RedditConversions APIconversion_idReddit_Ads tool_get_conversion_events (ad_account_id)
LinkedInConversions APIeventId (matches Insight Tag)LinkedIn_Ads tool_get_conversions (ad_account_id)
XConversion APIconversion_idX_Ads tool_get_web_event_tags (account_id)
Google AdsEnhanced conversionstransaction_id / order IDsee /conversion-debug

Only Meta is covered in depth here; for the others, confirm field names in the platform docs with WebFetch before writing code.

Aggregated Event Measurement (AEM)

Meta's protocol for measuring events from iOS 14.5+ users who opted out of tracking via ATT.

Check the account before applying this section. Meta's developer docs still describe an 8-event-per-domain limit with prioritisation and domain verification (developers.facebook.com/documentation/meta-pixel/implementation/marketing-api). Widely reported changes not yet reflected in those docs say Meta removed the AEM tab and manual web-event ranking from Events Manager in many accounts and made domain verification optional for event configuration. Ask the user what their Events Manager shows: no AEM / event-priority screen means skip the ranking steps below. Verifying the domain is still worth doing either way (link-preview control, multi-pixel domains).

Key Facts

  • 8-event limit per domain, ranked by priority
  • 72-hour delay for opted-out user data
  • 1-day click attribution (vs. standard 7-day click / 1-day view)
  • Statistical modeling used to estimate opted-out conversions
  • Requires domain verification in Business Settings

Recommended Event Priority (E-commerce)

PriorityEvent
1 (highest)Purchase
2Subscribe
3StartTrial
4InitiateCheckout
5AddPaymentInfo
6AddToCart
7CompleteRegistration
8 (lowest)ViewContent

Recommended Event Priority (Lead Gen)

PriorityEvent
1 (highest)Purchase
2Lead
3SubmitApplication
4Schedule
5CompleteRegistration
6Contact
7ViewContent
8 (lowest)Search

Domain Verification

  1. Business Settings > Brand Safety > Domains
  2. Add domain, verify via DNS TXT record (recommended), HTML file, or meta tag
  3. Configure 8 events in Events Manager > Aggregated Event Measurement

Impact on Reporting

MetricPre-iOS 14.5With AEM
Attribution window28d click, 7d view7d click, 1d view
Reporting delayReal-timeUp to 72 hours
BreakdownsFullLimited
Conversion countExactModeled for opted-out
Optimization eventsUnlimited8 per domain

Mitigations:

  • Use CAPI to maximize EMQ (partially offsets ATT opt-outs)
  • Prioritize 8 most important events
  • Expect 15-30% iOS conversion underreporting
  • Consider broad targeting strategies

Resources

Frequently asked questions

What does the Meta Capi AI skill do?

Meta Conversions API (CAPI) Setup Reference — architecture, event types, customer information hashing, deduplication, implementation examples, AEM, and testing

Why use Meta Capi on TypingMind?

Because you install it once and use it with any model. Meta Capi is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Meta Capi in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/cognyai/claude-code-marketing-skills/tree/main/skills/meta-capi. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Meta Capi?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Meta Capi?

As many as you like. As long as a model supports skills, you can use Meta Capi with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Meta Capi AI skill free?

It is published on GitHub by cognyai. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇