App Bridge Web Vitals: LCP keeps running across app-nav navigations, so later pages' paints count against the first load

Hi Shopifolks,

We’re seeing the App Bridge LCP (the one graded in the Partner Dashboard) include paints from pages the merchant opened after the first load, through the app’s sidebar nav (s-app-nav). We’d like to confirm this and, ideally, get it fixed in App Bridge.

What we see

We forward every shopify.webVitals.onReport metric to our own analytics. With each LCP we also record which route was on screen when the LCP paint happened.

  • About 5% of loads get their LCP from a later route, after one or more sidebar navigations. Their p75 is around 18 s. That number measures how long the merchant stayed on the first page, not how long anything took to render.
  • Our daily p75 closely matches the Partner Dashboard Web Vitals chart. On the days with the most of these loads, the dashboard follows the figure that includes them, about 350 ms above the figure without them. Over the last week they move our p75 from ~2275 ms to ~2475 ms.

Why it happens (from reading app-bridge.js)

  • The bundled web-vitals onLCP stops observing on a trusted keydown, click or visibilitychange (it checks isTrusted), just like upstream web-vitals.
  • When the merchant clicks an app nav item in the admin sidebar, App Bridge receives Navigation.redirect.app. The s-app-nav handler then navigates by calling .click() on the matching <s-link>, which dispatches new MouseEvent("click", { bubbles: true, cancelable: true }). A script-dispatched event has isTrusted === false, so the LCP observer never stops.
  • The app iframe stays visible the whole time, so visibilitychange doesn’t end it either.
  • So any element on the next page that is larger than the first page’s LCP element becomes the load’s LCP. It is timed from the original document’s start.

Steps to reproduce

  1. An embedded app with s-app-nav, whose home page has a small largest element (for example, a block of text).

  2. Open the app and wait about 10 s without clicking or typing inside the app.

  3. In the admin sidebar, click another app nav item whose page shows a larger image.

  4. Close the tab or switch away. The reported LCP is about 10s plus that image’s paint time.

Seen with App Bridge’s web-vitals reporting version 0.41.1+81ea1f46, in Chrome.

Questions

  1. Can you confirm the Partner Dashboard / Built for Shopify LCP includes these loads?
  2. Could App Bridge end the LCP observation when it handles Navigation.redirect.app? It already has the stop function the input listeners call, and apps have no legitimate way to end the observation themselves.
  3. If this is intended, how should apps handle it?

Thanks!

LCP is an useless metric and not required for BFS badge, if you want to lower it, just put a big img or div on tip of your app while it loads