Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add query to determine frequency of the same image being LCP between desktop & mobile #73

Merged
merged 6 commits into from
Nov 2, 2023

Conversation

westonruter
Copy link
Collaborator

@westonruter westonruter commented Oct 4, 2023

The current PHP heuristics adds fetchpriority=high to the same image for both desktop and mobile clients. Nevertheless, some sites serve different assets for desktop and mobile via CSS media queries. In such cases, when the LCP image on desktop is given fetchpriority=high, it can be that for mobile that the LCP image lacks fetchpriority=high and also gets loading=lazy. This PR seeks to determine how common a scenario this is.

At present, it is only considering cases in which fetchpriority=high was added correctly to the LCP image for either the desktop or the mobile. If so, then it counts how often or not both desktop and mobile have fetchpriority=high on the LCP image. It is also only considering mobile and desktop pages which both have an image as the LCP element. Lastly, it only considers WordPress 6.3.x since this is the version in which fetchpriority was introduced.

lcp_images_both_have_fetchpriority count
false 25,860
true 44,601
Total: 70,461

(Query elapsed time: 11 min 38 sec)

Of the matching pages, ~63% (25,860/70,461) have the same image as LCP for desktop and mobile. (Or technically that both of these images have fetchpriority=high, which WordPress only adds to one image.) So there is ~37% headroom here to improve LCP detection.

Note that this does not account for the case when fetchpriority=high is missing on both the LCP image for desktop and mobile. To account for this, we would not be able to rely on lcp_elem_stats or raw_lcp_element since they lack sufficient information:

JSON
{
  "_performance": {
    "lcp_elem_stats": {
      "startTime": 3429.900000002235,
      "nodeName": "IMG",
      "url": "https:\/\/example.com\/foo.jpg",
      "size": 53130,
      "loadTime": 3422.4,
      "renderTime": 3429.9,
      "attributes": [
        {
          "name": "width",
          "value": "768"
        },
        {
          "name": "height",
          "value": "480"
        },
        {
          "name": "src",
          "value": "https:\/\/example.com\/foo.jpg"
        },
        {
          "name": "class",
          "value": "wp-post-image"
        },
        {
          "name": "alt",
          "value": "some alt text"
        },
        {
          "name": "decoding",
          "value": "async"
        },
        {
          "name": "loading",
          "value": "lazy"
        },
        {
          "name": "srcset",
          "value": "https:\/\/example.com\/foo.jpg 768w, https:\/\/example.com\/foo-320x200.jpg 320w"
        },
        {
          "name": "sizes",
          "value": "(max-width: 768px) 100vw, 768px"
        },
        {
          "name": "title",
          "value": "some title"
        }
      ],
      "boundingClientRect": {
        "x": 15,
        "y": 1354.359375,
        "width": 330,
        "height": 206.234375,
        "top": 1354.359375,
        "right": 345,
        "bottom": 1560.59375,
        "left": 15
      },
      "naturalWidth": 359,
      "naturalHeight": 224,
      "styles": {
        "background-image": "",
        "pointer-events": "",
        "position": "",
        "width": "",
        "height": ""
      },
      "cover90viewport": false
    },
    "raw_lcp_element": {
      "nodeName": "IMG",
      "attributes": [
        {
          "name": "width",
          "value": "768"
        },
        {
          "name": "height",
          "value": "480"
        },
        {
          "name": "src",
          "value": "https:\/\/example.com\/foo.jpg"
        },
        {
          "name": "class",
          "value": "wp-post-image"
        },
        {
          "name": "alt",
          "value": "some alt text"
        },
        {
          "name": "decoding",
          "value": "async"
        },
        {
          "name": "loading",
          "value": "lazy"
        },
        {
          "name": "srcset",
          "value": "https:\/\/example.com\/foo.jpg 768w, https:\/\/example.com\/foo-320x200.jpg 320w"
        },
        {
          "name": "sizes",
          "value": "(max-width: 768px) 100vw, 768px"
        },
        {
          "name": "title",
          "value": "some title"
        }
      ]
    }
  }
}

