9 ways to track and detect CLS for yourselves and real users

9 ways to track and detect CLS for yourselves and real users

  • ± 4 minutes
  • CLS

You think it would be clear to everyone that the Tower of Pisa is shifted. However, it also depends on the point of view and angle. The same applies to CLS as well: different conditions will result in CLS happening at different moments. Let's discuss toolings you can use to track CLS.

To detect CLS, you have the following options:

Track CLS via lab data performance testing

Lab data CLS means tracking the CLS in a synthetic test setup. Due to lack of scrolling and interaction within lab data testing, you might not become aware of all CLS that could happen within a page life cycle. However, lab data testing could still be a good starting point.

Some examples of lab data testing to get CLS:

Real user or field data CLS

Field data CLS is based on real users and retrieved by monitoring pagespeed metrics amongst those real users. Which is known as real user monitoring (RUM).

In other words: you could use RUM to track CLS, to get insights into CLS as experienced by real users. You could use the following to get field data CLS:

Chrome User Experience report

Whenever you're testing a URL in PageSpeed Insights, you might see field data CLS if the tested page or otherwise origin summary has a sufficient amount of visitors. This data is coming from Google's Chrome User Experience report (CrUX).

The same applies to any Google data studio report, or API requests. For example, my ROI calculator is actually doing an API request as well, and then providing you a link to the Google data studio report.

Do note that this data will always have a delay. PageSpeed Insights data will have a delay of 28 days. CrUX's monthly data will only be updated every second Tuesday of the new month.

Send CLS data to your analytics

One could use JS libraries to send data to your analytics environment, for exampel GA of (even better) GA4. This comes with quite a few steps to get this going.

Online monitoring solutions

When you wanted to get started right away, without any hassle, you could use online monitoring solutions. As such solutions will have focus on performance monitoring, they will often provide you with options to deep dive into conditions where issues are happening. This will enable developers or other technical specialist to know what to search and test for.

RUMvision is such solution, where you only have to embed a snippet via GTM (or directly into your source code).

Debug CLS yourselves

Now that RUM told you where CLS issues are happening, you might want to take over from there. You could do this by starting to debug within your own browser.

A caveat is that you won't see CLS of other users out there, while every other user might be running into different CLS issues at different moments during their visit, depending on device conditions as well. But once again, next to specific pages, RUM might be able to tell you which devices caused the biggest CLS issues.

There are different ways to test CLS though:

Performance Insights via DevTools

Quite some other information will be thrown towards you, but you could use the Performance Insights pane within your DevTools.

When in DevTools, you could also activate the Core Web Vitals overlay (see screenshow below, available as of Chrome v90) to see all three Core Web Vitals at once, but only per-renderer basis. So, only as measured during the (full) page life cycle of your own page hit.

Plugins and online tools

You could use browser plugins to get to see the CLS score, such as this one that will even highlight shifted elements.

Log CLS to your console

Another option that I'm often using is logging CLS issues to your JS console. For this, you have to execute a JavaScript snippet in your JS console.

This CLS snippet will log any CLS to the console, but only the CLS that happend 500ms after user interaction (see hadRecentInput flag) will become a warning, or if it exceeded the 0.1 threshold, an error in your console.

The CLS snippet

let cls = 0;
new PerformanceObserver(l => {
l.getEntries().forEach(e => {
if (!e.hadRecentInput) {
cls += e.value;
if ( cls > 0.1 ) {
console.error('Current CLS value:', cls);
else {
console.warn('Current CLS value:', cls);
}).observe({type: 'layout-shift', buffered:true});

If you only want to track unexpected layout shifts, then move the console.log(e) line into the final if/else block.

The CLS debugging output

The result in your console would become something like the following:

Important things to look out for:

  • all the elements that got shifted, to be found within the sources object. Do not confuse this with the elements that caused the shift, as these could be totally different;
  • The amount of layout shift, to be found within value.
  • The moment when the layout shift happened (startTime).

Do note that the way CLS is being tracked within Core Web Vitals, was changed in 2021. In short, it's now collecting the highest CLS within a 5 second window session, while this snippet will track all layout shifts that happened within the current page life cycle.

Happy debugging! And if you actually only got more questions or need help with performance improving and auditing, let me know!