Back to all posts

Mobile Apps · iOS · Android · September 2026 · 12 min read

How to run an affiliate program for an iOS app in 2026 (without paying Branch $1,000 a month)

Why iOS affiliate tracking is genuinely hard, what doesn't work (and why people keep trying it anyway), the four-hop chain that does work, and the race condition that breaks 30% of installs if you ignore it.

If you sell a subscription iOS or Android app and you've tried to add an affiliate program, you already know the situation. Every web-grade affiliate platform (Refersion, Tapfiliate, PartnerStack, GoAffPro) ships zero mobile support. Every mobile platform that does work (Branch, AppsFlyer, Singular) is sized for paid acquisition and starts at $500 to $2,000 a month, on annual contracts. The middle ground for indie SaaS and bootstrapped mobile apps is essentially empty.

This article walks the architecture from first principles. Why iOS affiliate is genuinely hard, what doesn't work and why people keep trying it anyway, the chain that does work in 2026, and the one race condition that breaks roughly 30% of installs if you don't plan for it.

If you're shipping iOS, Android, or both, by the end you'll have a concrete picture of what every component does, what each line of code does, and what to look for when comparing platforms.

1. Why iOS affiliate is hard

Affiliate tracking on the web is a solved problem. A visitor clicks yourstore.com?ref=jane10, the server reads ref off the request, drops a first-party cookie, and on checkout the order carries the cookie value to the conversion webhook. Three moving parts, all on infrastructure you control.

iOS breaks every one of those parts.

