-
Notifications
You must be signed in to change notification settings - Fork 140
Description
Optimization Detective is currently being used to optimize LCP via Image Prioritizer and CLS via Embed Optimizer. However, for the other Core Web Vital, INP, it is not currently doing anything. This is somewhat expected given that there isn't really an element which can be optimized for INP issues like there can be for LCP and CLS. Nevertheless, Optimization Detective does provide a foundation for at least tracking INP issues:
- Initially, Optimization Detective would send the URL Metric as soon as the page has fully loaded and gone idle, but now it sends the URL Metric when the page is being closed. This means that all of the INP/LoAF data collected during the life of the page will be available for adding to a URL Metric for storage.
- As of Preload image URLs for LCP elements with external background images #1697 any Optimization Detective extension modules now have direct access to the
onINPfunction as provided by Web Vitals. - Optimization Detective extensions are able to extend the URL Metric schema via the
od_url_metric_schema_root_additional_propertiesfilter to add a new root property for something likeinpData. - Optimization Detective by default only stores a maximum of 12 URL Metrics per page (3 for each of the 4 viewport groups). This may not be a large enough sample size for collecting enough INP/LoAF data. To this end, there is a
od_url_metric_storedaction which is fired whenever a new URL Metric is stored. An extension could use this to grab the INP data out of the URL Metric and store it persistently in another location so it is not garbage-collected when a new URL Metric is collected. For example, theOD_URL_Metric_Store_Request_Contextobject passed to theod_url_metric_storedaction includes not only theOD_URL_Metricinstance but also the post ID for theod_url_metricspost type that the URL Metric is being stored in. An INP-focused extension could use this to persist the INP data in postmeta for that post, likeod_inp_data:
add_action(
'od_url_metric_stored',
static function ( OD_URL_Metric_Store_Request_Context $context ) {
$inp_data = $context->url_metric->get( 'inpData' );
if ( null === $inp_data ) {
return;
}
// Note: $unique is false to allow for multiple postmeta to be stored with the same key.
add_post_meta( $context->post_id, 'od_inp_data', $inp_data, false );
}
);We can then get all of the INP data with:
$all_data = get_post_meta( $post_id, 'od_inp_data', false );The question then remains: with this data in hand, what do we do with it?
Assuming we have something on the page that causes a long task:
add_action( 'wp_footer', static function () {
?>
<script>
function slowThing(event) {
const now = performance.now();
while ( performance.now() - now < 300 ) {
continue;
}
event.target.textContent = 'Clicked!';
}
</script>
<button type="button" onclick="slowThing(event);">Click Me</button>
<?php
} );The INP data provided by Web Vitals includes:
{
"name": "INP",
"value": 312,
"rating": "needs-improvement",
"delta": 296,
"entries": [
{
"name": "pointerup",
"entryType": "event",
"startTime": 2794.7000000029802,
"duration": 312,
"interactionId": 5364,
"processingStart": 2796.900000002235,
"processingEnd": 2797,
"cancelable": true
},
{
"name": "click",
"entryType": "event",
"startTime": 2794.7000000029802,
"duration": 312,
"interactionId": 5364,
"processingStart": 2797.10000000149,
"processingEnd": 3098.300000000745,
"cancelable": true
}
],
"id": "v4-1734029682811-7860789630775",
"navigationType": "reload",
"attribution": {
"interactionTarget": "html>body.home.blog.logged-in.admin-bar.no-customize-support.wp-embed-responsive>button",
"interactionTargetElement": {},
"interactionType": "pointer",
"interactionTime": 2794.7000000029802,
"nextPaintTime": 3106.7000000029802,
"processedEventEntries": [
{
"name": "pointerup",
"entryType": "event",
"startTime": 2794.7000000029802,
"duration": 312,
"interactionId": 5364,
"processingStart": 2796.900000002235,
"processingEnd": 2797,
"cancelable": true
},
{
"name": "mouseup",
"entryType": "event",
"startTime": 2794.7000000029802,
"duration": 312,
"interactionId": 0,
"processingStart": 2797.10000000149,
"processingEnd": 2797.10000000149,
"cancelable": true
},
{
"name": "click",
"entryType": "event",
"startTime": 2794.7000000029802,
"duration": 312,
"interactionId": 5364,
"processingStart": 2797.10000000149,
"processingEnd": 3098.300000000745,
"cancelable": true
}
],
"longAnimationFrameEntries": [
{
"name": "long-animation-frame",
"entryType": "long-animation-frame",
"startTime": 2796.5,
"duration": 302,
"renderStart": 3098.800000000745,
"styleAndLayoutStart": 3098.900000002235,
"firstUIEventTimestamp": 2794.7000000029802,
"blockingDuration": 252,
"scripts": [
{
"name": "script",
"entryType": "script",
"startTime": 2797.900000002235,
"duration": 300,
"invoker": "BUTTON.onclick",
"invokerType": "event-listener",
"windowAttribution": "self",
"executionStart": 2797.900000002235,
"forcedStyleAndLayoutDuration": 0,
"pauseDuration": 0,
"sourceURL": "http://localhost:8888/",
"sourceFunctionName": "onclick",
"sourceCharPosition": 0
}
]
}
],
"inputDelay": 2.199999999254942,
"processingDuration": 301.3999999985099,
"presentationDelay": 8.400000002235174,
"loadState": "complete"
}
}Do we capture these and just provide a UI to view them? Do we list the counts in the admin bar and show them when clicked? Do we highlight the elements on the page which are involved in slow interactions (if they are even present)? Or do we expose a dashboard for this information as explored in #1324?
Related: #1730
Metadata
Metadata
Assignees
Labels
Type
Projects
Status