Guida Avanzata

Advanced Guide: how to track Core Web Vitals with Google Tag Manager

[UPDATE 02 March 2021]

In this guide, I’ll explain to you the easiest way to track Core Web Vitals (if you don’t know what Core Web Vitas are, click here to read my italian article) i.e. metrics that are the new ranking factor in SEO for Google.

This post is inspired by:

Actually, I was inspired by several sources, but Philip Walton’s post is the most authoritative source for me.

Metrics to focus on are:

  • Largest Contentful Paint (LCP)
  • First Input Delay (FID)
  • Cumulative Layout Shift (CLS)

Are you ready to take advantage of the three Core Web Vitals metrics and create your own Real User Monitoring?

Let’s go!

Thanks to Simo Ahava

For me is an honor to inspired amazing people like Simo Ahava. Indeed, he has created a Core Web Vitals custom template in GTM. Please read his article also: https://www.simoahava.com/analytics/track-core-web-vitals-in-ga4-with-google-tag-manager/

STEP 1 – Create Custom HTML Tag with Web Vitals APIs

You are able to create the Custom HTML Tag just by copying and pasting the script below (integrated by some small changes with the help of the help of Simen Hansen) in 10 seconds.

  • Tag > New > Tag Configuration > Custom HTML Tag.
  • Copy and paste this script:
<!-- Load 'web-vitals' using a classic script that sets the global 'webVitals' object. -->
<script src="https://unpkg.com/web-vitals@1.1.0/dist/web-vitals.umd.js"></script>
<script>
function sendToGTM(name, delta, id) {
  // Assumes the global `dataLayer` array exists, see:
  // https://developers.google.com/tag-manager/devguide
  dataLayer.push({
    event: 'web-vitals',
    event_category: 'Web Vitals',
    event_action: name.name,
    // Google Analytics metrics must be integers, so the value is rounded.
    // For CLS the value is first multiplied by 1000 for greater precision
    // (note: increase the multiplier for greater precision if needed).
    event_value: Math.round(name.name === 'CLS' ? name.delta * 1000 : name.delta),
    // The 'id' value will be unique to the current page load. When sending
    // multiple values from the same page (e.g. for CLS), Google Analytics can
    // compute a total by grouping on this ID (note: requires `eventLabel` to
    // be a dimension in your report).
    event_label: name.id,
  });
}
webVitals.getCLS(sendToGTM);
webVitals.getFID(sendToGTM);
webVitals.getLCP(sendToGTM);
</script>
  • Triggering > select “All Pages” Trigger.
  • Rename Tag as “Script – Web Vitals”.
  • Save and publish.

Some considerations:

  • The green parts are comments (you can also delete them)
  • The dataLayer object must be initialized. No problem: it’s already like that 🙂
  • Since Google Analytics likes integers there’s rounding in the event_value parameter (Math.round), and in the case of the CLS metric a multiple of 1000 is added.
  • The event_label parameter contains a unique id of the page
  • There are three metrics to add: Largest Contentful Paint (LCP), First Input Delay (FID), Cumulative Layout Shift (CLS)

So this script fires three events called web-vitals in GTM. Let’s intercept metrics.

[WARNING]

The library https://unpkg.com/web-vitals@1.1.0/dist/web-vitals.umd.js the current version (03/02/2021) is 1.1.0 be careful and update it if there will be a new release.

You can find it here: https://unpkg.com/browse/web-vitals/

STEP 2 – Create Trigger for WEB VITALS Custom Event

  • Triggers > New > Trigger Configuration.
  • Trigger Type: Custom Event.
  • Event name: web-vitals.
  • Rename Trigger: “Web Vitals”.
  • Save.

STEP 3 – Create Data Layer Variables

You have to collect values that are inside dataLayer to send them to Google Analytics.

These values are:

  • event_category
  • event_action
  • event_value
  • event_label

You just have to do it for all four values.

Variables > New > Variable Configuration > Data Layer Variable

  • Name: dlv – event_category
  • Data Layer Variable Name: event_category
  • Data Layer Version: Version 2

Do the same for the rest of Variables by changing their name and value:

Variables > New > Variable Configuration > Data Layer Variable

  • Name: dlv – event_action
  • Data Layer Variable Name: event_action
  • Data Layer Version: Version 2

Variables > New > Variable Configuration > Data Layer Variable

  • Name: dlv – event_value
  • Data Layer Variable Name: event_value
  • Data Layer Version: Version 2

Variables > New > Variable Configuration > Data Layer Variable

  • Name: dlv – event_label
  • Data Layer Variable Name: event_label
  • Data Layer Version: Version 2

Great! You just have to send values to Google Analytics (but if you wish, you could send these metrics to any other tool).

STEP 3 – Create and configure Google Analytics Tag for web vitals

  • Tag > New.
  • Tag Type: Universal Analytics.
  • Track Type: Event.
  • Category: {{dlv – event_category}}
  • Action: {{dlv – event_action}}
  • Label: {{dlv – event_label}}
  • Value: {{dlv – event_value}}
  • Non-Interaction Hit: True

