{"id":1897,"date":"2026-07-31T09:00:00","date_gmt":"2026-07-31T14:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1897"},"modified":"2026-03-07T03:50:18","modified_gmt":"2026-03-07T08:50:18","slug":"cross-platform-referral-links","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/cross-platform-referral-links\/","title":{"rendered":"Cross-Platform Referral Links That Work Everywhere"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A referral link should work the same whether the recipient is on iOS, Android, or web. Tap the link, see the referral content, and attribute the referral to the sender. In practice, each platform handles URLs differently, and the recipient might not have the app installed. This article covers how to build referral links that handle all these cases.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For referral deep link mechanics, see <a href=\"https:\/\/tolinku.com\/blog\/referral-deep-links\/\">how referral deep links work: end-to-end guide<\/a>. For building effective referral programs, see <a href=\"https:\/\/tolinku.com\/blog\/building-referral-programs-that-work\/\">building referral programs that actually work<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A referral link like <code>https:\/\/yourdomain.com\/referral\/user123<\/code> needs to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the native app if installed (iOS or Android).<\/li>\n<li>Navigate to the correct screen with the referrer&#39;s ID.<\/li>\n<li>If the app is not installed, take the user to the app store or a landing page.<\/li>\n<li>After installation, still attribute the referral to <code>user123<\/code>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Each requirement has platform-specific challenges:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Requirement<\/th>\n<th>iOS<\/th>\n<th>Android<\/th>\n<th>Web<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Open app<\/td>\n<td>Universal Links<\/td>\n<td>App Links<\/td>\n<td>N\/A<\/td>\n<\/tr>\n<tr>\n<td>Navigate to screen<\/td>\n<td>AppDelegate\/SceneDelegate<\/td>\n<td>Intent<\/td>\n<td>URL routing<\/td>\n<\/tr>\n<tr>\n<td>App not installed<\/td>\n<td>Fallback to App Store<\/td>\n<td>Fallback to Play Store<\/td>\n<td>Show landing page<\/td>\n<\/tr>\n<tr>\n<td>Post-install attribution<\/td>\n<td>Deferred deep link<\/td>\n<td>Deferred deep link<\/td>\n<td>Cookie\/localStorage<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Referral Link Structure<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use a consistent URL format that works across platforms:<\/p>\n\n\n\n<pre><code>https:\/\/yourdomain.com\/referral\/{referrerId}?campaign={campaignId}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The URL is the same for all platforms. Platform detection happens server-side or client-side when the link is opened.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Server-Side Detection<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When the URL is opened in a browser (app not installed), detect the platform and redirect:<\/p>\n\n\n\n<pre><code class=\"language-typescript\">\/\/ Server route handler\napp.get(&#39;\/referral\/:referrerId&#39;, (req, res) =&gt; {\n  const { referrerId } = req.params;\n  const userAgent = req.headers[&#39;user-agent&#39;] || &#39;&#39;;\n\n  \/\/ If the app handles this via Universal Links \/ App Links,\n  \/\/ this handler won&#39;t be called. This runs only when the app\n  \/\/ isn&#39;t installed or links aren&#39;t verified.\n\n  if (\/iPhone|iPad|iPod\/.test(userAgent)) {\n    \/\/ iOS: redirect to App Store with context\n    res.redirect(\n      `https:\/\/apps.apple.com\/app\/id${APP_STORE_ID}?referrer=${referrerId}`\n    );\n  } else if (\/Android\/.test(userAgent)) {\n    \/\/ Android: redirect to Play Store with referrer\n    res.redirect(\n      `https:\/\/play.google.com\/store\/apps\/details?id=${PACKAGE_NAME}&amp;referrer=${referrerId}`\n    );\n  } else {\n    \/\/ Web: show referral landing page\n    res.render(&#39;referral-landing&#39;, { referrerId });\n  }\n});\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Native App Handling<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">iOS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Configure Universal Links so <code>https:\/\/yourdomain.com\/referral\/*<\/code> opens the app:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">AASA file:<\/p>\n\n\n\n<pre><code class=\"language-json\">{\n  &quot;applinks&quot;: {\n    &quot;details&quot;: [{\n      &quot;appIDs&quot;: [&quot;TEAMID.com.yourcompany.yourapp&quot;],\n      &quot;components&quot;: [\n        { &quot;\/&quot;: &quot;\/referral\/*&quot; }\n      ]\n    }]\n  }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Handle in the app:<\/p>\n\n\n\n<pre><code class=\"language-swift\">func application(_ application: UIApplication,\n                 continue userActivity: NSUserActivity,\n                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -&gt; Void) -&gt; Bool {\n    guard let url = userActivity.webPageUrl,\n          let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {\n        return false\n    }\n\n    let path = components.path\n    if path.hasPrefix(&quot;\/referral\/&quot;) {\n        let referrerId = String(path.dropFirst(&quot;\/referral\/&quot;.count))\n        handleReferral(referrerId: referrerId)\n        return true\n    }\n\n    return false\n}\n\nfunc handleReferral(referrerId: String) {\n    \/\/ Store the referral\n    UserDefaults.standard.set(referrerId, forKey: &quot;pending_referrer&quot;)\n\n    \/\/ Navigate to referral welcome screen\n    let vc = ReferralWelcomeViewController(referrerId: referrerId)\n    rootNavigationController?.pushViewController(vc, animated: true)\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Android<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Intent filter:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n    &lt;data android:scheme=&quot;https&quot;\n          android:host=&quot;yourdomain.com&quot;\n          android:pathPrefix=&quot;\/referral&quot; \/&gt;\n&lt;\/intent-filter&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Handle in the activity:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    handleReferralIntent(intent)\n}\n\noverride fun onNewIntent(intent: Intent) {\n    super.onNewIntent(intent)\n    handleReferralIntent(intent)\n}\n\nprivate fun handleReferralIntent(intent: Intent) {\n    val uri = intent.data ?: return\n    if (uri.path?.startsWith(&quot;\/referral\/&quot;) == true) {\n        val referrerId = uri.lastPathSegment ?: return\n        handleReferral(referrerId)\n    }\n}\n\nprivate fun handleReferral(referrerId: String) {\n    \/\/ Store the referral\n    getSharedPreferences(&quot;referral&quot;, MODE_PRIVATE)\n        .edit()\n        .putString(&quot;pending_referrer&quot;, referrerId)\n        .apply()\n\n    \/\/ Navigate to referral screen\n    val intent = Intent(this, ReferralWelcomeActivity::class.java).apply {\n        putExtra(&quot;referrer_id&quot;, referrerId)\n    }\n    startActivity(intent)\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Deferred Deep Linking<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The hardest case: the user taps the referral link but does not have the app installed. After they install and open the app, the referral should still be attributed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Deferred Deep Links Work<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User taps <code>https:\/\/yourdomain.com\/referral\/user123<\/code>.<\/li>\n<li>App not installed; user lands on a web page or app store.<\/li>\n<li>The referral context (referrer ID, timestamp, campaign) is stored server-side, associated with a fingerprint (IP, device info, timestamp).<\/li>\n<li>User installs the app and opens it.<\/li>\n<li>On first launch, the app calls a server endpoint with its fingerprint.<\/li>\n<li>Server matches the fingerprint and returns the original referral context.<\/li>\n<li>App processes the referral.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Server-Side Fingerprint Storage<\/h3>\n\n\n\n<pre><code class=\"language-typescript\">\/\/ When the referral link is opened in a browser\napp.get(&#39;\/referral\/:referrerId&#39;, async (req, res) =&gt; {\n  const { referrerId } = req.params;\n\n  \/\/ Store fingerprint for deferred matching\n  const fingerprint = {\n    ip: req.ip,\n    userAgent: req.headers[&#39;user-agent&#39;],\n    timestamp: Date.now(),\n    referrerId,\n    campaign: req.query.campaign\n  };\n\n  await storeDeferredLink(fingerprint);\n\n  \/\/ Redirect to app store or landing page\n  redirectByPlatform(req, res, referrerId);\n});\n\n\/\/ When the app calls on first launch\napp.post(&#39;\/api\/deferred-link&#39;, async (req, res) =&gt; {\n  const { ip, userAgent, deviceId } = req.body;\n\n  const match = await findDeferredLink({\n    ip,\n    userAgent,\n    maxAge: 48 * 60 * 60 * 1000 \/\/ 48 hours\n  });\n\n  if (match) {\n    res.json({\n      found: true,\n      referrerId: match.referrerId,\n      campaign: match.campaign\n    });\n    \/\/ Mark as consumed\n    await markDeferredLinkUsed(match.id);\n  } else {\n    res.json({ found: false });\n  }\n});\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Client-Side (First Launch)<\/h3>\n\n\n\n<pre><code class=\"language-swift\">\/\/ iOS: check for deferred link on first launch\nfunc checkDeferredLink() {\n    guard !UserDefaults.standard.bool(forKey: &quot;deferred_link_checked&quot;) else {\n        return\n    }\n\n    UserDefaults.standard.set(true, forKey: &quot;deferred_link_checked&quot;)\n\n    let body: [String: Any] = [\n        &quot;deviceId&quot;: UIDevice.current.identifierForVendor?.uuidString ?? &quot;&quot;,\n        &quot;userAgent&quot;: &quot;iOS\/\\(UIDevice.current.systemVersion)&quot;\n    ]\n\n    \/\/ POST to your server\n    apiClient.post(&quot;\/api\/deferred-link&quot;, body: body) { result in\n        if let referrerId = result.referrerId {\n            self.handleReferral(referrerId: referrerId)\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Attribution Consistency<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Referral attribution must be consistent regardless of how the user arrived. Track the referral source for analytics:<\/p>\n\n\n\n<pre><code class=\"language-typescript\">interface ReferralAttribution {\n  referrerId: string;\n  platform: &#39;ios&#39; | &#39;android&#39; | &#39;web&#39;;\n  method: &#39;direct&#39; | &#39;deferred&#39;;   \/\/ Direct = app was installed; Deferred = installed after\n  campaign?: string;\n  timestamp: number;\n}\n\nfunction attributeReferral(attribution: ReferralAttribution) {\n  \/\/ Store locally\n  localStorage.setItem(&#39;referral&#39;, JSON.stringify(attribution));\n\n  \/\/ Send to server\n  api.post(&#39;\/api\/referral\/attribute&#39;, attribution);\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Preventing Double Attribution<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A referral should only be attributed once. Guard against duplicate attributions:<\/p>\n\n\n\n<pre><code class=\"language-typescript\">async function processReferral(referrerId: string, method: string) {\n  \/\/ Check if already attributed\n  const existing = await getReferralAttribution(userId);\n  if (existing) {\n    console.log(&#39;Referral already attributed:&#39;, existing.referrerId);\n    return;\n  }\n\n  \/\/ Store attribution\n  await storeReferralAttribution({\n    userId,\n    referrerId,\n    method,\n    timestamp: Date.now()\n  });\n\n  \/\/ Credit the referrer\n  await creditReferrer(referrerId);\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Landing Pages for Web Users<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a desktop user clicks a referral link, they cannot install a mobile app. Show a landing page that:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Explains the referral offer.<\/li>\n<li>Provides app store links (with referral context).<\/li>\n<li>Allows web signup (if applicable).<\/li>\n<\/ol>\n\n\n\n<pre><code class=\"language-html\">&lt;!-- referral-landing.html --&gt;\n&lt;div class=&quot;referral-page&quot;&gt;\n  &lt;h1&gt;You&#39;ve been invited!&lt;\/h1&gt;\n  &lt;p&gt;Your friend shared something with you.&lt;\/p&gt;\n\n  &lt;div class=&quot;app-links&quot;&gt;\n    &lt;a href=&quot;https:\/\/apps.apple.com\/app\/idYOUR_ID&quot;\n       class=&quot;app-store-badge&quot;&gt;\n      Download on the App Store\n    &lt;\/a&gt;\n    &lt;a href=&quot;https:\/\/play.google.com\/store\/apps\/details?id=com.yourapp&quot;\n       class=&quot;play-store-badge&quot;&gt;\n      Get it on Google Play\n    &lt;\/a&gt;\n  &lt;\/div&gt;\n\n  &lt;p&gt;Or &lt;a href=&quot;\/signup?ref=USER123&quot;&gt;sign up on the web&lt;\/a&gt;&lt;\/p&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing Referral Links<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Direct Attribution (App Installed)<\/h3>\n\n\n\n<pre><code class=\"language-bash\"># iOS\nxcrun simctl openurl booted &quot;https:\/\/yourdomain.com\/referral\/user123?campaign=summer&quot;\n\n# Android\nadb shell am start -a android.intent.action.VIEW \\\n  -d &quot;https:\/\/yourdomain.com\/referral\/user123?campaign=summer&quot; \\\n  -c android.intent.category.BROWSABLE\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Verify:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The app opens to the referral screen.<\/li>\n<li>The referrer ID <code>user123<\/code> is stored.<\/li>\n<li>Analytics show <code>method: direct<\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Deferred Attribution (App Not Installed)<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the referral link in a mobile browser.<\/li>\n<li>Verify the user lands on the app store or landing page.<\/li>\n<li>Install the app.<\/li>\n<li>Open the app and verify the referral is attributed.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Web Attribution<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the referral link on desktop.<\/li>\n<li>Verify the landing page shows.<\/li>\n<li>Click &quot;sign up on web.&quot;<\/li>\n<li>Verify the referrer ID is passed to the signup form.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Tolinku for Referral Links<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/tolinku.com\/features\/referrals\">Tolinku<\/a> provides built-in <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/referrals\/\">referral program<\/a> support with <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/referrals\/referral-links\/\">referral links<\/a> that work across platforms. Tolinku handles deferred deep linking, so referral attribution works even when users install the app after clicking. The platform also provides a <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/referrals\/leaderboard\/\">referral leaderboard<\/a> and <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/referrals\/rewards-and-attribution\/\">rewards tracking<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For referral mechanics, see <a href=\"https:\/\/tolinku.com\/blog\/referral-deep-links\/\">how referral deep links work: end-to-end guide<\/a>. For the cross-platform deep linking guide, see <a href=\"https:\/\/tolinku.com\/blog\/cross-platform-deep-linking-guide\/\">cross-platform deep linking guide for 2026<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Build referral links that work across iOS, Android, and web. Handle platform detection, deferred linking, and consistent attribution.<\/p>\n","protected":false},"author":2,"featured_media":1896,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Cross-Platform Referral Links That Work Everywhere","rank_math_description":"Build referral links that work across iOS, Android, and web. Handle platform detection, deferred linking, and consistent attribution.","rank_math_focus_keyword":"cross-platform referral links","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-cross-platform-referral-links.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-cross-platform-referral-links.png","footnotes":""},"categories":[15],"tags":[25,28,156,20,21,113,24,69,45,41],"class_list":["post-1897","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-android","tag-attribution","tag-cross-platform","tag-deep-linking","tag-deferred-deep-linking","tag-growth","tag-ios","tag-mobile-development","tag-referrals","tag-web-to-app"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1897","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1897"}],"version-history":[{"count":1,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1897\/revisions"}],"predecessor-version":[{"id":1898,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1897\/revisions\/1898"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1896"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1897"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1897"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1897"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}