How-To Guide 4 min read

How to Upload Offline Conversions to Facebook (Meta) Ads

Last verified: 2026-11-07

Uploading offline conversions to Meta (Facebook/Instagram) requires the Conversions API (CAPI) — Meta’s server-side event tracking endpoint. Unlike Google Ads, which accepts CSV files, Meta requires all offline events to be sent via API.

This guide from The Upload Offline Conversions App (TUOCA) walks through every step, from setup to your first successful event submission.

Prerequisites

  • ✅ Meta Business account
  • ✅ Facebook/Instagram ad campaigns running
  • ✅ Pixel created (required for CAPI access)
  • ✅ Access token generated
  • ✅ Conversion data (leads with email/phone and conversion details)

Step 1: Create a Pixel (If You Don’t Have One)

  1. Go to Meta Events Manager (business.facebook.com/events_manager)
  2. Click Connect Data Sources → Web
  3. Name your pixel
  4. Click Create Pixel
  5. Note the Pixel ID (you’ll need this for API calls)

Step 2: Generate an Access Token

  1. In Events Manager, select your pixel
  2. Click Settings
  3. Scroll to Conversions API
  4. Click Generate Access Token
  5. Copy and securely store the token

Important: This token doesn’t expire automatically, but it’s tied to your user account. If your account permissions change, you may need to regenerate it.

Step 3: Prepare Your Data

Required Fields

FieldAPI NameFormatRequired
Event nameevent_nameString (e.g., “Purchase”)✅ Yes
Event timeevent_timeUnix timestamp✅ Yes
Action sourceaction_sourcesystem_generated (for offline)✅ Yes
Hashed emailuser_data.emSHA-256 of lowercase, trimmed email✅ At least one
Hashed phoneuser_data.phSHA-256 of E.164 phoneRecommended
FieldAPI NameFormatPurpose
fbcuser_data.fbcfb.1.{timestamp}.{fbclid}Click-level matching
Event IDevent_idUnique stringDeduplication
Valuecustom_data.valueNumberRevenue tracking
Currencycustom_data.currencyISO 4217Currency code

Step 4: Normalize and Hash PII

Critical: PII must be normalized THEN hashed with SHA-256. The order matters.

Email

Raw:      "  John.Doe@Gmail.COM  "
Step 1:   "john.doe@gmail.com"       (lowercase, trim)
Step 2:   SHA-256 hash → "e8b6c3..."  (hash)

Phone

Raw:      "(555) 123-4567"
Step 1:   "+15551234567"              (E.164 format)
Step 2:   SHA-256 hash → "d4f5c3..."  (hash)

Use the SHA-256 Hasher and E.164 Formatter tools to verify.

Step 5: Format the API Request

Endpoint

POST https://graph.facebook.com/v26.0/{PIXEL_ID}/events

Request Body

{
  "data": [{
    "event_name": "Purchase",
    "event_time": 1714502400,
    "event_id": "job-2026-04-001",
    "action_source": "system_generated",
    "user_data": {
      "em": ["e8b6c3a4f2d1..."],
      "ph": ["d4f5c3b1e72a..."],
      "fbc": "fb.1.1714000000.IwAR3x7..."
    },
    "custom_data": {
      "value": 4500.00,
      "currency": "USD"
    }
  }],
  "access_token": "YOUR_ACCESS_TOKEN"
}

Key Notes

  • em and ph are arrays — you can send multiple emails/phones per event
  • event_time is a Unix timestamp (seconds, not milliseconds)
  • action_source must be system_generated for offline CRM events
  • fbc is the processed FBCLID (format: fb.1.{timestamp}.{fbclid})

Step 6: Send the Event

Using cURL (Testing)

