Deep Linking

Version and platform compatibility

  • Deep linking support was introduced in version 4.89.0 of the JourneyApps Runtime and version 1 of the JourneyApps Container.

  • Deep links are currently only supported in Android, iOS, Windows, and MacOS containers.

    • Currently, on Web containers, deep links can be generated and called, but the Web container cannot be opened using a deep link.

  • The "Deep linking" feature flag must be enabled.

  • @journeyapps/runtime-build version 2.1.9 is required for TypeScript apps.

Overview

Deep links can be used in emails, external systems, or other apps to open an app on a specific view. This improves the usability of an app by reducing the number of steps to get to the right place in the app.

The structure of a deep link is:

yourcontainerurlscheme:///deeplink?view=viewPath&paramName1=value1&paramName2=value2

Deep links take a view path and, optionally, a number of parameters.

yourcontainerurlscheme

  • The URL scheme of the JourneyApps container downloaded from OXIDE our through the App Stores is journeyapps.

view

paramName

Substitute paramName with the name of a parameter in your view. Additional view parameter-and-value pairs can be added, separated by a &.

Basic Example

job_details.view.xml
<?xml version="1.0" encoding="UTF-8"?>
<view title="Job Details">
    <param name="job" type="job" />
    ...
</view>

For example, a deep link to this job_details view would be structured as

acmecontainer:///deeplink?view=job_details&job=358e03d-a6b9-4b5a-a7c1-024765fb9b23
Start --> User clicks on a deep link
        |--> Browser opens the app based on 'urlScheme'
            |--> If app found, open JourneyApps container
                |--> Container checks if the user is enrolled
                    |--> If user is not enrolled, navigate to the login screen
                    |--> If user is enrolled, loads JourneyApps runtime
                        |--> Runtime checks deep link view and view params
                            |--> If View found, 
                                 |--> processes any view params and calls 'transform-value' if defined
                            |--> If no view found, load the 'main' view
                            |--> If an error occurs while deep linking
                                |--> user is navigated to 'main'
                        |--> End
                    |--> End
            |--> End

Deep links for an app can be generated in an app by calling the navigate.getDeeplink() function from a view's JS/TS or by constructing the URL manually. This latter approach is useful for generating deep links from external systems or from CloudCode tasks.

main.ts
const link = await navigate.getDeepLink({
        path: 'technician/landing',
        urlScheme: 'acmecontainer',
        args: {
            technician: 'technicianId',
            job: 'jobId'
        }
});

// link is a string of the compiled url
console.log(link); // -> acmecontainer:///deeplink?view=technician%2Flanding&technician=technicianId&job=jobId
// Create the initial url with the container urlscheme and the "deeplink" url pathname
const link = new URL('acmecontainer:///deeplink'); 
// Append a "view" parameter
link.searchParams.append('view', 'technician/landing');
// Append any required view parameters 
link.searchParams.append('technician', 'ABCD 123! 567? 89/|\\');

// link.href is a string of the compiled url
console.log(link.href); 
// -> acmecontainer:///deeplink?view=technician%2Flanding&technician=ABCD+123%21+567%3F+89%2F%7C%5C

Handling view parameters

When generating a deep link all parameters become strings. When opening the deep link, certain parameters are automatically cast to JourneyApps types - e.g. "true"/"false" strings are turned into booleans. This happens for the following types: text, boolean, number, integer.

Developer Recommendations

View-level access control

Access control, such as limiting access to a view to certain user roles only, should happen in the init() function of a view, not in the navigation function that navigates to the view. This ensures that access control is being applied whether users navigate using in-app navigation or using deep links.

For example, the following is recommended:

admin_view.ts

async function init() {
  if (user.role !== 'admin') {
      notification.error('You do not have access to this view');
      return navigate.replace('main');
  }
}

And the following is not recommended:

main.ts

async function adminNav() {
  if (user.role === 'admin') {
    return navigate.link('admin_view');
  }
  else {
    return notification.error('You do not have access to this view');
  }
}

Validation and error handling of view parameters

This should happen in the init() function of a view i.e. after parameters have received their values. This should not happen in the transform-value function.

Deep links should be URL encoded. When generating a deep link from an external system (including CloudCode) this can be done using the URL( ) class since it handles encoding of slashes, spaces and other non browser-safe characters into a valid url.

  • navigate.getDeeplink() has this built-in

  • Example in CloudCode:

index.ts
import { TaskContext } from '@journeyapps/cloudcode';
import { URL } from 'url';

export async function run(this: TaskContext) {
    const link = new URL('acmecontainer:///deeplink');
    link.searchParams.append('view', 'technician/landing');
    link.searchParams.append('technician', 'ABCD 123! 567? 89/|\\');
    console.log(link.href); // -> acmecontainer:///deeplink?view=technician%2Flanding&technician=ABCD+123%21+567%3F+89%2F%7C%5C
}

Last updated