ampproject / amphtml

The AMP web component framework.
https://amp.dev
Apache License 2.0
14.88k stars 3.89k forks source link

amp-analytics: Allow for optional variables to support Core Web Vitals #35663

Open nicjansma opened 3 years ago

nicjansma commented 3 years ago

Description

Hi,

In amp-analytics today, any variables that you request on a beacon will "hold" the beacon from being sent until all of the variables are resolved:

https://amp.dev/documentation/components/amp-analytics/#vars

Variables are resolved asynchronously and can delay the request until they are fulfilled. For example, some metrics such as Cumulative Layout Shift and Largest Contentful Paint are calculated after the page is hidden. For First Input Delay, it is resolved after the user interacts with the page. For this reason these metrics might not be suitable for use with all triggers (for example, on timer or visible).

Unfortunately, "resolving" of some of the variables may depend on whether that event happens, or even whether the browser supports that feature.

For example, we (Akamai mPulse) are interested in capturing some of the Core Web Vitals such as LCP, CLS and FID. When we went to add these variables to our "primary" beacon, it was pointed out that these CWV metrics shouldn't be placed along regular page analytics data:

We closed this PR after it was pointed out that:

CLS & LCP is only calculated when you move out of the page or go to another tab. FID is calculated only after the user clicks on the browser.

So our first approach was to simply:

This resulted in two possible beacons:

{
  "requests": {
    "onvisible": "https://${beacon_url}?...&c.cls=${cumulativeLayoutShift}&pt.lcp=${largestContentfulPaint}&pt.fcp=${firstContentfulPaint}",

    "onvisible-fid": "https://${beacon_url}?...&et.fid=${firstInputDelay}"
  },
  "triggers": {
    "onvisible-fid": {
      "on": "visible",
      "request": "onvisible-fid"
    }
  }
}

Unfortunately we've found this doesn't work reliably, because if the browser doesn't support CLS/LCP (e.g. non-Chromium browsers), then the main beacon doesn't get sent either.

So instead, we're having to have the browser send four separate beacons, one for the main page data and one for each CWV:

{
  "requests": {
    "base_api": "https://${beacon_url}?...",
    "fid": "${base_api}&et.fid=${firstInputDelay}",
    "cls": "${base_api}&c.cls=${cumulativeLayoutShift}",
    "lcp": "${base_api}&pt.lcp=${largestContentfulPaint}"
  },
  "triggers": {
    "fid": {
      "on": "visible",
      "request": "fid"
    },
    "cls": {
      "on": "visible",
      "request": "cls"
    },
    "lcp": {
      "on": "visible",
      "request": "lcp"
    }
  }
}

While this works, it's certainly not ideal:

What I'm wondering is if there would be a way to specify "optional" parameters for beacons -- if the parameter doesn't resolve (e.g. FID doesn't happen) or the browser doesn't support it (e.g. CLS or LCP), then that value would resolve and send an empty parameter.

Maybe you'd be able to specify a parameter is optional with double curlys ${{parameterName}} or something.

Then, the above request could be simplified back to a single beacon:

{
  "requests": {
    "onhidden": "https://${beacon_url}?...&c.cls=${{cumulativeLayoutShift}}&pt.lcp=${{largestContentfulPaint}}&pt.fcp=${{firstContentfulPaint}}&et.fid=${{firstInputDelay}}",
  },
  "triggers": {
    "onhidden": {
      "on": "hidden",
      "request": "onhidden"
    }
  }
}

The beacon would be sent at hidden, and would only contain values for FID (if it happened) and CLS/LCP if they were supported by the browser too. The important thing is it would always be sent, even if the browser didn't support them.

Or maybe extraUrlParams gets a value and optional field:

"extraUrlParams": {
  "c.cls": {
      value: "${cumulativeLayoutShift}",
      optional: true
  }
}

Thoughts?

Alternatives Considered

I've seen some other similar requests in the past, e.g.:

Additional Context

No response

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.