Skip to content
bizurk
← ALL WRITING

2026-07-01 (Updated 2026-10-23) / 4 MIN READ

Meta CAPI match quality audit and identifier checks

Inspect Meta CAPI identifier coverage, normalization, and event diagnostics, then verify repairs against controlled events and a dated reporting window.

Match quality helps inspect the customer information attached to Meta server events. It does not translate directly into a percentage of matched people or a measured revenue loss. Start with the event payload and the diagnostics for that event type before choosing a fix.

This guide combines the audit with the identifier repair sequence from the earlier rebuild notes. The tracking gap case study remains the implementation record; the checklist below is for evaluating your own configuration.

The CAPI match quality audit checklist

  1. Record the event name, observation period, and score shown in Events Manager. Compare the same event type across the change.
  2. Inventory the identifiers that are actually present. A score alone cannot identify a missing field with certainty.
  3. Inspect a controlled event in Test Events and the payload that your sender emitted. Keep raw customer values out of saved debugging logs.
  4. Compare identifier coverage between relevant event types. The data available on a page view can differ from a completed purchase.
  5. Verify normalization and hashing for each customer information parameter against its current contract.
  6. Check that available fbp and fbc values use the expected format and have not been hashed again.
  7. Follow external_id from the system that owns it through each intended event path. Record how guest and authenticated events differ.
  8. Save the deployment time and review the reporting window before judging the result. Repeat the controlled event after the change.

Separate the score from the purchase count

A stronger matching signal does not prove that an order was counted once, that its value was correct, or that the platform should attribute it to an ad. Check deduplication, event coverage, value, currency, and the attribution settings separately.

The earlier articles gave different starting scores for the same general rebuild story. A retained event sample and dated Events Manager capture are better evidence than inferring a starting value from those articles. Avoid assigning a fixed number of score points to an identifier without data for the actual event population.

How to evaluate a repair

Choose one suspected fault from the audit and write down the expected payload change. Test the normal path, a guest purchase, an unavailable identifier, and the relevant consent state. Compare the emitted field with a fixture whose expected normalization and digest you can calculate independently.

After release, monitor warnings and coverage for the same event names. Purchase count reconciliation belongs beside this work, using the GA4, Meta, and Shopify comparison. A score change is a diagnostic observation with a date and scope, rather than a promise about campaign performance.

Repairing identifier inputs after the audit

Fix the normalization path before adding fields. Hash the normalized value required by Meta's current parameter contract. An email with different whitespace or case produces a different SHA256 digest if the input is left unchanged.

import { createHash } from "node:crypto";

function sha256(value: string): string {
  return createHash("sha256").update(value, "utf8").digest("hex");
}

function hashEmail(raw?: string | null): string | undefined {
  const value = raw?.trim().toLowerCase();
  return value ? sha256(value) : undefined;
}

function hashExternalId(raw?: string | number | null): string | undefined {
  if (raw === null || raw === undefined) return undefined;
  const value = String(raw).trim();
  return value ? sha256(value) : undefined;
}

For a phone number, resolve the country before normalization. An international value such as +14155552671 identifies the country and subscriber number; the format Meta hashes uses the digits, including the country code, without punctuation. A local number such as (415) 555-2671 needs country context before that transformation. Treat an ambiguous number as missing instead of inventing its country.

Billing address fields have different rules from email. Keep country, state, city, and postal code as separate parameters. Use field specific normalization against the current contract rather than sending all values through an ASCII stripping helper. That distinction matters for international addresses.

Meta's parameter builder provides normalization and hashing for these field types. The example below assumes an initialized builder and an already authorized payload. It shows the address mapping without pretending one handwritten normalizer covers every country.

const address = order.billing_address ?? order.shipping_address;
const addressFields = address ? {
  ct: builder.getNormalizedAndHashedPII(address.city, "city"),
  st: builder.getNormalizedAndHashedPII(address.province_code, "state"),
  zp: builder.getNormalizedAndHashedPII(address.zip, "zip_code"),
  country: builder.getNormalizedAndHashedPII(address.country_code, "country"),
} : {};

Keep external_id tied to a stable identifier your system actually owns. Forward fbp and fbc in the format Meta expects, without hashing them again. Include these values only when available and permitted for the event. Adding identifiers is a data handling decision as well as a matching decision.

The earlier rebuild notes reported a score around six rising to 9.1. Those are observations from one engagement, with inconsistent starting figures across the old articles. They do not establish a fixed lift per field, a percentage of people matched, or revenue recovered. Keep a dated before and after event sample and the Events Manager view when evaluating your own change.

// related

DTC Stack Audit

If this resonated, the audit covers your tracking layer end-to-end. Server-side CAPI, dedup logic, and attribution gaps - all mapped to your stack.

>See what is covered

Tell me what you’re trying to ship.

Send a quick message and I read it within a day, or talk to AI Michael first if you want to feel out your project before you write to me.

By sending this, you agree to the Terms and acknowledge the Privacy Policy.