{"id":1542,"date":"2026-06-22T09:00:00","date_gmt":"2026-06-22T14:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1542"},"modified":"2026-03-07T03:49:33","modified_gmt":"2026-03-07T08:49:33","slug":"deep-linking-post-cookie-world","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/deep-linking-post-cookie-world\/","title":{"rendered":"Deep Linking in the Post-Cookie World"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Third-party cookies are disappearing. Safari blocked them years ago. Firefox followed. Chrome is phasing them out through the Privacy Sandbox. For deep linking, this matters because many deferred deep linking and attribution systems relied on third-party cookies to match a web click to an app install.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The core deep linking functionality (opening the right content in the right app) is completely unaffected. Universal Links and App Links do not use cookies. What changes is the attribution and tracking layer that sits on top of deep links. This guide covers how to adapt. For privacy changes broadly, see <a href=\"https:\/\/tolinku.com\/blog\/privacy-changes-deep-linking\/\">privacy changes and their impact on deep linking<\/a>. For deferred linking without fingerprinting, see <a href=\"https:\/\/tolinku.com\/blog\/deferred-linking-without-fingerprinting\/\">deferred deep linking without fingerprinting<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Third-Party Cookies Did for Deep Linking<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">The Old Model<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before cookie restrictions, a typical deferred deep linking flow looked like this:<\/p>\n\n\n\n<pre><code>1. User clicks deep link on Website A\n2. Deep link service drops a third-party cookie (on its own domain)\n3. User goes to the app store, installs the app\n4. App opens, SDK checks for the cookie (via a web view or redirect)\n5. Cookie matches \u2192 user is routed to the original content\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The third-party cookie was the matching mechanism. It connected step 1 (web click) to step 5 (app open) across different contexts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why This Broke<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Third-party cookies are blocked because they enable cross-site tracking. A cookie from <code>tracking.example.com<\/code> set on Site A could be read when the user visits Site B, creating a browsing profile across sites.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Deep link services used this same mechanism for legitimate purposes (matching a click to an install), but browsers do not distinguish between &quot;good&quot; and &quot;bad&quot; third-party cookies. All are blocked.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">First-Party Data Strategies<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">URL Parameter Passing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The simplest post-cookie approach: carry attribution data in the URL itself.<\/p>\n\n\n\n<pre><code>Web page click \u2192 https:\/\/links.yourapp.com\/products\/shoes?click_id=abc123&amp;source=blog\n  \u2192 App store (referrer carries parameters on Android)\n    \u2192 App opens \u2192 reads click_id from referrer \u2192 looks up click context server-side\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No cookies needed. The attribution data travels with the link.<\/p>\n\n\n\n<pre><code class=\"language-javascript\">\/\/ Server: generate a click with server-side context\napp.get(&#39;\/link\/:slug&#39;, async (req, res) =&gt; {\n  const clickId = crypto.randomUUID();\n\n  \/\/ Store click context server-side\n  await clickStore.save({\n    clickId,\n    slug: req.params.slug,\n    source: req.query.utm_source,\n    campaign: req.query.utm_campaign,\n    ip: req.ip,\n    userAgent: req.headers[&#39;user-agent&#39;],\n    timestamp: Date.now()\n  });\n\n  \/\/ Build app store URL with click ID\n  const storeUrl = buildStoreUrl({\n    referrer: `click_id=${clickId}&amp;utm_source=${req.query.utm_source}`\n  });\n\n  res.redirect(302, storeUrl);\n});\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">First-Party Cookies<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">First-party cookies (set by your own domain) still work everywhere. If your deep link URL is on your own domain, you can use first-party cookies:<\/p>\n\n\n\n<pre><code class=\"language-javascript\">\/\/ Set a first-party cookie on your domain\napp.get(&#39;\/link\/:slug&#39;, (req, res) =&gt; {\n  const clickId = crypto.randomUUID();\n\n  res.cookie(&#39;tolk_click&#39;, clickId, {\n    maxAge: 30 * 24 * 60 * 60 * 1000, \/\/ 30 days\n    httpOnly: true,\n    secure: true,\n    sameSite: &#39;lax&#39;,\n    domain: &#39;.yourapp.com&#39; \/\/ your domain\n  });\n\n  \/\/ Continue with the redirect flow\n  redirectToAppOrStore(req, res, clickId);\n});\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the user later visits your website (on the same domain) after installing the app, the first-party cookie matches the click:<\/p>\n\n\n\n<pre><code class=\"language-javascript\">\/\/ On your website, after user installs and visits\napp.get(&#39;\/welcome-back&#39;, (req, res) =&gt; {\n  const clickId = req.cookies.tolk_click;\n  if (clickId) {\n    const originalClick = await clickStore.get(clickId);\n    \/\/ Match: this user came from our deep link campaign\n  }\n});\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Server-Side Click Matching<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Move the matching logic from the browser (cookies) to the server:<\/p>\n\n\n\n<pre><code class=\"language-javascript\">\/\/ Server-side click matching\nclass ClickMatcher {\n  async matchInstallToClick(installData) {\n    const { ip, userAgent, timestamp, referrer } = installData;\n\n    \/\/ 1. Try exact match via referrer (Android Install Referrer)\n    if (referrer) {\n      const clickId = new URLSearchParams(referrer).get(&#39;click_id&#39;);\n      if (clickId) {\n        return await this.getClick(clickId);\n      }\n    }\n\n    \/\/ 2. Try probabilistic match (within strict time window)\n    const recentClicks = await this.getRecentClicks({\n      ip,\n      userAgent,\n      maxAge: 60 * 60 * 1000 \/\/ 1 hour window\n    });\n\n    if (recentClicks.length === 1) {\n      return recentClicks[0]; \/\/ High confidence single match\n    }\n\n    \/\/ 3. No match found\n    return null;\n  }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Platform-Specific Solutions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Android: Install Referrer API<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Google Play&#39;s <a href=\"https:\/\/developer.android.com\/google\/play\/installreferrer\" rel=\"nofollow noopener\" target=\"_blank\">Install Referrer API<\/a> is the most reliable post-cookie attribution method on Android. It passes referral parameters through the install:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">val client = InstallReferrerClient.newBuilder(context).build()\nclient.startConnection(object : InstallReferrerStateListener {\n    override fun onInstallReferrerSetupFinished(responseCode: Int) {\n        if (responseCode == InstallReferrerResponse.OK) {\n            val details = client.installReferrer\n            val referrer = details.installReferrer\n            \/\/ referrer = &quot;click_id=abc123&amp;utm_source=blog&amp;utm_campaign=summer&quot;\n\n            val params = Uri.parse(&quot;?$referrer&quot;)\n            val clickId = params.getQueryParameter(&quot;click_id&quot;)\n            val source = params.getQueryParameter(&quot;utm_source&quot;)\n\n            \/\/ Fetch the original click context\n            fetchClickContext(clickId) { context -&gt;\n                navigateToContent(context.slug)\n            }\n        }\n        client.endConnection()\n    }\n\n    override fun onInstallReferrerServiceDisconnected() {}\n})\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is first-party Google data, privacy-compliant, and works without cookies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">iOS: Pasteboard and SKAdNetwork<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">iOS has no equivalent to the Install Referrer API. Alternatives:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pasteboard (clipboard):<\/strong> Copy a token to the clipboard on web click, read it in the app. Since iOS 16, users see a permission prompt for clipboard access, reducing reliability.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>SKAdNetwork:<\/strong> Provides aggregate campaign attribution (which campaign drove installs) but not user-level deep link matching. It does not help with deferred deep linking to specific content.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>App Store overlay:<\/strong> When Apple&#39;s Smart App Banner is used, the <code>app-argument<\/code> parameter can carry a URL:<\/p>\n\n\n\n<pre><code class=\"language-html\">&lt;meta name=&quot;apple-itunes-app&quot; content=&quot;app-id=YOUR_ID, app-argument=https:\/\/yourapp.com\/products\/shoes&quot;&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the user installs via the Smart App Banner, the app receives the <code>app-argument<\/code> URL on launch.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Attribution Models in the Post-Cookie World<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Deterministic vs. Probabilistic<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Type<\/th>\n<th>Accuracy<\/th>\n<th>Privacy<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Install Referrer (Android)<\/td>\n<td>Deterministic<\/td>\n<td>~100%<\/td>\n<td>First-party<\/td>\n<\/tr>\n<tr>\n<td>First-party cookies<\/td>\n<td>Deterministic<\/td>\n<td>~95%<\/td>\n<td>First-party<\/td>\n<\/tr>\n<tr>\n<td>User login matching<\/td>\n<td>Deterministic<\/td>\n<td>~100%<\/td>\n<td>First-party<\/td>\n<\/tr>\n<tr>\n<td>Server-side IP+UA<\/td>\n<td>Probabilistic<\/td>\n<td>~60-80%<\/td>\n<td>Gray area<\/td>\n<\/tr>\n<tr>\n<td>Fingerprinting<\/td>\n<td>Probabilistic<\/td>\n<td>~70-85%<\/td>\n<td>Restricted<\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Self-Reported Attribution<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ask users directly how they found your app:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">\/\/ On first app launch\nclass OnboardingActivity : AppCompatActivity() {\n    fun showAttributionSurvey() {\n        val options = listOf(\n            &quot;Search (Google, Bing)&quot;,\n            &quot;Social media&quot;,\n            &quot;Friend or colleague&quot;,\n            &quot;Blog post or article&quot;,\n            &quot;QR code&quot;,\n            &quot;Advertisement&quot;,\n            &quot;Other&quot;\n        )\n        showSurveyDialog(&quot;How did you hear about us?&quot;, options) { selected -&gt;\n            analytics.trackSelfReportedAttribution(selected)\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is privacy-friendly and provides qualitative data that automated attribution misses.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building a Cookie-Free Deep Link System<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Architecture<\/h3>\n\n\n\n<pre><code>Web click\n  \u2192 Server generates click ID, stores context\n    \u2192 URL carries click ID to app store\n      \u2192 Android: Install Referrer passes click ID\n      \u2192 iOS: Smart App Banner app-argument carries URL\n        \u2192 App opens, reads click ID\n          \u2192 Server looks up click context\n            \u2192 App navigates to original content\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">No cookies at any step. The attribution data flows through URL parameters and platform APIs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Implementation Checklist<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate unique click IDs server-side for every deep link click.<\/li>\n<li>Store click context (source, campaign, content, timestamp) server-side.<\/li>\n<li>Pass click ID through the install flow via URL parameters.<\/li>\n<li>On Android, read the Install Referrer to get the click ID.<\/li>\n<li>On iOS, use Smart App Banner <code>app-argument<\/code> or first-party cookies on your domain.<\/li>\n<li>On app launch, fetch click context from your server using the click ID.<\/li>\n<li>Navigate to the original content.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Tolinku Post-Cookie Attribution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/tolinku.com\/features\/deep-linking\">Tolinku<\/a> uses first-party data for deep link attribution. Deep links use your own custom domain, which means first-party cookies are available. Click context is stored server-side, and attribution data flows through URL parameters and platform APIs (Install Referrer on Android, Smart App Banner on iOS).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Configure your attribution in the <a href=\"https:\/\/tolinku.com\/docs\/concepts\/attribution\/\">Tolinku dashboard<\/a>. For the broader privacy strategy, see <a href=\"https:\/\/tolinku.com\/blog\/privacy-changes-deep-linking\/\">privacy changes and their impact on deep linking<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Adapt deep linking strategies for a world without third-party cookies. Use first-party data, server-side tracking, and privacy-safe attribution.<\/p>\n","protected":false},"author":2,"featured_media":1541,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Deep Linking in the Post-Cookie World","rank_math_description":"Adapt deep linking strategies for a world without third-party cookies. Use first-party data, server-side tracking, and privacy-safe attribution.","rank_math_focus_keyword":"deep linking post-cookie","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-deep-linking-post-cookie-world.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-deep-linking-post-cookie-world.png","footnotes":""},"categories":[11],"tags":[28,402,20,404,110,69,36,405],"class_list":["post-1542","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-deep-linking","tag-attribution","tag-cookies","tag-deep-linking","tag-first-party-data","tag-marketing","tag-mobile-development","tag-privacy","tag-server-side-tracking"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1542","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=1542"}],"version-history":[{"count":3,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1542\/revisions"}],"predecessor-version":[{"id":2628,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1542\/revisions\/2628"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1541"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}