Skip to content

Instantly share code, notes, and snippets.

@mat
Last active November 9, 2024 13:30
Show Gist options
  • Save mat/e35393e9dfd9d7fb0972 to your computer and use it in GitHub Desktop.
Save mat/e35393e9dfd9d7fb0972 to your computer and use it in GitHub Desktop.
apple-app-site-association —with examples

“apple-app-site-association” file

One file for each domain, both www.example.com and example.com need separate files:

{
    "applinks": {
        "apps": [],
        "details": {
            "9JA89QQLNQ.com.apple.wwdc": {
                "paths": [
                    "/wwdc/news/",
                    "/videos/wwdc/2015/*"
                ]
            }
        }
    }
}

When a URL cannot be opened

  • Fall back gracefully
  • If cannot handle, open Safari UIApplication.sharedApplication().openURL(webURL)

Smart App Banners

There is no guarantee that the user experience with custom URL schemes will remain the same in the future. Smart App Banners afford the preferred experience.

https://developer.apple.com/videos/wwdc/2015/?id=509

<head>
  <meta name="apple-itunes-app" content="app-id=640199958, app-argument=https://developer.apple.com/wwdc/schedule, affiliate- data=optionalAffiliateData">
</head>

How often is apple-app-site-association updated by app on device?

I've found that the apple-app-site-association file is fetched when the app is installed on the device. So essentially, every install/update will trigger a download of the file. You can simulate this by deleting the app from your device and reinstalling it.

https://forums.developer.apple.com/thread/6972

{
"activitycontinuation": {
"apps": [
"5LL7P8E8RA.com.airbnb.app",
"5LL7P8E8RA.com.airbnb.appdev",
"5LL7P8E8RA.com.airbnb.appbeta",
"5LL7P8E8RA.com.airbnb.appenterprise",
"9BPWRS9A4J.com.airbnb.app",
"9BPWRS9A4J.com.airbnb.appdev",
"9BPWRS9A4J.com.airbnb.appbeta",
"9BPWRS9A4J.com.airbnb.appenterprise",
"KYLDQ3QJT3.com.airbnb.app",
"KYLDQ3QJT3.com.airbnb.appdev",
"KYLDQ3QJT3.com.airbnb.appbeta",
"KYLDQ3QJT3.com.airbnb.appenterprise"
]
},
"webcredentials": {
"apps": [
"5LL7P8E8RA.com.airbnb.app",
"5LL7P8E8RA.com.airbnb.appdev",
"5LL7P8E8RA.com.airbnb.appbeta",
"5LL7P8E8RA.com.airbnb.appenterprise",
"9BPWRS9A4J.com.airbnb.app",
"9BPWRS9A4J.com.airbnb.appdev",
"9BPWRS9A4J.com.airbnb.appbeta",
"9BPWRS9A4J.com.airbnb.appenterprise",
"KYLDQ3QJT3.com.airbnb.app",
"KYLDQ3QJT3.com.airbnb.appdev",
"KYLDQ3QJT3.com.airbnb.appbeta",
"KYLDQ3QJT3.com.airbnb.appenterprise"
]
}
}
{
"applinks" :
{
"apps" : [],
"details" :
{
"9JA89QQLNQ.developer.apple.wwdc-Debug" :
{
"paths" :
[
"/videos/wwdc/2011/*",
"/videos/wwdc/2012/*",
"/videos/wwdc/2013/*",
"/videos/wwdc/2014/*",
"/videos/wwdc/2015/*"
]
},
"9JA89QQLNQ.developer.apple.wwdc-Internal" :
{
"paths" :
[
"/videos/wwdc/2011/*",
"/videos/wwdc/2012/*",
"/videos/wwdc/2013/*",
"/videos/wwdc/2014/*",
"/videos/wwdc/2015/*"
]
},
"9JA89QQLNQ.developer.apple.wwdc-Release" :
{
"paths" :
[
"/videos/wwdc/2011/*",
"/videos/wwdc/2012/*",
"/videos/wwdc/2013/*",
"/videos/wwdc/2014/*",
"/videos/wwdc/2015/*"
]
},
}
}
}
{
"activitycontinuation": {
"apps": [
"7QXYLT27C4.fm.overcast.overcast"
]
},
"webcredentials": {
"apps": [
"7QXYLT27C4.fm.overcast.overcast"
]
}
}
@eyekay234
Copy link

@gary-archer @rromanchuk Thanks a lot for the help as i was able to resolve this

@muizidn
Copy link

muizidn commented Oct 3, 2022

Hello. Thank you for sharing this. I find that this different format really annoying because in my case, the one with components like in the docs doesn't work in iOS15.
If anyone want to try fast, one can use this little project of mine. https://github.com/muizidn/apple-app-site-association.test

@walteh
Copy link

walteh commented Nov 13, 2022

Another option for anyone who needs it:

You can create a CloudFront Function and associate it to your distribution's cache behavior as a viewer-request function to bypass hosting the file completely.

function handler(event) {
	if (event.request.uri.endsWith("apple-app-site-association")) {
		return {
			statusCode : 200,
			statusDescription : "OK",
			headers : { "content-type" : { value : "application/json" } },
			body : {
				encoding : "text",
				data :  "{\"applinks\":{\"details\":[{\"appIDs\":[\"TEAMID.com.example.app\"],\"components\":[{\"/\":\"/test/*\",\"comment\":\"Matches any URL with a path that starts with /test/.\"}]}]},\"webcredentials\":{\"apps\":[\"TEAMID.com.example.app\"]}}"
			}
		 }
	}
	return event.request;
}

@wwwmaster1
Copy link

this is the best method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment