For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Dashboard
GuidesAPI ReferenceSDKs
GuidesAPI ReferenceSDKs
  • SDKs
      • Android
      • iOS
        • Set up Universal Links
        • Migrate from custom schemes (iOS)
      • React Native
      • Cordova
Dashboard
Products
PaymentsDataPayouts
Company
AboutCareersContact Sales

Terms of Use | Privacy Policy | © 2026 Trustly, Inc.

Developer-friendly docs for your API
GitHub|Contact Support|Business Help Center|Merchant Portal
Terms of Use|Privacy Policy|© 2026 Trustly, Inc.
Developer-friendly docs for your API
LogoLogo
North AmericaEurope
North AmericaEurope
On this page
  • Required changes
  • Code migration strategy
  • Implement the Universal Link handler
  • Update the custom URL Scheme handler
  • Create the unified router
SDKsMobileiOS

Migrate from custom schemes (iOS)

|View as Markdown|Open in Claude|
Was this page helpful?
Previous

Set up Universal Links

Next

React Native

Built with

If your application currently uses custom URL schemes such as myapp://product?id=123, Trustly recommends migrating to Universal Links. Custom schemes are less secure and provide a poorer user experience when compared to Universal Links.

To avoid customer disruptions, implement Universal Links as the primary deep linking method while keeping the custom scheme active as a fallback for older app versions or specific internal routing cases.

Required changes

The migration process involves shifting your infrastructure from a local, app-specific protocol to a verified, web-based standard.

The following table summarizes the key changes required to move from custom URL schemes to Universal Links.

ComponentRequired Change
Deep Link URLChange from a custom protocol (myapp://path) to a standard web URL ( https://yourdomain.com/path).
Web ServerYou must host the apple-app-site-association file and serve content over HTTPS.
Xcode ConfigurationYou must add the Associated Domains capability to your target.
Code ImplementationChange the primary entry point from openURL to continueUserActivity.

Code migration strategy

When migrating, the most efficient approach is to create a unified route handler. This allows your app to accept links from both sources (Universal Links and custom URL schemes) and funnel them into a single logic flow. This ensures that users land on the same screen regardless of which link type they click.

Implement the Universal Link handler

Implement the scene(_:continue:) method in your SceneDelegate to intercept the modern HTTPS links. Instead of handling the navigation logic directly, the URL is extracted and passed to a shared helper function. For example:

1func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
2 // Validate that this is a Universal Link
3 guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
4 let incomingURL = userActivity.webpageURL else {
5 return
6 }
7
8 // Pass the URL to your unified router
9 handleDeepLink(url: incomingURL)
10}

Update the custom URL Scheme handler

Update your existing scene(_:openURLContexts:) method to pass the legacy URL to the shared helper function instead of duplicating your routing logic. For example:

1func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
2 guard let urlContext = URLContexts.first else {
3 return
4 }
5
6 let incomingURL = urlContext.url
7
8 // Check if the scheme matches your legacy custom scheme
9 if incomingURL.scheme == "myapp" {
10 print("Handling legacy custom URL scheme: \(incomingURL)")
11
12 // Pass the URL to the same unified router
13 handleDeepLink(url: incomingURL)
14 }
15}

Create the unified router

Create the handleDeepLink(url:) function to parse the following URL types:

  • Universal Links: The route is usually defined in the path. For example, https://site.com/product.
  • Custom schemes: The route is often defined in the host. For example, myapp://product.

The following example demonstrates how to normalize these differences and execute the navigation:

1func handleDeepLink(url: URL) {
2 var route: String?
3 var queryItems: [String: String] = [:]
4
5 // 1. Normalize the route based on the scheme
6 if url.scheme == "https" {
7 // Universal Link: Route is in the path (e.g., /products)
8 route = url.path
9 } else if url.scheme == "myapp" {
10 // Custom Scheme: Route is often the host (e.g., myapp://products)
11 route = url.host
12 } else {
13 return // Unknown scheme
14 }
15
16 // 2. Parse query parameters (e.g., ?id=123)
17 if let components = URLComponents(url: url, resolvingAgainstBaseURL: true),
18 let items = components.queryItems {
19 for item in items {
20 queryItems[item.name] = item.value
21 }
22 }
23
24 // 3. Execute Navigation
25 // Check if the route contains the target keyword
26 if route?.contains("products") == true {
27 if let id = queryItems["id"] {
28 print("Unified Router: Navigating to Product ID: \(id)")
29 // Trigger your navigation controller push here...
30 }
31 } else if route?.contains("profile") == true {
32 print("Unified Router: Navigating to Profile View")
33 // Trigger your navigation controller push here...
34 }
35}