Navigation Management into Installed PWAs
Techniques and Best Practices
Self-link: bit.ly/navigation-management-into-installed-pwas
Authors: dmurph@chromium.org, drenzulli@google.com, finnur@chromium.org
This is a developer-focused document, intended to document the basics of the deep linking algorithms which are required to understand the user navigation capturing feature launching in Chrome in m133/134.
When a more well-written article is created, this document will simply link to that.
Developers want their installed PWA to launch when the user clicks on entry points like:
The way these 'launch' into the PWA are non-trivial, and this document shows how these all work, and the tools the developer has to control exactly how their PWA will behave.
Current Ship Status:
There are many ways to deep-link to an installed PWA. Experiment with this example website (source code) and short animation of what is possible using the knowledge you learn in this article!
<webm version 2mb> <webp version 18mb>
Clicking on links and launching files in the browser are going straight into the installed PWA. Interested in what's going on here? Read below!
Note: This behavior also works if the installed PWA is set to open in a browser tab! What does that mean? Install it above, change its settings to not 'open in a window', and try it out!
On desktop, when certain criteria or heuristics are passed, an installation icon is shown in the omnibox and a beforeinstallprompt event is dispatched on the document.
Browser install promotion (desktop)
A developer can listen to the beforeinstallprompt to implement their own install experience.
On Android, installation promotion occurs via an ML model to prevent bothering the user unnecessarily.
A user on any platform can install any website as a PWA. On desktop platforms, this is under the 3-dot menu, "Cast, Save, and Share", "Install". On Android, this is under "Add to Home screen".
All types of PWA deep linking (links, protocol handling, files, etc.) go through the PWA Deep Linking Flowchart.
PWA Deep Linking Flowchart: From User Action to Browser Processing to Task Outcome
* Desktop will consider URL launches from the OS when https://crbug.com/330282442 is fixed, targeting 2025.
Legend:
The "Navigation Capturing" and "Launch Handler Algorithm" steps are expanded into flowcharts below.
Other than the launch handler algorithm, the developer also controls which urls/files/protocols apply to their PWA via the manifest they provide. e.g., if the developer doesn't specify it handles a type of file, or if the URL isn't in the app's scope, then it will never reach the 'launch handler' algorithm.
Clicking a URL in a browser, such as from another web page.
An arrow pointing at click-able https anchor link HTML element.
Shown as the orange rectangle on the top-left side of the PWA Deep Linking Flowchart. Occurs when a user clicks a URL from any surface within the operating system, for example, a link in a message in another native app, such as the operating system's native notes application or chat app.
The Mac "Notes" native application displaying an example note. The cursor is hovering over a click-able https link.
Represented by the orange rectangle on the top-left side of the PWA Deep Linking Flowchart, next to OS, URL. Involves a user interacting with a protocol (e.g., tel:) that is registered via the navigator.registerProtocolHandler() method by a browser tab.
Shown as the orange rectangle second from the top on the left side. The user interacts with a protocol that was registered by an installed PWA via the protocol_handlers manifest field.
Shown as the penultimate orange rectangle on the left hand side. Refers to a user that clicks on the desktop shortcut icon of an installed PWA.
PWA shortcut icons as displayed by different operating systems.
Shown as the orange rectangle on the bottom left hand side. Involves a user that opens a file that an installed PWA is registered to handle via the file_handler manifest field and algorithm.
The 'open with' menu is open in the Mac "Finder" application on an SVG file, displaying that the Boxy SVG installed PWA can open this image. In the background, the Boxy SVG installed PWA is displayed, with that file open.
The user right-clicks on a link and picks the PWA option in the browser menu (these options show up for urls that are in-scope of the installed PWA).
Note that for PWAs configured to not 'Open in a window', this right-click menu doesn't exist and thus the user cannot 'enter' the flowchart at this location directly.
The right-click menu is open in the browser for a URL that is in-scope of the Google Meet installed PWA, and the "Open Link in Google Meet" option is highlighted.
Navigation capturing is used to turn a user action, that results in only a URL (link click, click that calls window.open from javascript, etc), into a PWA launch at a URL. The flowchart below shows how this works:
Navigation Capturing: Determine if a URL navigation should be turned into a PWA launch.
What is 'capturable'? See Appendix - What is “capturable”? below, but essentially user clicks that would have created a new browser tab are considered capturable.
If a capturable URL falls within the scope of an installed PWA, the browser will launch the PWA using the "launch handling algorithm" instead of opening a browser tab. Users can enable or disable this functionality through the settings page of the installed PWA.
The settings page for the installed PWA Boxy SVG, showing the user settings to change how supported links are opened.
Once the app is invoked, the Launch Handler API allows you to control how it launches—for example, whether it opens in an existing window, a new window, or if the selected window navigates to the launch URL. See this guide for in-depth information about using Launch Handlers effectively.
Overview of launch handling and developer controls through the client_mode web manifest member.
For example, the following code checks whether the app should focus on an existing window or open a new URL, handling special cases like opening a chat in the app without making a network request.
if ('launchQueue' in window) {
launchQueue.setConsumer((launchParams) => {
if (launchParams.files && launchParams.files.length != 0) {
// The user launched files from their operating system!
// ...
return;
}
if (!launchParams.targetUrl) {
return;
}
// If the client_mode in the manifest is focus_existing, that
// means this function is supposed to handle what is supposed to
// happen with navigation, and we skip the network!
if (isChatUrlForThisUser(launchParams.targetUrl) {
openChatInPageViaUrl(launchParams.targetUrl);
return;
}
window.location = launchParams.targetUrl;
});
}
See https://chat-app-deep-linking.glitch.me/ and its source code at https://glitch.com/edit/#!/chat-app-deep-linking for a demo.
For a navigation to be capturable for normal non-modified clicks, it must:
The client_mode is overridden if the navigation is coming from the same app it might be captured into.
*Note: Auxiliary contexts created from app windows will turn into popups soon, (crbug.com/392106502)
Clicks can be modified by the user via controls like the shift-key, ctrl-key, meta-key, etc. These have established meanings for browsers, and those need to be respected (e.g. create in a new window, new tab, etc).
For a navigation to be capturable for modified clicks, it must:
Client mode is always overridden to create a new window.