<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[App Link Host Blog]]></title><description><![CDATA[Thoughts on building and maintaining Universal Links on iOS.]]></description><link>https://blog.applinkhost.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 20:57:25 GMT</lastBuildDate><atom:link href="https://blog.applinkhost.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Implement Universal Links on iOS, iPadOS, and macOS]]></title><description><![CDATA[Universal Links let you deep-link into your app from anywhere a URL can be tapped: Safari, Messages, Notes, other apps.
If your app is installed, iOS/iPadOS/macOS opens it and passes in the URL to your app. If not, the link loads in Safari.
Step 1. G...]]></description><link>https://blog.applinkhost.com/implement-universal-links-on-ios-ipados-and-macos</link><guid isPermaLink="true">https://blog.applinkhost.com/implement-universal-links-on-ios-ipados-and-macos</guid><category><![CDATA[universallinks]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Daniel Yoo]]></dc:creator><pubDate>Thu, 01 May 2025 04:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Universal Links let you deep-link into your app from anywhere a URL can be tapped: Safari, Messages, Notes, other apps.</p>
<p>If your app is installed, iOS/iPadOS/macOS opens it and passes in the URL to your app. If not, the link loads in Safari.</p>
<h2 id="heading-step-1-get-identifiers"><strong>Step 1. Get Identifiers</strong></h2>
<p>First, you need to get the identifiers for your app that will be used in later steps.</p>
<ol>
<li><p>Go to <a target="_blank" href="https://developer.apple.com/account/resources/identifiers/list"><strong>Apple Developer &gt; Identifiers</strong></a>.</p>
</li>
<li><p>Click your app, then grab <strong>App ID Prefix</strong> and <strong>Bundle ID</strong>. You’ll use these in your Apple-App-Site-Association file.</p>
</li>
</ol>
<h2 id="heading-step-2-create-apple-app-site-association-aasa-file"><strong>Step 2. Create Apple-App-Site-Association (AASA) file</strong></h2>
<p>Create a file named <code>apple-app-site-association</code> (no .json extension). Use this structure:</p>
<pre><code class="lang-plaintext">{
  "applinks": {
    "details": [
      {
        "appID": "ABCDE12345.com.example.app",
        "components": [
          {
            "/": "/*",
            "comment": "Matches all urls in the domain."
          }
        ]
      }
    ]
  }
}
</code></pre>
<p>Replace ABCDE12345.com.example.app with your <code>&lt;App ID Prefix&gt;.&lt;Bundle ID&gt;</code>from Step 1.</p>
<h2 id="heading-step-3-register-a-domain"><strong>Step 3. Register a Domain</strong></h2>
<p>Register a domain and point it to a host that supports:</p>
<ul>
<li><p>HTTPS (with valid SSL cert)</p>
</li>
<li><p>Serving static files without redirects</p>
</li>
</ul>
<h2 id="heading-step-4-host-the-aasa-file"><strong>Step 4. Host the AASA file</strong></h2>
<p>Upload the AASA file to: <a target="_blank" href="https://example.com/.well-known/apple-app-site-association"><strong>https://example.com/.well-known/apple-app-site-association</strong></a></p>
<p>It must be:</p>
<ul>
<li><p>Accessible via HTTPS</p>
</li>
<li><p>No redirects</p>
</li>
<li><p>No .json extension</p>
</li>
</ul>
<h2 id="heading-step-5-configure-your-app"><strong>Step 5. Configure your app</strong></h2>
<p>In Xcode, under <strong>Signing &amp; Capabilities</strong>:</p>
<ul>
<li><p>Add <strong>Associated Domains</strong></p>
</li>
<li><p>Add <code>applinks:example.com</code>, but with the domain you got in Step 3.</p>
</li>
</ul>
<p>Optional: repeat for any additional domains.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747648441415/c3f81d23-f00b-461a-ace4-cec3c75b0346.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-step-6-handle-universal-links-in-your-app"><strong>Step 6. Handle universal links in your app</strong></h2>
<h3 id="heading-if-your-app-uses-scenes"><strong>If your app uses Scenes</strong></h3>
<p>In your SceneDelegate:</p>
<pre><code class="lang-swift"><span class="hljs-comment">/// This is called if your your app needs to launch when a universal link is delivered.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">scene</span><span class="hljs-params">(<span class="hljs-number">_</span> scene: UIScene, willConnectTo
           session: UISceneSession,
           options connectionOptions: UIScene.ConnectionOptions)</span></span> {    
    <span class="hljs-comment">// Get URL components from the incoming user activity.</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> userActivity = connectionOptions.userActivities.first,
        userActivity.activityType == <span class="hljs-type">NSUserActivityTypeBrowsingWeb</span>,
        <span class="hljs-keyword">let</span> incomingURL = userActivity.webpageURL <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span>
    }
    <span class="hljs-comment">// Route to the correct screen in your app</span>
    handleUniversalLink(url: incomingURL)
}

