A hand and several hanging chains, symbolizing links.

Choose how in-scope links open your PWA with Declarative Link Capturing

Choose how in-scope links open your PWA with Declarative Link Capturing

Declarative Link Capturing is a proposal for a web app manifest property called
"capture_links" that lets developers determine declaratively what should happen when the browser
navigates to a URL that is within the application's navigation scope, from a context
outside of the navigation scope.


Declarative Link Capturing is part of the capabilities project and is currently in development. This post will be updated as the implementation progresses.

What is Declarative Link Capturing? #

Clicking links on the web can sometimes be a pleasant surprise. For example, clicking a web page link to YouTube on a mobile device opens the YouTube iOS or Android app, if it is installed. But when you install the YouTube PWA on a desktop computer and click a link, it opens in… 🥁 a browser tab.

But it gets more complex. What if the link appears not in a website, but in a chat message that you receive in one of Google's chat apps? On desktop operating systems that have the notion of separate app windows, if the app is open already, should a new window or tab be created for each link click that is captured? When you think about it, there are many ways links and navigations can be captured, including, but not limited to, the following:

Declarative Link Capturing is a proposal for a web app manifest property called "capture_links" that lets developers determine declaratively what should happen when the browser is asked to navigate to a URL that is within the application's navigation scope, from a context outside of the navigation scope. This proposal does not apply if the user is already within the navigation scope (for instance, if the user has a browser tab open that is within scope, and clicks an internal link).

Key Term: The navigation scope of a web app manifest is the "scope" item of a processed manifest. The navigation scope restricts the set of URLs to which an application context can be navigated while the manifest is applied. If the "scope" member is not present in the manifest, it defaults to the parent path of the "start_url" member.

Some special conditions like middle-clicking a link (or right-clicking and then "open in new tab") would typically not trigger the link capturing behavior. Whether a link is target=_self or target=_blank does not matter, so that links clicked in a browser window (or window of a different PWA) would be opened in the PWA even if they would normally cause a navigation within the same tab.

Suggested use cases #

Examples of sites that may use this API include:

  • PWAs that want to open a window, rather than a browser tab, when the user clicks on a link to them. In a desktop environment, it often makes sense to have multiple application windows open at a time.
  • Single-window PWAs where the developer prefers to only have a single instance of the app open at any time, with new navigations focusing the existing instance. Sub-use cases include:
    • Apps for which it make sense to have only one instance running (e.g., a music player, a game).
    • Apps that include multi-document management within a single instance (e.g., an HTML-implemented tab strip).

Current status #

1. Create explainerComplete
2. Create initial draft of specificationIn Progress
3. Gather feedback & iterate on designIn progress
4. Origin trialIn progress (on Chrome OS)
5. LaunchNot started

Enabling via about://flags #

To experiment with Declarative Link Capturing locally, without an origin trial token, enable the #enable-desktop-pwas-link-capturing flag in about://flags.

Enabling support during the origin trial phase #

Starting in Chromium 91, Declarative Link Capturing will be available as an origin trial in Chromium. The origin trial is expected to end in Chromium 94 (October 13, 2021).

Caution: The origin trial is initially limited to Chrome OS.

Origin trials allow you to try new features and give feedback on their usability, practicality, and effectiveness to the web standards community. For more information, see the Origin Trials Guide for Web Developers. To sign up for this or another origin trial, visit the registration page.

Register for the origin trial #

  1. Request a token for your origin.
  2. Add the token to your pages. There are two ways to do that:
    • Add an origin-trial <meta> tag to the head of each page. For example, this may look something like:
      <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
    • If you can configure your server, you can also add the token using an Origin-Trial HTTP header. The resulting response header should look something like:
      Origin-Trial: TOKEN_GOES_HERE

How to use Declarative Link Capturing? #

Developers can declaratively determine how links should be captured by leveraging the additional web app manifest field "capture_links". It takes a string or a an array of strings as its value. If an array of strings is given, the user agent chooses the first supported item in the list, defaulting to "none". The following values are supported:

  • "none" (the default): No link capturing; links clicked leading to this PWA scope navigate as normal without opening a PWA window.
  • "new-client": Each clicked link opens a new PWA window at that URL.
  • "existing-client-navigate": The clicked link opens in an existing PWA window, if one is available, or in a new window if it is not. If more than one PWA window exists, the browser may choose one arbitrarily. This behaves like "new-client" if no window is currently open. 🚨 Careful! This option potentially leads to data loss, as pages can be arbitrarily navigated away from. Sites should be aware that they are opting into such behavior by choosing this option. This option works best for "read-only" sites that do not hold user data in memory, such as music players. If the page being navigated away from has a beforeunload event, the user would see the prompt before the navigation completes.

There is discussion about adding options that do not open a window at all, but instead fire a launch event in a chosen foreground window or the service worker. See the launch event explainer for details, and, more specifically, the sections on existing-client-event and service-worker.

Demo #

The demo for Declarative Link Capturing actually consists of two demos that interact together:

  1. https://continuous-harvest-tomato.glitch.me/
  2. https://hill-glitter-tree.glitch.me/

The screencast below shows how the two interact. They show two different behaviors, "new-client" and "existing-client-navigate". Be sure to test the apps in different states, running in a tab or as an installed PWA, to see the difference in behavior.

Security and permissions #

The Chromium team has designed and implemented Declarative Link Capturing using the core principles defined in Controlling Access to Powerful Web Platform Features, including user control, transparency, and ergonomics. This API allows sites new additional control options. First, being able to automatically open installed apps in a window. This uses existing UI but makes it possible for the site to automatically trigger it. Second, the capability to focus an existing window on its own domain and fire an event containing the clicked URL. This is intended to allow the site to navigate an existing window to a new page, overriding the default HTML navigation flow.

Feedback #

The Chromium team wants to hear about your experiences with Declarative Link Capturing.

Tell us about the API design #

Is there something about the API that does not work like you expected? Or are there missing methods or properties that you need to implement your idea? Have a question or comment on the security model? File a spec issue on the corresponding GitHub repo, or add your thoughts to an existing issue.

Report a problem with the implementation #

Did you find a bug with Chromium's implementation? Or is the implementation different from the spec? File a bug at new.crbug.com. Be sure to include as much detail as you can, simple instructions for reproducing, and enter UI>Browser>WebAppInstalls in the Components box. Glitch works great for sharing quick and easy repros.

Show support for the API #

Are you planning to use Declarative Link Capturing? Your public support helps the Chromium team prioritize features and shows other browser vendors how critical it is to support them.

Send a tweet to @ChromiumDev using the hashtag #DeclarativeLinkCapturing and let us know where and how you are using it.

Helpful links #

Acknowledgements #

Declarative Link Capturing was specified by Matt Giuca with input from Alan Cutter and Dominick Ng. The API was implemented by Alan Cutter. This article was reviewed by Joe Medley, Matt Giuca, Alan Cutter, and Shunya Shishido. Hero image by Zulmaury Saavedra on Unsplash.

Last updated: Improve article