pixellint

Mobile · PMs · engineers · marketers

The click was on the web. The conversion was in the app.

Thank-you pixels never run. App Purchase events never see fbclid unless you pass a campaign token through the MMP or a claimed deep link. This is a designed seam, not a tag typo.

Keep the web click id

fbclid, gclid, ttclid, and the MMP click live on the landing URL. Store them before the user leaves for the store. If the store hop is a redirect that strips query, the app will never see them. This is the same class of bug as a www redirect that eats gclid, with a store interstitial in the middle.

On first open, send those ids on the MMP event and on app CAPI if you use it. Meta wants fbc constructed from fbclid when you have it. A hashed email helps. An app event with neither, after a web click, is an unmatched conversion. Pixel plus CAPI on the web does not count the in-app purchase unless you also send the app event.

https://example.com/offer?fbclid=IwAR0abcdef&utm_source=facebook&utm_campaign=w2a-spring

CAPI action_source is app

action_source=app on CAPI. Do not fire website Purchase when the charge happened in IAP. A website event with event_source_url set to the store listing is a lie. vendor.meta-conversions-api.body.action_source.invalid if you invent a spelling. website is one of the nine documented values. It is the wrong one for IAP.

Use the same event_id if a web PageView and an app Purchase are a funnel, not two Purchases. Double Purchase, one web and one app, with different event_id values, is how ROAS doubles on web-to-app. Do not fire a web Purchase pixel when the user taps Download. Fire Purchase in the app when the receipt is real.

{
  "data": [{
    "event_name": "Purchase",
    "event_time": 1770000000,
    "event_id": "iap-10492",
    "action_source": "app",
    "user_data": {
      "em": ["a85e9ca18f34935ab9b0381b25bfad2455444112b0149270fd88e3da172fe196"],
      "fbc": "fb.1.1758300000000.IwAR0abcdef"
    },
    "custom_data": { "value": 129.99, "currency": "USD" }
  }]
}

MMP

AppsFlyer and Branch exist for this path: web click, store, install, first open, in-app purchase. Use their web links or smart banners so the click is theirs, then S2S the purchase with receipts. A plain https link to the App Store with no MMP click is an organic install in their world, even if Meta paid for the page view.

Deferred deep links are how the user sees the product they clicked. Measurement can succeed without the route, but then you paid to dump users on home. Do both: keep the click, and open the right screen. Use the documented web-to-app flow rather than a homemade click id in a query the store will strip.

POST https://api3.appsflyer.com/inappevent/id123456789
{
  "appsflyer_id": "1234567890123-1234567",
  "eventName": "af_purchase",
  "eventValue": "",
  "eventTime": "2026-08-21 18:04:00.000",
  "ip": "192.0.2.1"
}

SKAN is a second view

Apple may attribute the install to the web campaign via SKAN if the ad was SKAN-capable, without giving you the user. That postback will not include the web click id. Report SKAN and MMP as two views. Do not subtract one from the other and call the remainder fraud.

You cannot paste a SKAN postback into a pixel validator. Keep the web click id for the hops that can still carry it. Let SKAN report what Apple will still attribute. Do not drop fbclid because SKAN exists.

QA the whole walk

Walk a click from ad to store to first open to purchase on a device that did not have the app. Anything less is a unit test of the SDK, not of the campaign. Confirm the landing URL still has fbclid. Confirm the app event has fbc or the MMP click. Confirm you did not also fire a web Purchase.

pixellint validate json on the app CAPI body. pixellint validate url on any web pixel that still fired. If the web pixel fired Purchase on the Download tap, that is the double-count, not an MMP bug. Fix the tag, then the S2S, then the SKAN map, in that order of damage.

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Nothing leaves the tab.