Match Quality

Why your EMQ is stuck at 5 (and how to push it to 8+)

Low EMQ is the silent cause of high CAC. In 2026, brands with EMQ 8+ cut CAC by 15-25% compared to those stuck at 5-6. This is the complete technical checklist to raise Meta CAPI's EMQ without guesswork.

Direct answer

Low EMQ (5 or less) happens because your implementation sends few identity signals to Meta. The 5 main fixes: (1) hash email in SHA-256 lowercase trimmed; (2) normalize phone to E.164 before hashing; (3) propagate click IDs (fbc, fbp); (4) include full PII (name, city, zip, state); (5) ensure IP and User-Agent from the request. Applied right, you go from 5 to 8 in 7-14 days.

What EMQ is and how Meta calculates it

EMQ (Event Match Quality) is a score from 1 to 10 that Meta assigns to each event you send. It measures how well Meta can match the event to a real user on Facebook/Instagram.

The more identifier fields you send, the more likely Meta finds a precise "match". The fields that count most (in order of weight):

  1. Hashed email (em) — very high weight
  2. Hashed phone (ph) — high weight
  3. External ID (external_id) — your CRM ID, medium weight
  4. Click IDs (fbc, fbp) — medium-high weight
  5. Name (fn, ln), city (ct), state (st), zip (zp), country — combined medium weight
  6. IP + User-Agent — low individual weight, but mandatory

Why CAC depends on it

Meta uses EMQ to calibrate optimization. Events with high EMQ are treated as "truth" by the AI — it optimizes hard for similar patterns. Events with low EMQ are "noise" — the AI ignores or distrusts them.

In real campaigns we audited in 2026:

Average EMQTypical CAC (1.0 baseline)AI behavior
3-41.40 (40% more expensive)Optimizes by weak proxy, high variance
5-61.15 (15% more expensive)Optimizes OK but misses signals
7-81.00 (baseline)Solid optimization, low variance
9-100.85 (15% cheaper)Very high precision look-alike

Diagnosis: why your EMQ is low

Before fixing, find the cause. Go to Events Manager → your pixel → Diagnostics. Look for warnings like:

  • "Missing customer information parameters" → missing email/phone/name in user_data
  • "Email not hashed correctly" → wrong hash (with whitespace, uppercase, etc.)
  • "Phone number format invalid" → phone not in E.164 format
  • "Click ID missing" → fbc/fbp not being sent
  • "Server and browser events received without event_id" → broken dedupe

Fix 1 — Email hash (high weight)

Email is the most valuable signal. Meta's spec:

  1. Trim whitespace;
  2. Lowercase everything;
  3. SHA-256 of the result (not MD5, not plaintext, not base64).
// PHP
$email = '[email protected]  ';
$normalized = strtolower(trim($email));  // '[email protected]'
$hash = hash('sha256', $normalized);
// → 'a7f5f35426b927411fc9231b56382173e3b7be3...'

// JavaScript (Node)
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update(email.trim().toLowerCase()).digest('hex');

Common mistake: hashing with a trailing space or an uppercase letter. Result: hash different from what Meta expects, EMQ stuck at 0.

Fix 2 — Phone in E.164 before hashing (high weight)

Phone is the second most valuable signal, but requires careful normalization. Spec: E.164 format (international standard).

// "555 123-4567" → "+15551234567" → SHA-256

function normalizePhone($phone, $defaultCountry = '1') {
    $digits = preg_replace('/[^0-9]/', '', $phone);

    // If exactly 10 digits, prepend country code (US default = 1)
    if (strlen($digits) === 10) {
        $digits = $defaultCountry . $digits;
    }

    return '+' . $digits;
}

$phone_e164 = normalizePhone('(555) 123-4567');  // '+15551234567'
$hash = hash('sha256', $phone_e164);

By itself, a well-hashed phone can push EMQ from 4 → 7.

Fix 3 — Click IDs (fbc + fbp)

When a user clicks on your Meta ad, the browser stores two cookies:

  • _fbc — Facebook Click ID (comes from the fbclid URL param)
  • _fbp — Facebook Browser ID (generated by the pixel)