Select Google Analytics Variable on Google Analytics Settings Variable and Enable overriding settings. Insert GA Costant or GA tracking code as Tracking ID.

  • Firing Triggers:“Web Vitals”.
  • Rename Tag: “GA – Event – Web Vitals”.
  • Save.

STEP 5 – Check the correct tag functioning

Before publishing any changes, check the correct tag functioning by activating the Preview and Debug Mode.

Go to your site and refresh the page. You should see a box at the bottom of your current page showing “web-vitals” event triggered three times. Click on Tags Fired On This Event, you’ll find newly created Tag.

This Tag will fire three time, one for each metric. Keep in mind that the event corresponding to the CLS metric will take a little longer to appear in the box.

 

Therefore, on each event there will be a dataLayer push which will have the parameters of the three metrics:

  • Largest Contentful Paint (LCP)
  • First Input Delay (FID)
  • Cumulative Layout Shift (CLS)

 

 

And these following Tags in Google Analytics.

 

STEP 6 – Publish changes

If the Tags function correctly, then you can publish the changes.

Next step: create your R.U.M.

Now that data are sent to Google Analytics, you should export them and create reports and your Real User Monitoring.

As explained in web.dev official article

“For each of the above metrics, to ensure you’re hitting the recommended target for most of your users, a good threshold to measure is the 75th percentile of page loads, segmented across mobile and desktop devices.”

You have to wait for data (for a few days) and then you can export them by using tools such as Google Sheet, BigQuery, and Data Studio.

Would you like to read a guide explaining how to do it? Let me know in the comments!

Here is an example:

See you in the next article and… Buon Tag 😉

Links

Matteo Zambon

View Comments

  • Hi Matteo,

    thanks for the great article but there's one question that accurred.

    What units do the CWV have

  • Hi MATTEO,

    I just completed the setup.
    It's working in the GTM preview, but I can't get the CLS LCP FID values in the GA-UA real-time events.

    Does this mean I need to wait a few days?

  • Hello Matteo,
    I installed the script. What I see is that CLS, LCP and CSP are created, but besides that a lot of hits are registered with event_categry Web Vitals, but wit the event_action as "undiefined". Do you know how this is created?
    Kind regards,
    Erik

    • Hi Erik,

      I should check your configuration to answer your question.

      Can you post your problem on our Facebook Group “Fatti di Tag Manager” please?

      Add some screenshots too.

      Thank you :)

  • Hi, Thanks for this article! Could you please show how to shoe the 75th percentile score in Data Studio?

  • Hi Matteo, thanks for this conclusion.

    I've learned: ;-)
    LCP data in GA are seconds
    FID data in GA are milliseconds
    CLS data is a score multiplied by 1000

    My question: The table you've shown in this articel contains a LCP value of 518,384. I have similar values. This score means 518 seconds, which mean nearly 10 minutes, am I right?

    Kind regards,
    Laura

    • Hi Laura,

      Yes, you’re right, remember that the column "Score" column is a sum.

      Best regards ;)

  • Hi together,

    Google recently announced, that they have changed the measurement of the Cumulative Layout Shift. So they are now observing layout shift sessions of 5 Seconds and add all values within this time range.

    Does changes in the Vital Scoring have an impact on the JavaScript? Or does this script just reads the value, which the chrome browser delivers?

    • Hi Sebastian, I think all script or DOM elements can impact the scoring. So I think the answer could be "yes".
      I suggest you ask Philip Walton this question directly.

      Bye :)

  • Greetings Matteo
    I have a couple of questions regarding your reporting:
    1.In the table visualization, what aggregation do you use for the values (Score) ?
    2.In the scorecard visualization, what aggregation do you use for the values (Score) ? .

    • Hide Dave,
      1) the score is 75 Percentile. If you mean the column score on the table is a simple sum
      2) Average of 75 Percentile :D

Recent Posts

Come gestire la Consent Mode v2 con Iubenda e Google Tag Manager

Grazie alle Consent Management Platform puoi gestire in modo semplice ed efficace i consensi al…

2 mesi ago

ANALYTIX TALK: il Podcast di Marketing e Digital Analytics

Hai mai desiderato un luogo dove i commenti sulle ultime novità, i metodi delle migliori…

2 mesi ago

Tutto sulla Consent Mode e come gestire la Consent Mode v2: guida completa

Se la GDPR ti sta a cuore e se ti occupi di advertising, allora questo…

2 mesi ago

Come migrare gli eventi da Google Universal Analytics (GA3) Google Analytics 4 (GA4)

[Aggiornata il 6 Febbraio 2024] Quante volte avrai sentito la classica frase “Siamo a Luglio,…

3 mesi ago

Alternativa Google Optimize: usa Google Tag Manager per A/B Test

Ora che anche il caro Google Optimize ci ha lasciati, quella che troverai in questa…

4 mesi ago