Meta/Facebook Offline Conversions Guide: CAPI, Enhanced Matching, and Offline Event Uploads
The complete guide to uploading offline conversions to Meta (Facebook/Instagram) using the Conversions API (CAPI). The Upload Offline Conversions App covers event setup, PII hashing, deduplication, iOS 14 impact, and common CAPI errors.
Meta offline conversions — uploading real-world business outcomes like phone calls, booked appointments, and closed deals to your Facebook and Instagram ad campaigns — are handled through Meta’s Conversions API (CAPI). Unlike Google Ads’ GCLID-based system, Meta relies primarily on hashed personally identifiable information (PII) to match offline events to ad clicks.
The Upload Offline Conversions App (TUOCA) supports Meta CAPI as a destination platform, handling PII normalization, SHA-256 hashing, event formatting, deduplication, and automated uploads. This guide covers everything you need to implement Meta offline conversion tracking — from initial setup through advanced optimization.
Understanding Meta’s Conversion Infrastructure
Meta’s conversion tracking ecosystem has evolved significantly. Here’s the current landscape:
Conversions API (CAPI) — The Current Standard
The Conversions API is Meta’s server-to-server event tracking system. It bypasses the browser entirely, sending conversion data directly from your server (or a tool like TUOCA) to Meta’s servers.
Key advantages over the Meta Pixel:
- Not blocked by ad blockers
- Not affected by browser cookie restrictions
- Not dependent on JavaScript execution
- Can send offline events that never happened in a browser
- More reliable data transmission
For offline conversions specifically, CAPI is the only method. The Meta Pixel can’t track events that happen outside of a web browser.
Offline Conversions API — Deprecated
Meta previously offered a separate “Offline Conversions API” with offline event sets. This legacy system has been deprecated in favor of the unified Conversions API. If you see references to “offline event sets” in older documentation, note that this has been replaced by CAPI with action_source: "system_generated".
Event Structure
Every Meta CAPI offline event requires these components:
Required Fields
| Field | Type | Description | Example |
|---|---|---|---|
event_name | String | The type of event | Purchase, Lead, CompleteRegistration |
event_time | Integer | Unix timestamp (seconds) | 1714150200 |
user_data | Object | Hashed PII for matching | See below |
action_source | String | Must be system_generated for offline events | system_generated |
Recommended Fields
| Field | Type | Description |
|---|---|---|
event_id | String | Unique identifier for deduplication |
custom_data.value | Float | Conversion value |
custom_data.currency | String | ISO 4217 currency code |
custom_data.content_name | String | Name of the product/service |
custom_data.order_id | String | Your internal order/job ID |
Event Names
Meta supports both standard and custom event names. For offline conversions, the most relevant standard events are:
| Event Name | Use Case |
|---|---|
Purchase | Completed sale / booked job / revenue collected |
Lead | Qualified lead / booked appointment |
CompleteRegistration | Signed contract / started onboarding |
Contact | Phone call / form submission |
Subscribe | Recurring service signup |
StartTrial | Free trial / initial consultation |
Custom events (e.g., BookedJob, CompletedInstallation) are also supported but may have limited optimization support in Meta’s ad delivery algorithms. Standard events are preferred when they match your use case.
The 7-Day Window
Unlike Google Ads’ 90-day GCLID window, Meta requires events to be uploaded within 7 days of the event occurring. The event_time field determines the event timestamp.
Critical implication: For service businesses with long sales cycles, you may need to upload intermediate conversion events (e.g., “Lead” when the appointment is booked) in addition to final conversion events (e.g., “Purchase” when the job is completed and paid).
TUOCA handles this by running automated relays on daily or hourly schedules, ensuring events are uploaded well within the 7-day window.
PII Hashing Requirements
Meta matches offline events to ad interactions using hashed PII. All PII must be SHA-256 hashed before sending. Sending unhashed PII will result in rejected events and potential privacy violations.
Supported User Data Fields
| Parameter | Field Name | Normalization | Example (Before) | Example (After Hash) |
|---|---|---|---|---|
em | Lowercase, trim | John.Doe@Gmail.COM | a8b14... (SHA-256) | |
| Phone | ph | E.164 format, remove non-digits | (555) 123-4567 | +15551234567 → d4f5e... |
| First name | fn | Lowercase, trim | John | a8cfcd... |
| Last name | ln | Lowercase, trim | Doe | 0679a... |
| City | ct | Lowercase, trim, no spaces | New York | newyork → ceb33... |
| State | st | Lowercase 2-letter | NY | ny → 0235c... |
| Zip code | zp | First 5 digits only (US) | 10001-1234 | 10001 → a9334... |
| Country | country | ISO 2-letter lowercase | US | us → 9b202... |
Normalization Rules (Critical)
Before hashing, you must normalize PII exactly as Meta expects:
- Email: Convert to lowercase. Trim leading/trailing whitespace. Do NOT remove dots from the local part (unlike Google’s recommendation for Gmail addresses).
- Phone: Remove all non-digit characters. Add country code prefix. Must be in E.164 format:
+15551234567 - Names: Convert to lowercase. Trim whitespace. Remove non-letter characters.
- Location: Convert to lowercase. Remove spaces from city names. Use 2-letter state abbreviations. Use first 5 digits of zip code.
Common mistakes:
- Hashing before normalizing (the hash of “John@Email.com” ≠ the hash of “john@email.com”)
- Using MD5 instead of SHA-256
- Sending raw (unhashed) PII
- Not including country code in phone numbers
- Including dots in Gmail addresses (this differs from Google’s normalization)
TUOCA handles all normalization and hashing automatically. For manual hashing, use our SHA-256 Hasher tool.
Deduplication
Meta uses a combination of event_id and event_name for deduplication within a 48-hour window.
How It Works
If Meta receives two events with the same event_id AND event_name, it keeps only the first one. This is critical in two scenarios:
Scenario 1: Browser Pixel + CAPI (Redundant Events)
If you’re sending the same event from both the browser (Pixel) and the server (CAPI), use the same event_id on both so Meta deduplicates them. This is called “redundant event setup” and is Meta’s recommended configuration for online events.
Scenario 2: Purely Offline Events
For events that only come from CAPI (like offline conversions from your CRM), each event should have a unique event_id. Use your CRM’s record ID, job number, or another unique identifier.
The action_source Field
For offline conversions, action_source must be set to system_generated. This tells Meta the event didn’t happen in a browser or app — it was generated by a backend system based on offline activity.
Other action_source values (for reference):
website— browser-side events (Pixel)app— mobile app eventsphone_call— telephone conversionsemail— email conversionschat— messaging conversionsphysical_store— in-store conversions
iOS 14.5 / ATT Impact
Apple’s App Tracking Transparency (ATT) framework, introduced in iOS 14.5, significantly impacts Meta’s ability to track and match user activity.
What Changed
- Apple’s prompt asks the person to allow or refuse tracking across apps. Many people refuse. There is no single published opt-out rate.
- Meta’s ability to observe post-click behavior on iOS devices is drastically reduced
- The Meta Pixel fires less reliably on iOS Safari
- Attribution windows were shortened (from 28 days to 7 days for many events)
Impact on Offline Conversions
Offline conversions uploaded via CAPI are less directly affected than online events because:
- Matching is done server-side based on first-party data (hashed PII), not cookies or device identifiers
- The conversion event is sent directly to Meta’s servers, bypassing browser restrictions
- First-party data you collect (email, phone from forms or calls) is unaffected by ATT
However, overall match rates may be lower because:
- Meta’s user identification pool is smaller post-ATT
- Cross-device matching is less reliable
- Some users who opted out may not be matchable even with correct PII
Optimization Strategies
- Send multiple PII fields — Email + phone + name + zip gives Meta more matching signals
- Upload events quickly — The 7-day window is even more important post-ATT
- Use standard event names — Better optimization signal for Meta’s algorithms
- Include conversion values — Enables value-based optimization even with smaller matched audiences
Setting Up Meta CAPI for Offline Conversions
Prerequisites
- Meta Business Manager account with admin access
- Meta Pixel created (even for server-side events, CAPI events are associated with a Pixel)
- System User or App for API authentication
- Access Token with
ads_managementandbusiness_managementpermissions
Configuration in TUOCA
- Connect Meta as a destination — OAuth flow or access token input
- Select your Pixel — Choose the Pixel ID to associate events with
- Map event names — Map your source data fields to Meta event parameters
- Configure PII mapping — Specify which source fields contain email, phone, name, etc.
- Set schedule — Daily recommended (to stay within 7-day window)
- Test — Use Meta’s Test Events tool to verify events are received and matched
Verifying Uploads
After uploading events, verify them in Meta Events Manager:
- Go to Events Manager → Select your Pixel
- Click “Test Events” tab during testing
- Click “Overview” tab for production events
- Check “Event Match Quality” — aim for 6.0+ out of 10.0
- Review match rate — percentage of events Meta could match to user profiles
Event Match Quality is Meta’s scoring system (1–10) that indicates how much user data you’re sending and how useful it is for matching. Sending more PII fields improves this score.
Common CAPI Errors
| Error | Cause | Fix |
|---|---|---|
| Invalid event_time | Event older than 7 days, or timestamp in milliseconds instead of seconds | Use Unix seconds, upload within 7 days |
| Duplicate event | Same event_id + event_name sent twice | Ensure unique event_ids for offline events |
| Invalid Pixel ID | Pixel doesn’t exist or isn’t accessible | Verify Pixel ID and permissions |
| Missing user_data | No PII provided for matching | Include at least email or phone |
| Invalid hash format | PII not properly SHA-256 hashed | Normalize first, then SHA-256 hash |
| Permission denied | Access token lacks required permissions | Verify ads_management scope |
| Rate limit | Too many API calls per time period | Batch events, implement backoff |
| Deduplication conflict | event_id reused across different event types | Use unique event_ids per event |
Comparison: Meta vs. Google Ads Offline Conversions
| Feature | Google Ads | Meta CAPI |
|---|---|---|
| Primary matching | GCLID (click ID) | Hashed PII |
| Event window | 90 days (GCLID) / 63 days (ECL) | 7 days |
| PII hashing | SHA-256 (for Enhanced Conversions) | SHA-256 (mandatory) |
| Deduplication | order_id | event_id + event_name |
| Processing delay | 4–6 hours | Near real-time |
| Offline event type | Import (conversion action setting) | system_generated (action_source) |
| MCC support | Yes (cross-account uploads) | Business Manager (cross-Pixel) |
| Value-based bidding | Target ROAS, Max Conversion Value | Value optimization |
Getting Started
- Set up prerequisites — Business Manager, Pixel, System User, Access Token
- Start with your highest-value event — Usually “Purchase” or “Lead”
- Ensure PII collection — Your forms, CRM, or call tracking must capture email and/or phone
- Test with Meta’s Test Events tool — Verify matching before going live
- Automate with TUOCA — Connect your data source and Meta as a destination
- Monitor Event Match Quality — Aim for 6.0+ score by sending multiple PII fields
- Verify in reports — Check Ads Manager for offline event attribution