pixellint

Mobile · engineers · PMs

IDFA is advertising. IDFV is the vendor. GAID is Android.

Sending IDFV in an IDFA field does not anonymize the user. It just mismatches. Sending a hashed IDFA when the MMP wanted the raw value is the IP-and-UA lesson again.

IDFA

Identifier for Advertisers. Across apps, for ads, on iOS, and only if ATT authorized. Format is a UUID. All zeros when denied. Treat zeros as missing, not as a device. Do not persist last week's IDFA after deny. Do not put IDFV in the idfa field to avoid an empty parameter. Empty is honest. The wrong UUID is a join to a device that does not exist in the ads graph.

Hashing IDFA is usually wrong. MMPs and Meta want the raw advertising id in the field they named for it, and hashed PII in the email fields. A SHA-256 IDFA will not match Apple's id or the MMP's device graph. Hash emails. Leave device ads ids in the clear unless the vendor said otherwise. Pixellint does not invent a hashed-idfa rule for a raw idfa field.

https://s2s.adjust.com/event?s2s=1&event_token=f0ob4r&app_token=4w565xzmb54d&idfa=D2CADB5F-410F-4963-AC0C-2A78534BDF1E

Zeros means denied

00000000-0000-0000-0000-000000000000 is denied ATT, restricted, or not determined, depending on what you actually read. It is not a stable device key. Do not send it as idfa to keep the column non-empty. Adjust still needs some documented device id on S2S. After deny, send a documented alternative, not zeros, and not IDFV stuffed into idfa.

Branch wants at least one of developer_identity, browser_fingerprint_id, idfa, idfv, android_id, or aaid. After ATT deny, idfv or developer_identity is honest. idfa filled with zeros is not a documented identifier. Do not hash the zeros either.

https://s2s.adjust.com/event?s2s=1&event_token=f0ob4r&app_token=4w565xzmb54d&idfa=00000000-0000-0000-0000-000000000000

IDFV

Identifier for Vendor. Shared among apps from the same vendor, not among all advertisers. Useful for your own analytics and for MMP uniqueness when IDFA is gone. Useless as a cross-app ads cookie. Sending IDFV as idfa tells Meta or the MMP you have an advertising id you do not have.

IDFV can reset if the user uninstalls all of your apps. Do not treat it as a lifelong key. Do not use it as external_id on CAPI unless you understand it will collide across users who share nothing but the vendor reset. Good for your own product analytics. Not a magic ads match key across other companies' apps.

{
  "branch_key": "key_live_example",
  "name": "COMPLETE_TUTORIAL",
  "user_data": {
    "os": "iOS",
    "idfv": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "ip": "192.0.2.1",
    "developer_identity": "user-10492"
  }
}

GAID spellings

Android's advertising id has three common spellings. Adjust uses gps_adid. Branch uses aaid. AppsFlyer uses advertising_id in places. Put the Android id in the Android field. An iOS event with gps_adid filled from a backup laptop is how test traffic poisons Android campaigns.

Users can reset GAID or opt out of ads personalization. Limit Ad Tracking on older Android, or the current opt-out, is not ATT, but it is a signal. Honor it. Do not invent a GAID. Adjust still requires some device id on S2S. Pick a documented one, not a hash of IP, and not IDFA copied from a teammate's iPhone. Read the Play policy, not a 2018 forum snippet.

https://s2s.adjust.com/event?s2s=1&event_token=f0ob4r&app_token=4w565xzmb54d&gps_adid=660e1d86-6796-463a-be86-897993136018

Wrong field, hashed field

Sending IDFV in idfa, GAID in idfa, or IDFA in gps_adid looks populated in a log and matches nobody. The MMP 200 does not mention it. Pixellint will fail Adjust with no device id at all. It will not fail a well-formed UUID in the wrong conceptual slot if the parameter name is one Adjust accepts.

AppsFlyer email_hashed must be SHA-256. AppsFlyer ip must not. That split is the lesson for device ids too: hash only the fields the vendor documented as hashed. vendor.appsflyer.body.email_hashed.invalid and vendor.appsflyer.body.hashed_plaintext_field are those two. There is no hashed_idfa contract on these packs. Do not invent one.

Check the artifact

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