<span class="hljs-comment">/// This is called if your app is in memory when a universal link is delivered.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">scene</span><span class="hljs-params">(
    <span class="hljs-number">_</span> scene: UIScene,
    <span class="hljs-keyword">continue</span> userActivity: NSUserActivity
)</span></span> {
  <span class="hljs-keyword">guard</span> userActivity.activityType == <span class="hljs-type">NSUserActivityTypeBrowsingWeb</span>,
        <span class="hljs-keyword">let</span> incomingURL = userActivity.webpageURL <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }

  <span class="hljs-comment">// Route to the correct screen in your app</span>
  handleUniversalLink(url: incomingURL)
}
</code></pre>
<h3 id="heading-if-your-app-doesnt-use-scenes"><strong>If your app doesn’t use Scenes</strong></h3>
<p>In your AppDelegate:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication,
  <span class="hljs-keyword">continue</span> userActivity: NSUserActivity,
  restorationHandler: @escaping <span class="hljs-params">([UIUserActivityRestoring]?)</span></span></span> -&gt; <span class="hljs-type">Void</span>) -&gt; <span class="hljs-type">Bool</span> {
  <span class="hljs-keyword">guard</span> userActivity.activityType == <span class="hljs-type">NSUserActivityTypeBrowsingWeb</span>,
        <span class="hljs-keyword">let</span> incomingURL = userActivity.webpageURL <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }

  <span class="hljs-comment">// Route to the correct screen in your app</span>
  handleUniversalLink(url: incomingURL)
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
}
</code></pre>
<h3 id="heading-if-you-have-a-macos-app"><strong>If you have a macOS app</strong></h3>
<p>In your AppDelegate:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: NSApplication,
                     <span class="hljs-keyword">continue</span> userActivity: NSUserActivity,
                     restorationHandler: @escaping <span class="hljs-params">([NSUserActivityRestoring])</span></span></span> -&gt; <span class="hljs-type">Void</span>) -&gt; <span class="hljs-type">Bool</span>
{
  <span class="hljs-comment">// Get URL components from the incoming user activity.</span>
  <span class="hljs-keyword">guard</span> userActivity.activityType == <span class="hljs-type">NSUserActivityTypeBrowsingWeb</span>,
    <span class="hljs-keyword">let</span> incomingURL = userActivity.webpageURL <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
  }
  <span class="hljs-comment">// Route to the correct screen in your app</span>
  handleUniversalLink(url: incomingURL)
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
}
</code></pre>
<h2 id="heading-step-7-test-your-universal-links"><strong>Step 7. Test your universal links</strong></h2>
<ol>
<li><p>Install your app on a device.</p>
</li>
<li><p>In the Apple Notes app, create some sample links that you want to test, like <code>https://example.com/mylink</code>.</p>
</li>
<li><p>Tap that link and if all went well, it should open in your app!</p>
</li>
</ol>
<h2 id="heading-external-resources"><strong>External Resources</strong></h2>
<ul>
<li><p><a target="_blank" href="https://developer.apple.com/documentation/xcode/supporting-associated-domains"><strong>Supporting associated domains</strong></a></p>
</li>
<li><p><a target="_blank" href="https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app"><strong>Supporting universal links in your app</strong></a></p>
</li>
<li><p><a target="_blank" href="https://developer.apple.com/documentation/technotes/tn3155-debugging-universal-links"><strong>Debugging universal links</strong></a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>