# Deep Linking

{% hint style="info" %}
**Version and platform compatibility**

* Deep linking support was introduced in version **4.89.0** of the JourneyApps Runtime and version [**23.7.**](#user-content-fn-1)[^1]**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`](https://docs.journeyapps.com/reference/build/syntax/typescript-apps/runtime-build-package) version **2.1.9** is required for TypeScript apps.

{% endhint %}

### 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.

{% hint style="warning" %}
**Limitations**

* When generating a deep link, parameters can only be of type `text`, `boolean`, `integer` or `number.`See the [Handling view parameters](#handling-view-parameters) section below for handling more complex types.
* Users need to be enrolled in the target app.
  {% endhint %}

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`

This value corresponds to the URL scheme of the container. This is the standard way of opening containers (see the [Open other Containers](https://docs.journeyapps.com/reference/build/integration/opening-external-links-apps#open-other-containers) section).

* The URL scheme of the JourneyApps container downloaded from OXIDE our through the App Stores is `journeyapps`.&#x20;
* In custom containers, the URL scheme is specified in the [Enrollment](https://docs.journeyapps.com/reference/oxide/create-and-manage-app-containers#enrollment) section when creating the container configuration.

#### `view`

The `viewPath` value corresponds to the view path as defined in OXIDE. Also see [view.path](https://docs.journeyapps.com/reference/get-started/journeyapps-fundamentals/view-navigation/..#view-path).

#### `paramName`

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

{% hint style="danger" %}
The following are reserved terms and should not be used as parameter names:\
`j, k, h, t, u, enroll, user, url, view`
{% endhint %}

### Basic Example

{% code title="job\_details.view\.xml" %}

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

{% endcode %}

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
```

### Basic deep link flow

```
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
```

### Generating a deep link

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.

#### Example: Generate deep link in an app

{% code title="main.ts" %}

```typescript
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
```

{% endcode %}

#### Example: Generate deep link manually

```typescript
// 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`.&#x20;

Developers will need to handle more complex view parameter types, e.g.  where a view parameter is a `DB` object, or a `date`. The [`transform-value`](https://docs.journeyapps.com/reference/get-started/journeyapps-fundamentals/view-navigation/..#transform-value) attribute is available on a view parameter for this purpose. In addition, the [`required`](https://docs.journeyapps.com/reference/get-started/journeyapps-fundamentals/view-navigation/..#required) attribute is available to improve link/deep link management throughout an app in the case where optional parameters are added to a view at a later stage.

### 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:

<pre class="language-typescript"><code class="lang-typescript"><strong>admin_view.ts
</strong>
async function init() {
  if (user.role !== 'admin') {
      notification.error('You do not have access to this view');
      return navigate.replace('main');
  }
}
</code></pre>

And the following is not recommended:

```typescript
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.

#### Encode URL when generating a deep link from an external system

Deep links should be URL encoded. When generating a deep link from an external system (including CloudCode) this can be done using the [URL( )](https://developer.mozilla.org/en-US/docs/Web/API/URL/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:&#x20;

{% code title="index.ts" %}

```typescript
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
}
```

{% endcode %}

[^1]:


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.journeyapps.com/reference/get-started/journeyapps-fundamentals/view-navigation/deep-linking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
