Facebook’s Agents Still Run. Apple Keeps Wiping Their Memory.
How Apple killed cross-app tracking, rebuilt deep links with privacy guardrails, and keeps making sure Facebook’s SDK forgets who you are.
Previously: Apple Is Crushing Deep Links That Were Used As Ad-Tracking Devices | Apple Is Killing A Billion-Dollar Ad Industry With One Popup
In July 2020, I wrote that Apple’s iOS 14 privacy popup would crush deep links used for ad tracking. Facebook warned of 50 percent revenue drops. Advertisers panicked.
Four years later, we have the receipts.
Meta projected a ~$10 billion headwind. Deep links lost their tracking superpowers. But then Apple did something unexpected: they rebuilt attribution measurement from the ground up—with privacy guardrails.
Think of the old system as an agent with unrestricted memory access. It could read everything about you, share it with anyone, remember it forever. The new system? An agent with defined skills and boundaries. It can only do what it’s authorized to do.
The agent is the spy. The advertiser is the handler. Apple didn’t fire the spy—they wiped its memory and put it on a leash.
The Reckoning
In February 2022, Meta CFO Dave Wehner admitted: “We believe the impact of iOS overall is a headwind on our business in 2022. It’s on the order of $10 billion.”
The stock nosedived. Facebook lost $200 billion in market cap in a single day.
Early ATT data showed opt-out rates above 90 percent in the U.S. The vast majority chose “Ask App Not to Track.”
The hosts woke up.
How Facebook’s SDK Used to Work (The Abuse)
For starters, let’s look at how the old system actually worked in code.
Before iOS 14.5, any app with Facebook’s SDK could grab your device’s advertising identifier without asking:
// THE OLD WAY - No consent required
import AdSupport
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
// Returns: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
// Facebook SDK would then:
// 1. Send this IDFA to Facebook's servers
// 2. Match it against your Facebook profile
// 3. Track every app you opened, every purchase you made
// 4. Build a behavioral model to predict what you'd buy nextThat IDFA was constant for your device. It followed you everywhere. Facebook’s SDK existed in hundreds of thousands of apps across app stores. Every one of them fed data back to the mothership.
In simpler words: Facebook had planted agents everywhere, all reporting back everything you did.
The SDK would track app installs, app opens, in-app purchases, time spent in each app, which ads you clicked, which products you viewed. All tied to a single identifier. All without your explicit consent.
What Apple Killed
iOS 14.5 introduced App Tracking Transparency. Now that same code requires permission:
// THE NEW WAY - Consent required
import AppTrackingTransparency
import AdSupport
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
// User said yes (only 20% do)
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
case .denied, .restricted, .notDetermined:
// User said no - IDFA returns all zeros
// "00000000-0000-0000-0000-000000000000"
@unknown default:
break
}
}When users decline, the IDFA returns all zeros. Useless. Facebook’s cross-app surveillance network went dark.
The agent lost its memory access. It could still exist in those apps, but it couldn’t remember who you were.
The Privacy-Preserving Alternative
Apple didn’t just kill tracking. They built a replacement: SKAdNetwork, and later AdAttributionKit.
The key insight: advertisers don’t need to know who installed their app. They need to know that their ad worked.
Here’s how the new system measures ad success without identifying users:
// PRIVACY-PRESERVING ATTRIBUTION
import StoreKit
// When user engages with the app, update conversion value
// No user ID, no device ID, no IDFA
SKAdNetwork.updatePostbackConversionValue(
42, // Fine-grained value (0-63)
coarseValue: .high, // Coarse value (low/medium/high)
lockWindow: false
) { error in
// Apple sends anonymous postback to ad network
// Postback contains NO user-specific data
}What gets sent to the advertiser:
{
"version": "4.0",
"ad-network-id": "example123.skadnetwork",
"source-identifier": "1234",
"conversion-value": 42,
"did-win": true
// NO device ID
// NO user ID
// NO IDFA
}The advertiser learns: “Someone who saw ad campaign 1234 installed our app and reached conversion level 42.”
They don’t learn: “John Smith, age 34, who also uses Instagram and ordered pizza last Tuesday, installed the app.”
Crowd Anonymity: Memory That Requires Consensus
Here’s where it gets clever. With SKAdNetwork 4.0, Apple introduced postback data tiers based on crowd size. AdAttributionKit inherits the same privacy model.
Think of it like this: an agent can only share a memory if enough other agents have the same memory. Individual experiences stay private. Only patterns emerge.
Tier 3 (Large crowd): Full details flow—4-digit campaign ID, exact conversion value, publisher app, country code.
Tier 2 (Medium crowd): Partial details—2-4 digit campaign ID, conversion value.
Tier 1 (Small crowd): Minimal—2-digit campaign ID, coarse value only (low/medium/high).
Tier 0 (Tiny crowd): Almost nothing—just that someone installed.
If you’re the only person who clicked an ad and installed an app, the advertiser learns almost nothing. Your individual behavior is protected.
Only when enough people take the same action does detailed data flow. And even then, it’s aggregate—never individual.
The agent remembers, but only what the crowd experienced together.
The Resurrection: Universal Links
At WWDC 2024, Apple unveiled AdAttributionKit with a feature advertisers had begged for: re-engagement.
For the first time since iOS 14, advertisers could measure campaigns for apps users already had installed. The mechanism? Universal Links.
But these aren’t the lawless deep links of 2019.
Old Deep Links: Agents Without Boundaries
The old deep links could do anything:
// OLD DEEP LINK - No verification
// Any app could claim any URL scheme
// myapp://track?idfa=XXX&campaign=YYY&user_data=ZZZNo verification. No consent. Any app could claim any URL, pass any data, track anything.
Universal Links: Agents With Defined Skills
Universal Links require mutual verification.
Step 1: Website declares which apps can handle its URLs
// https://example.com/.well-known/apple-app-site-association
{
"applinks": {
"details": [{
"appIDs": ["TEAMID.com.example.app"],
"components": [
{ "/": "/products/*" },
{ "/": "/checkout/*" }
]
}]
}
}Step 2: App declares which domains it handles
// In app's entitlements
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:example.com</string>
</array>Step 3: System verifies both sides match before routing
// App handles the verified link
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return false
}
// URL is verified - only arrives here if:
// 1. Domain owner authorized this app
// 2. App declared this domain
// 3. System verified the handshake
return handleDeepLink(url)
}The agent can only do what both parties agreed to. No rogue behavior. No unauthorized tracking.
Re-engagement: Deep Links Reborn
With AdAttributionKit, Universal Links power privacy-preserving re-engagement:
// PRIVACY-PRESERVING RE-ENGAGEMENT
import AdAttributionKit
// User taps ad for app they already have
// Universal Link opens app to specific screen
// AdAttributionKit records conversion anonymously
try await Postback.updateConversionValue(
42,
coarseConversionValue: .high,
lockPostback: false
)
// Postback sent with:
// - "conversion-type": "re-engagement"
// - NO user identification
// - Same crowd anonymity rules
// - Same random delays (24-144 hours)Deep links work again. But they can’t identify you.
WWDC 2025: More Slots, Same Amnesia
Apple keeps shipping privacy patches like it’s a live service game. WWDC 2025 dropped four AdAttributionKit buffs:
Overlapping conversions. Old system: one re-engagement conversion at a time. Second campaign? Overwrites the first. New system: overlapping re-engagement conversions via conversion tags. Multiple campaigns, separate measurements. Concurrent amnesia.
Cooldown timer. Configurable via Info.plist. After a conversion fires, the cooldown prevents overlapping attribution within a window. No credit-stealing between campaigns.
Country codes (crowd-gated). Postbacks can now include country-code: "FR"—but only if the French cohort crosses Apple’s anonymity threshold. Below the threshold? No country code.
But what if an app uses CoreLocation directly to track you? Here’s the kicker: iOS 26 encrypts your entire location history end-to-end. Apple can’t read it. Courts can’t subpoena it. Advertisers get “France.” Your actual location diary? Only you hold the key. An app with location permission can still phone home in real-time, but that’s on you for granting it.
Sandbox testing. Developers can now simulate postbacks in iOS Settings. Facebook had to test their tracking on live users for years. Apple lets you sandbox the whole thing first.
Better measurement without better surveillance.
What Facebook Lost (And Can’t Get Back)
Facebook’s SDK still exists in thousands of apps. But here’s what it can no longer do:
Before iOS 14.5: Access IDFA without consent. Track users across apps. Build individual behavioral profiles. Match app data to Facebook profiles. Precise ad retargeting. Measure exact user-level conversions.
After iOS 14.5: None of the above. For the vast majority of users who opted out, the IDFA returns zeros.
Facebook rebuilt their system around probabilistic matching and aggregate modeling. They can guess. They can’t know.
The agent still runs. But its memory has been wiped.
The Irony
While Facebook hemorrhaged billions, Apple’s own advertising business quietly grew. Reports suggested Apple Search Ads gained adoption among advertisers while Facebook’s share declined.
Apple built the privacy wall, then sold premium real estate inside it.
The Loop Closes
In 2020, I wrote that Apple’s privacy popup would kill deep links used for tracking.
I was half right.
The tracking did die. But deep links evolved. Universal Links and AdAttributionKit rebuilt what advertisers lost, and with boundaries.
The old system: agents with unrestricted memory, sharing everything with anyone, tracking individuals across the entire ecosystem.
The new system: agents with defined skills, verified identities, crowd-anonymous memories, and time-limited tasks.
Apple didn’t destroy advertising. They forced it to grow up.


