Event Match Quality is the score Meta shows next to each event in Events Manager. It measures how well the customer information you send with an event lets Meta match that event to a real account. Low scores mean purchases and leads that happened but cannot be credited to your ads, smaller custom audiences, and an optimisation algorithm working with partial information.
Most accounts score poorly for mundane reasons: no email on the event, no click cookie, nothing identifying the customer beyond an IP address. This guide explains what moves the score and how to fix it, parameter by parameter.
How the Score Works
Meta looks at the customer information parameters attached to an event and rates, on a scale of one to ten, how likely the event is to be matched. More parameters, correctly formatted, mean a higher score. The score is calculated per event name, so Purchase and PageView have different scores and different realistic ceilings.
The Parameters, Ranked by Impact
| Parameter | Key | Impact | Where you get it |
|---|---|---|---|
| em | Highest | Login, checkout, forms, order confirmation | |
| Phone | ph | Highest | Checkout, forms |
| External ID | external_id | High | Your customer or user ID, hashed |
| Click ID cookie | fbc | High | _fbc cookie, or built from fbclid in the URL |
| Browser ID cookie | fbp | High | _fbp cookie set by the pixel |
| First and last name | fn, ln | Medium | Checkout, forms |
| City, state, postcode, country | ct, st, zp, country | Medium | Checkout address |
| Date of birth, gender | db, ge | Low to medium | Only where you legitimately collect it |
| Client IP address and user agent | client_ip_address, client_user_agent | Expected on server events | Read from the request by the server template |
Everything above the double line in impact is where accounts gain the most. In practice, the three most commonly missing are external_id, fbc and phone.
Normalisation and Hashing Rules
Meta matches hashed values exactly, so the input must be normalised first. Templates do this for you; if you write code, follow the rules:
- Email: trim, lowercase. Then SHA-256.
- Phone: digits only, including country code, no leading zeros or plus sign. Then SHA-256.
- Names: lowercase, no punctuation, UTF-8. Then SHA-256.
- City: lowercase, no spaces or punctuation. State: two-letter code lowercase. Postcode: lowercase, no spaces, UK and Canada first part only. Country: two-letter ISO code lowercase. Then SHA-256.
- External ID: your stable identifier, SHA-256 recommended.
- fbp, fbc, IP address, user agent: send as they are. Do not hash.
A phone number stored as "+1 (555) 123-4567" must become "15551234567" before hashing, or it will never match.
Step 1: Push Customer Data Wherever You Have It
The pixel cannot send what the page does not expose. Build a user data layer:
- On login, push the user's email, name and your user ID as external_id.
- On checkout, push billing fields as they are completed.
- On the order confirmation page, push the full billing details.
- On form submission, push the submitted email and phone.
The WordPress Advanced Matching guide on this site has the PHP for WooCommerce. For Shopify, the Customer Events pixel exposes checkout email, phone and address on checkout_completed.
Step 2: Map Advanced Matching in the Pixel
In the Meta Pixel template in GTM, enable Advanced Matching on the base tag and map each Data Layer Variable. Do the same on the Purchase and Lead event tags, because that is where you have the most complete data. The template hashes in the browser.
Step 3: Capture fbc Correctly
The _fbc cookie is set by the pixel when a visitor arrives with fbclid in the URL. It is often missing because the pixel fired late, consent delayed it, or the visitor navigated before it was set. Add a small Custom HTML tag early on every page that creates it when needed:
<script>
(function () {
var m = location.search.match(/[?&]fbclid=([^&#]+)/);
if (!m) { return; }
if (document.cookie.indexOf('_fbc=') > -1) { return; }
var value = 'fb.1.' + Date.now() + '.' + decodeURIComponent(m[1]);
var domain = location.hostname.replace(/^www\./, '');
document.cookie = '_fbc=' + value + '; max-age=' + (90 * 24 * 60 * 60) + '; path=/; domain=.' + domain + '; SameSite=Lax; Secure';
})();
</script>
If you run server-side GTM, enable the server template's option to set _fbp and _fbc as HTTP cookies. Server-set cookies last longer on Safari than browser-set ones.
Step 4: Send external_id
Decide on one stable identifier per customer: the user ID in your platform, the CRM contact ID, or the Shopify customer ID. Push it to the dataLayer on login and on conversion, hash it, and send it as external_id on both pixel and server events. For anonymous visitors, some setups send the _fbp value as a fallback external ID; it is better than nothing but a real customer ID is what moves the score.
Step 5: Server Events With Full User Data
The Conversions API is where the score is won. On the server, each event should carry the hashed email, phone, name and address where available, the hashed external_id, the _fbp and _fbc values, and the client IP address and user agent read from the request. The Conversions API guide on this site covers the tag configuration. With all of that, Purchase and Lead events reach 8 or higher.
Step 6: Deduplicate, Then Compare
Matching across browser and server is combined when events are deduplicated by event_id. If the browser event has the email and the server event has the cookies and IP, Meta merges what it needs. Make sure both carry the event ID, otherwise you get two half-matched events instead of one well-matched one.
Step 7: Read the Score Properly
In Events Manager, open the dataset Overview and look at each event's score. Click into an event to see which parameters are being received and the coverage percentage for each. Low coverage on fbc means visitors from ads are not getting the cookie. Zero coverage on external_id means it is not being sent at all. The coverage view tells you exactly what to fix next.
Realistic Targets
| Event | Target | Why |
|---|---|---|
| Purchase | 8 to 10 | Full billing details available |
| Lead, CompleteRegistration | 8 to 9 | Email and usually phone available |
| InitiateCheckout | 6 to 8 | Partial checkout data |
| AddToCart, ViewContent | 5 to 7 | Mostly anonymous visitors |
| PageView | 4 to 7 | Cookies and IP only for most visitors |
If Purchase is below 7, something is missing from the setup rather than from the data. If PageView is 5, that is normal.
Common Mistakes
- Hashing fbp, fbc or IP address.
- Phone numbers with formatting or without country code.
- Email captured in mixed case and hashed without lowercasing.
- external_id never sent.
- Advanced Matching enabled only on the base pixel and not on conversion events.
- Server events without client IP and user agent because the request headers were stripped by a proxy.
Outcome
Events Manager shows Purchase and Lead in the green, coverage on email, phone, fbc and external_id climbing toward the share of customers you actually know, and Ads Manager attributing more of the sales you were already making. That is what match quality buys you: credit for results that were always there.