curl -X POST \
  "https://graph.facebook.com/v26.0/YOUR_PIXEL_ID/events" \
  -H "Content-Type: application/json" \
  -d '{
    "data": [{
      "event_name": "Purchase",
      "event_time": 1714502400,
      "event_id": "test-001",
      "action_source": "system_generated",
      "user_data": {
        "em": ["YOUR_HASHED_EMAIL"]
      },
      "custom_data": {
        "value": 100.00,
        "currency": "USD"
      }
    }],
    "access_token": "YOUR_TOKEN"
  }'

Successful Response

{
  "events_received": 1,
  "messages": [],
  "fbtrace_id": "ABC123..."
}

Step 7: Verify in Events Manager

  1. Go to Events Manager → your pixel
  2. Click Test Events tab
  3. Check that your test event appears
  4. Click the Overview tab to see event counts
  5. Check Event Match Quality — aim for 6+ (out of 10)

The 7-Day Window Challenge

Meta’s event window is only 7 days. For service businesses with longer sales cycles, you need a strategy:

Strategy: Multi-Stage Events

Day 0:  Ad click (FBCLID captured)
Day 1:  Phone call → Send "Contact" event ✅ (within 7 days)
Day 3:  Estimate scheduled → Send "Lead" event ✅ (within 7 days)
Day 14: Job booked → Send "Purchase" ❌ (outside 7 days for FBCLID)
        BUT: Send with hashed email/phone → PII matching still works

Upload the high-funnel event (“Contact”) within 7 days to establish the click-level match. Then send the final revenue event with hashed PII for people-based matching.

Common Errors

ErrorCauseFix
Invalid hash formatPII not properly SHA-256 hashedUse 64-character hex lowercase
Missing user_dataNo matching identifiersInclude at least em or ph
Invalid event_timeTimestamp too old or futureMust be within 7 days, not in the future
Duplicate eventSame event_id sent twiceExpected — Meta silently deduplicates
Permission deniedToken expired or lacks scopeRegenerate access token

How TUOCA Automates Meta Uploads

TUOCA handles the entire CAPI pipeline:

  1. Data extraction — Pulls from CallRail, CRM, or webhooks
  2. PII normalization — Lowercases email, formats phone to E.164
  3. SHA-256 hashing — Hashes all PII per Meta’s requirements
  4. fbc construction — Converts raw FBCLIDs to fbc format
  5. Event formation — Builds the CAPI JSON payload
  6. Batch upload — Sends events to the Conversions API
  7. Deduplication — Generates consistent event_ids
  8. Error handling — Logs and categorizes API errors
  9. EMQ monitoring — Tracks Event Match Quality scores

Next Steps

  1. ✅ Create pixel and generate access token
  2. ✅ Send a test event via cURL
  3. ✅ Verify in Events Manager → Test Events
  4. ✅ Set up TUOCA for automated CAPI uploads
  5. ✅ Monitor Event Match Quality — aim for 6+

Frequently Asked Questions

Meta no longer supports the legacy Offline Events CSV upload. All offline conversions must be sent via the Conversions API (CAPI). This requires formatting data as JSON and sending HTTP POST requests to Meta's Graph API endpoint. TUOCA handles this API integration automatically.

At minimum: event_name, event_time, action_source (set to 'system_generated' for offline), and at least one user_data field (hashed email or phone). For best results, include the fbc parameter (from FBCLID), hashed email, hashed phone, and conversion value.

Low match rates are usually caused by: (1) Not sending enough user data fields — send email AND phone, not just one, (2) Incorrect normalization before hashing — email must be lowercase/trimmed, phone must be E.164, (3) Missing fbc parameter — include when available for click-level matching, (4) Events outside the 7-day window.

Within 7 days of the ad click. Meta's Conversions API has a 7-day event window — the shortest of any major platform. For service businesses with longer sales cycles, upload an intermediate event (like 'Contact' or 'Lead') within 7 days, even if the final conversion hasn't happened yet.

Stop Guessing. Start Proving ROI.

TUOCA connects your CRM and call tracking data directly to your ad platforms. Set up in minutes.