Skip to content

Manifest start_url

In one line: start_url is the URL your PWA opens when a user launches it from the home screen or OS launcher. It must be within your declared scope, and it is the right place to add UTM parameters or other analytics markers so you can distinguish installed-app launches from regular browser visits.

{
"start_url": "/app/?source=pwa",
"scope": "/app/"
}

start_url can be a relative or absolute URL. Relative values are resolved against the manifest URL, not the page URL.

start_url must be within scope. If it is not, the browser falls back to treating the directory containing the manifest as the scope — your explicit scope member is silently ignored. Always verify the constraint:

scope Valid start_url Invalid start_url
/app/ /app/, /app/dashboard /, /blog/
/ /, /app/, /blog/ https://other.example.com/
  • When start_url is absent the browser uses the URL of the page that linked to the manifest.
  • The spec requires that start_url be same-origin as the manifest.
  • The browser normalises start_url before checking it against scope; trailing-slash differences can matter.

Because start_url is the launch entry point, it is the canonical place to add tracking parameters:

{
"start_url": "/app/?utm_source=homescreen&utm_medium=pwa"
}

This lets you segment installed-app sessions from organic browser traffic in analytics dashboards without modifying any JavaScript.

start_url is the default entry point, not the only one. Users can deep-link directly to any in-scope URL (from notifications, share targets, shortcuts). The deep-link URL takes precedence over start_url; your app must handle any in-scope path as a valid entry point, not only the one in start_url.

  • start_url is in the same origin as the manifest.
  • start_url is a subpath of your declared scope.
  • You have tested launching the installed app on Android, iOS, and desktop to confirm the correct page loads.
  • If you use UTM parameters, confirm they appear in your analytics on a fresh install launch.
  • Your app handles every in-scope URL as a valid entry point — not only start_url.