The App Store sits between the click and the install. A user tapping an affiliate link in Safari ends up on an App Store page; tapping Install begins a download that has no continuity with the original tap. The App Store does carry one ad-channel attribution mechanism (StoreKit's Transaction.appAccountToken, plus SKAdNetwork postbacks), but the parameters are scoped to Apple Search Ads and the few ad networks Apple integrates. Your affiliate link gets nothing.

The IDFA, which used to bridge that gap, is effectively dead. App Tracking Transparency added an explicit opt-in prompt in iOS 14.5; current opt-in rates sit between 18% and 25% depending on category. Even when you get consent, IDFA is a per-device identifier; matching it back to the affiliate who referred the user requires a third party to be in the middle for both the web click and the app install, which is the entire MMP business model.

Cookies don't exist in native apps. Safari View Controller maintains its own cookie jar separate from the main app, so any "cookie" you set before the user downloads cannot be read after.

Custom URL schemes (yourapp://?ref=jane10) only fire if the user already has the app. They die on first install, which is the exact moment you need them.

Fingerprinting (IP + browser features + locale + screen dimensions) used to be the desperation fallback. Apple's App Store Review Guidelines section 5.1.2 prohibits it for advertising and analytics, and probabilistic matching at install time degrades fast above 50,000 daily installs. GDPR and CCPA reduce the attack surface further.

The combined result: you have a click in a browser and an install in a sandboxed app, and almost nothing connecting them that survives platform privacy controls. Every affiliate platform that tries to retrofit the web model onto this stack hits the same wall.

2. What doesn't work

If you ask three iOS developers how they'd add affiliate tracking, you'll get three suggestions that all sound reasonable for ten minutes. None of them ship at scale.

Clipboard handoff

The affiliate link writes the code to the iOS clipboard before redirecting to the App Store; after install, the app reads the clipboard and extracts the code. This worked quietly until iOS 14 added a visible "Pasted from Safari" banner the moment any app reads the clipboard. iOS 16 escalated to a per-paste user permission prompt. iOS 17 made the prompt impossible to suppress with UIPasteboard.DetectionPattern. Users either deny the prompt or feel surveilled and stop trusting your app. Real-world capture rate is below 30% on iOS 17 and falling.

Typed referral codes

The affiliate gives out JANE10; the app shows a "Got a referral code?" field on first launch. This works mechanically. The redemption rate in production is 4 to 8%. Most users forget the code between tapping the link and finishing onboarding, and the fraction who type it correctly is smaller than you'd think (capital letters, zero versus O, numeric ones).

Server-side IP fingerprinting

Match the IP that hit the affiliate redirect with the IP the app's first API call comes from, within a few minutes. This works on first-party WiFi about 40% of the time and on cellular near zero. Carrier-grade NAT pools tens of thousands of phones behind a single IP. False positive rate in apartment buildings or office buildings is high enough that you'll credit the wrong affiliate routinely.

Apple's iAd / Search Ads / SKAdNetwork

These exist, work, and are honored by Apple. They are scoped to paid ads via the App Store campaign system or partner ad networks. They do not pass arbitrary affiliate codes from an organic affiliate link. Different problem, different solution.

MMPs (Branch, AppsFlyer, Singular)

These solve the problem properly using Universal Links, deferred deep linking, and probabilistic fallbacks. The minimum monthly commitment for any of them starts in the high three figures, and the contract is sold on the assumption you're spending five to six figures a month on paid acquisition. For an indie app trying to launch an affiliate program with creators earning $50 a month, the math doesn't work.

3. What does work in 2026

The architecture every shipping iOS/Android affiliate program ends up at, regardless of which platform builds it, is the same four-hop chain.

Hop 1: The smart link is a domain you own, not a redirect

When someone taps https://yourbrand.com/r/jane10 in Safari, iOS checks an apple-app-site-association file on your domain. If the user has your app installed, iOS opens the app directly with the URL. No detour through the App Store, no clipboard prompt, no IDFA. If they don't, the link falls through to the App Store. After install, when they open the app for the first time, the deferred Universal Link fires the same handler.

Same architecture on Android with assetlinks.json and App Links.

This is the foundational shift. Old-school affiliate tracking depends on cookies or device fingerprints surviving the App Store detour. Universal Links don't need any of that. The OS itself carries the affiliate code from the tap to your application:continueUserActivity:.

Hop 2: The app extracts the code in two lines

Install:

# Swift Package Manager (Xcode → File → Add Package Dependencies)
https://github.com/affref/affref-ios

# Android (build.gradle.kts)
implementation("com.affref:affref-android:0.1.0")

Wire it into your app delegate / main activity:

// iOS — AppDelegate.swift
import AffRef

func application(_ app: UIApplication, continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    AffRef.handle(userActivity)
    return true
}
// Android — MainActivity.kt
import com.affref.AffRef

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent.data?.let { AffRef.handle(it) }
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    intent.data?.let { AffRef.handle(it) }
}

The SDK reads the path segment (jane10), POSTs an install row to your attribution backend so you can see install-level analytics, and surfaces the captured code via a callback.

Hop 3: Hand the code to your subscription stack as a user attribute

The crucial piece most teams get wrong. The conversion event doesn't come from your app. It comes from your subscription provider's webhook when the user pays. So you have to give the subscription provider the affiliate code at the time the user starts using the app, not at the time they subscribe.

// iOS — RevenueCat
AffRef.onCodeCaptured = { code in
    Purchases.shared.attribution.setAttributes(["affref_code": code])
}
// Android — Adapty
AffRef.onCodeCaptured { code ->
    val params = AdaptyProfileParameters.Builder()
        .withCustomAttribute("affref_code", code)
        .build()
    Adapty.updateProfile(params) { /* result */ }
}

Substitute RevenueCat, Adapty, Qonversion, or raw StoreKit / Play Billing. They all support per-user custom attributes that ride along on every subsequent subscription event.

Hop 4: The subscription webhook closes the loop

When the user finally pays (could be 30 seconds later, could be 14 days into a trial), RevenueCat fires its webhook with subscriber_attributes.affref_code already attached to the event. Your affiliate platform reads that field, matches it to the affiliate, and credits the commission. No cookies. No fingerprints. No clipboard. No MMP-grade infrastructure.

The whole chain is: OS-level deep link → app callback → subscription provider attribute → provider webhook → commission. Five hops, every one of them durable, no probabilistic matching.

4. The race condition no one talks about

The chain above has one subtle failure mode that breaks attribution on roughly 20 to 30% of conversions if you ignore it.

The flow assumes the order: user installs, app opens, SDK extracts the code from the deferred Universal Link, SDK sets affref_code as a subscriber attribute, user eventually subscribes. In practice, the user can subscribe within seconds of first opening the app. A growing share of subscription apps now lead with a paywall on first launch. If the user taps Subscribe before the SDK has finished posting the custom attribute to the subscription provider, the subscription event fires with no affref_code attached, and the affiliate gets no credit.

The fix is server-side. Your affiliate backend should record an "install" row at the moment the SDK fires its first attribution call, keyed by the same device identifier the subscription provider will eventually send (app_user_id on RevenueCat, customer_user_id on Adapty). When a subscription webhook arrives with no affref_code on it, the backend looks up the most recent install row for that device ID within an attribution window (30 days is a reasonable default), pulls the affiliate code from there, and uses it as the fallback.

The same fallback is what saves you when an iOS user grants and then revokes notification permissions mid-onboarding, when a flaky network drops the SDK's attribution call, and when a power user closes the app between launch and subscribe. Every shipping iOS affiliate platform handles this. Every home-rolled implementation forgets it the first time.

5. The trial-policy question

Subscription apps almost universally lead with a free trial. The architecture above will happily credit the conversion the moment the trial starts. Whether that's the right time to credit depends on your category.

Two reasonable defaults exist.

Credit at trial start. The affiliate sees the conversion as soon as the user starts the trial. Fast feedback for creators, easier to attribute correctly because there's no second event to track. The downside is that you'll pay commission on trials that never convert. If 60% of your trials drop off (typical for utility apps) you're paying a 60% premium versus crediting on conversion. A refund event reverses the conversion automatically, but cash-flow-wise the commission ages out before the refund signal arrives.

Credit only when the trial converts to paid. Wait for the trial-to-paid transition (TRIAL_CONVERTED on RevenueCat, the first paid renewal on Adapty). Slower feedback for affiliates. More accurate spend.

Industry default is to credit at trial start. If your category trial drop-off is unusually high (utility apps, gimmicky one-off purchases), credit on conversion. Whatever you pick, document it on your affiliate program page so creators aren't surprised.

6. What this looks like end to end

Walking the lifecycle of one affiliate-driven subscription:

  1. Jane is a creator with a TikTok audience. You sign her up to your affiliate program. AffRef (or whatever you're using) generates her a smart link: https://yourbrand.com/r/jane10.
  2. She posts it in her bio.
  3. A follower, Sam, taps the link in mobile Safari. iOS resolves the Universal Link, sees Sam doesn't have your app, and falls through to the App Store. Sam taps Install.
  4. Sam opens the app for the first time. iOS replays the deferred Universal Link to application:continueUserActivity:. The AffRef SDK extracts jane10, POSTs an install row to AffRef, and sets affref_code = jane10 as a RevenueCat subscriber attribute.
  5. Three minutes later, Sam taps Subscribe on your paywall.
  6. RevenueCat handles the StoreKit transaction, charges Sam's iCloud card, and fires its webhook to AffRef with the event payload including subscriber_attributes.affref_code: "jane10".
  7. AffRef matches jane10 to Jane's affiliate row, creates a Conversion, calculates the commission off the order total, and either auto-approves or queues for your review depending on your settings.
  8. Jane sees the conversion in her brand-portal dashboard. Pending review for the refund-window period, then released for payout.
  9. At month-end, you bulk-export the cleared payouts to PayPal Mass Pay or Wise Batch. Done.

If Sam had subscribed in 5 seconds instead of 3 minutes, hop 3 might have lost the race. AffRef's server-side fallback (section 4) catches it: when the webhook arrives without affref_code, AffRef looks up the install row for Sam's RevenueCat app_user_id, finds jane10, and credits Jane anyway.

What to look for when comparing platforms

Most of the mobile affiliate platforms on the market are either MMPs targeting paid-acquisition spend (where attribution is one feature of many), or web-grade affiliate tools that grafted iOS support on as an afterthought. Here's the diligence checklist if you're evaluating one:

  1. Does the platform host its own AASA file, or do you have to host one on your own domain? Hosting your own is fine if you control DNS and want a branded link domain. Many indie devs don't.
  2. Is there an SDK, or does the platform expect you to wire Universal Links by hand and POST attribution events from your code? An SDK that handles the AASA registration, the universal-link handler, the install-row reporting, and the deferred-link fallback is 90% of what you're paying for.
  3. Does it integrate natively with your subscription stack (RevenueCat, Adapty, Qonversion), or does it require you to fire conversion calls manually from your purchase handler? Manual is brittle. Native webhook-based is durable.
  4. Does it implement the install-row fallback for the race condition? Ask. If they don't know what you're talking about, they don't have it.
  5. Does it support trial-policy toggling? Some apps want credit at trial start, others at trial-to-paid. The toggle is a 30-minute build that vendors often skip.
  6. What's the pricing model? Per-install (MMP-style), per-conversion (revenue-share), or flat-fee SaaS? For an affiliate program in particular, flat fees beat per-conversion, because you don't want to be paying both your affiliates and your tracker on every sale.

So how does AffRef do it

The four-hop chain in section 3 is exactly what AffRef ships, end to end. The Swift Package and Android Gradle dependency. The AASA and assetlinks hosting on affref.com (or your branded subdomain). The subscription-provider webhook handlers for RevenueCat and Adapty (and a generic REST endpoint for Qonversion or raw StoreKit). The install-row fallback that catches the race condition. The trial-policy toggle. The affiliate dashboard. The payout pipeline.

One Pro-plan subscription, no per-conversion fee, no MMP contract. Plans & pricing · Full mobile SDK setup · Start the trial.

If you're sitting on a mobile app with no affiliate program because everything you've evaluated costs more than your first ten affiliates would earn, this is the article we wrote for you. Set it up, run it for a month, see if the model fits your audience. If it doesn't, you've lost the Pro fee and 30 minutes of integration time. If it does, you have a creator channel you didn't have last quarter.

Ready to grow your affiliate program?

Start your 7-day free trial. Cancel anytime.

View Plans
Usually replies within an hour
Hey 👋 I'm Aaron, founder of AffRef. Drop your email and your question and I'll get back to you fast.
By chatting you agree to our privacy policy.
End this chat? History on this device clears.