You need to capture these cookies on your backend and send them via CAPI:

// PHP - reads from the HTTP request
$user_data = [
    'em' => [hashEmail($email)],
    'ph' => [hashPhone($phone)],
    'fbp' => $_COOKIE['_fbp'] ?? null,
    'fbc' => $_COOKIE['_fbc'] ?? null,
    'client_ip_address' => $_SERVER['REMOTE_ADDR'],
    'client_user_agent' => $_SERVER['HTTP_USER_AGENT'],
];

If the user converts hours/days after the click (typical in B2B SaaS), persist these cookies in LocalStorage or on the server tied to session_id. Otherwise they expire and EMQ drops.

Fix 4 — Full PII (name, address)

Each extra field is one more signal for Meta to match against. For e-com checkout you ALREADY have this data — just need to send it:

$user_data = array_merge($user_data, [
    'fn'      => [hash('sha256', strtolower(trim($order->first_name)))],
    'ln'      => [hash('sha256', strtolower(trim($order->last_name)))],
    'ct'      => [hash('sha256', strtolower(trim($order->city)))],
    'st'      => [hash('sha256', strtolower(trim($order->state_code)))],
    'zp'      => [hash('sha256', preg_replace('/[^0-9]/', '', $order->zip))],
    'country' => [hash('sha256', 'us')],
    'external_id' => [hash('sha256', (string)$order->customer_id)],
]);

Each of these fields can add 0.3-0.7 to EMQ.

Fix 5 — Correct IP and User-Agent

They are mandatory and lower EMQ when missing. Be careful with IP behind a proxy/CloudFlare:

// CloudFlare passes the real IP in CF-Connecting-IP
$ip = $_SERVER['HTTP_CF_CONNECTING_IP']
   ?? $_SERVER['HTTP_X_FORWARDED_FOR']
   ?? $_SERVER['REMOTE_ADDR'];

// Take only the first if it's X-Forwarded-For (can be a list)
$ip = trim(explode(',', $ip)[0]);

$user_data['client_ip_address'] = $ip;
$user_data['client_user_agent'] = $_SERVER['HTTP_USER_AGENT'];

Monitor EMQ continuously

EMQ can drop without you noticing. Things that kill EMQ:

  • A deploy broke and stopped sending phone;
  • Click ID cookie expiring earlier than expected;
  • Traffic volume changed (new campaigns, different audiences);
  • Meta updated the spec and your hash got out of date.

Set up an automatic alert: if EMQ drops below 7.0 for 48h, trigger a notification. SaaS like Trakvo do this out-of-the-box.

FAQ

What exactly is EMQ?

EMQ (Event Match Quality) is a score from 1 to 10 that measures how well Meta can match your events to real users on the platform. The higher the score, the better the AI optimizes. EMQ is calculated per event, based on the last 7 days.

What EMQ is considered good?

Meta classifies: 1-5 low, 5-7 medium (label "Good"), 8-10 high (label "Great"). To scale campaigns, aim for 8+. Above 9 is exceptional and requires careful technical setup.

Does high EMQ really reduce CAC?

Yes, measurably. Climbing from EMQ 5 → 8 typically reduces CAC by 15-25%. The reason: Meta's AI optimizes based on who REALLY converted. With bad data, it optimizes for the wrong sample — ads get expensive for low return.

Can I have high EMQ WITHOUT server-side?

It is practically impossible to reach EMQ 7+ with only the client pixel. The realistic max is 4-5. Because the pixel alone captures only IP + UA + cookie, and Meta needs more signals (hashed email, phone, click IDs).

How long does EMQ take to rise after changes?

EMQ updates with a 48h window. You'll see the impact of changes in 1-2 business days. To stabilize the improvement, count 7 days.

EMQ 8+ without technical work

Trakvo configures hash, normalization, click IDs and PII enrichment automatically. Match Quality 8+ guaranteed in 7 days or your money back.

Talk to the team
Trakvo Assistant
Reply in real time