In order to expand the set of URLs beyond ~70K, we would need to query for the LCP element on desktop and mobile, and then compare the image attributes or the CSS selectors as is exposed by the Lighthouse audit. However, this is complicated by the fact that the desktop and mobile crawls by HTTP Archive may reflect different states of the page, such as when a new article is published and appears at the top of the homepage between desktop and mobile crawls. When this happens, the src of the LCP elements will no longer match so they cannot be compared, and the selectors could involve some attachment ID or post ID, so they may not be reliable to compare either.

@westonruter westonruter marked this pull request as ready for review October 4, 2023 22:30
Copy link
Collaborator

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter The query mostly looks good so far, but there is one notable issue with it: As far as I can tell, relying on the fetchpriority attribute here is an unnecessary limitation that drastically reduces the dataset we can work with. I'm not sure why we need to use fetchpriority in this query in the first place.

Rather than using fetchpriority to determine whether a site has an image as the LCP element on both mobile and desktop (which could in principle also have false positives if both images are different but both have the same fetchpriority attribute applied), I would advise that we make this dependent on a more reliable approach - for example by comparing the src (or if we want to be very verbose, the entire tag's attributes). Instead of getAttr(), you could have a function like hasSameAttributes(). This would then cover way more WordPress sites.

I think we should remove the limitation to WordPress 6.3 as well, since this question isn't really specific to whether or not fetchpriority is applied.

@felixarntz
Copy link
Collaborator

@westonruter Other than my query review feedback above, two questions on your summary in the PR description:

Of the matching pages, ~58% have the same image as LCP for desktop and mobile.

Can you clarify where that percentage comes from?

Note that this does not account for the case when fetchpriority=high is missing on both the LCP image for desktop and mobile. To account for this, we would not be able to rely on lcp_elem_stats or raw_lcp_element since they lack sufficient information:

I'm not sure I understand what you mean. Why can't we discover whether a page has the same LCP image on mobile and desktop regardless of fetchpriority?

@westonruter
Copy link
Collaborator Author

westonruter commented Oct 5, 2023

for example by comparing the src (or if we want to be very verbose, the entire tag's attributes). Instead of getAttr(), you could have a function like hasSameAttributes(). This would then cover way more WordPress sites. [...] I'm not sure I understand what you mean. Why can't we discover whether a page has the same LCP image on mobile and desktop regardless of fetchpriority?

Unfortunately, I found that we cannot compare the src or the other attributes because the desktop crawl and the mobile crawl do not happen at the same time. I tried to make this clear in the last paragraph of the PR description. This is why the query is using fetchpriority because it is stable across crawls. The reliance on fetchpriority is also why the WordPress 6.3 constraint is put in place, since that is when core added support for that attribute.

We could potentially see if there is a CSS selector exposed in the Lighthouse LCP audit and compare that, but there could still be some variance based on the time of crawling (e.g. differing class names).

Can you clarify where that percentage comes from?

Yeah, from the results there are 44,601 pages that correctly set fetchpriority on the LCP image, and there are 25,860 which do not. So 25,860/44,601 = ~58% and that is the success rate. Humm, but the total number of pages returned is 70,461, so ~63% of the pages have fetchpriority set properly for both mobile and desktop. Now I'm confusing myself. How would you slice those numbers?

Update: I updated the description to fix my faulty calculation.

Copy link
Collaborator

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @westonruter, LGTM!

sql/2023/10/cross-device-matching-lcp-image.sql Outdated Show resolved Hide resolved
Copy link
Collaborator

@swissspidy swissspidy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the merge conflict now

@felixarntz felixarntz merged commit b25d9d6 into main Nov 2, 2023
3 checks passed
@westonruter westonruter deleted the add/cross-device-matching-lcp-image branch November 2, 2023 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants