Jason Galuten
Jason Galuten

Reputation: 1072

User clicks url in email on iOS and is taken to the app instead of web. How to know url?

It seems that since iOS 9 if a user has already been redirected to an app from a website, then future links to that website automatically open the app.

How can I detect inside the iOS app what the link was that the user clicked so that I can serve the correct content?

In my case, a user has already installed the app, does a forgot password, and clicks the link in the email. On a desktop it works fine, but on iOS it just takes them to the app and my app does not know the context.

It is a Swift app that is mostly a webview serving the mobile version of our web app.

UPDATE:

Here are some details about the situation:

Not sure if this is relevant, but I actually have a second URL scheme defined, app, which is used to by the js of the website (when the site is loaded in a webview) to send data to the app like:

window.location = "app://do/some/thing"

which the app can catch via func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {}

To be clear, inside that shouldStartLoadWith I am only testing that request.url?.scheme equals "app". This function does not get involved with the other URL scheme, ourUniqueOrganizationName, as I understand that just having that defined in the info.plist is enough for websites to open the app using that as the scheme.

UPDATE # 2:

I finally realized that I did, in fact, have Universal Links on so the behavior I was seeing should have been expected!

Upvotes: 1

Views: 1393

Answers (2)

staticVoidMan
staticVoidMan

Reputation: 20234

If the link is something like:

myAppURLScheme://loremIpsumDolor

Then your app has defined a URL Scheme because of which iOS is able to open your app when the user taps on such a link.

To handle the url, you need to do 2 things in AppDelegate:

  1. Implement the application(_:open:options:) delegate
    • If your app is already running, whether in background or foreground, you will get the URL as a parameter here
  2. Also handle the case in application(_:didFinishLaunchingWithOptions:)
    • This is incase you app is not running i.e not opened or was terminated then you will get the url string in launchOptions parameter here

Solution (Swift 4):

//Extra work to handle url when app was not already running and was launched due to the user tapping on the link
func application(_ application: UIApplication, 
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    //...        
    let strURL = launchOptions?[UIApplicationLaunchOptionsKey.url] as? String
    handleURL(strURL)
    //...
}

//Delegate to handle url when app is already running (background/foregroung)
func application(_ app: UIApplication, 
                 open url: URL,
                 options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    handleURL(url.absoluteString)
    return true
}

//Our common helper function
func handleURL(_ string: String?) {
    guard let string = string else { return }

    print(string)
    //do your case handling now
}

EDIT:

If you have Universal Links enabled for your app then you only need the application(_:continue:restorationHandler:) delegate method in your AppDelegate.
You get an NSUserActivity object here that will have all sorts of information including a webpageURL which will be the url that caused your app to open.

Example:

func application(_ application: UIApplication,
                 continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
    print(userActivity.webpageURL?.absoluteString)
    return true
}

Upvotes: 1

Evghenii Nicolaev
Evghenii Nicolaev

Reputation: 584

It looks like you your site is supporting Universal Links, in this case your AppDelegate should implement a method:

func application(_ application: UIApplication, 
             continue userActivity: NSUserActivity, 
   restorationHandler: @escaping ([Any]?) -> Void) -> Bool

When iOS launches your app after a user taps a universal link, you receive an NSUserActivity object with an activityType value of NSUserActivityTypeBrowsingWeb. The activity object’s webpageURL property contains the URL that the user is accessing. The webpage URL property always contains an HTTP or HTTPS URL. Source: https://medium.com/@abhimuralidharan/universal-links-in-ios-79c4ee038272

In case of URLScheme, which is less probable, you should implement in AppDelegate method:

iOS < 9

func application(_ application: UIApplication, handleOpen url: URL) -> Bool

iOS >= 9

func application(_ app: UIApplication, 
                     open url: URL, 
                  options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool

For more details check Documentation

Upvotes: 1

Related Questions