Last active
March 14, 2021 05:03
-
-
Save sgelob/110581ed66cf49a6d6c3b7ac33cdc17c to your computer and use it in GitHub Desktop.
Real User Monitoring of Web Performance with Navigation Timing API, Google Tag Manager and Google Analytics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* user-timing-api-RUM-gtm.js 1.0.1 | |
* Olegs Belousovs @sgelob | |
*/ | |
(function() { | |
"use strict"; | |
// From https://github.com/addyosmani/timing.js/ –––> | |
var performance = window.performance || window.webkitPerformance || window.msPerformance || window.mozPerformance; | |
if (performance === undefined) { | |
return false; | |
} | |
// From https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp –––> | |
var t = performance.timing, | |
// When DOM is ready | |
domInteractiveTime = t.domInteractive - t.domLoading, | |
// When both the DOM and CSSOM are ready | |
dcl = t.domContentLoadedEventStart - t.domLoading, | |
// When the page and all of its subresources are ready | |
domCompleteTime = t.domComplete - t.domLoading, | |
// From https://github.com/addyosmani/timing.js/ –––> | |
// Total time from start to load | |
loadTime = t.loadEventEnd - t.fetchStart, | |
// Time spent constructing the DOM tree | |
domReadyTime = t.domComplete - t.domInteractive, | |
// Time spent during redirection | |
redirectTime = t.redirectEnd - t.redirectStart, | |
// AppCache | |
appcacheTime = t.domainLookupStart - t.fetchStart, | |
// Time spent unloading documents | |
unloadEventTime = t.unloadEventEnd - t.unloadEventStart, | |
// Time spent during the request | |
requestTime = t.responseEnd - t.requestStart, | |
// Request to completion of the DOM loading | |
initDomTreeTime = t.domInteractive - t.responseEnd, | |
// Load event time | |
loadEventTime = t.loadEventEnd - t.loadEventStart; | |
// Time to First Paint | |
if (firstPaint === undefined) { | |
// All times are relative times to the start time within the | |
// same objects | |
var firstPaint = 0; | |
var firstPaintTime = 0; | |
// By bmdevel https://github.com/bmdevel/timing.js/blob/d5531b3b023367d467d3558061de8d8cf5b5ea79/timing.js –––> | |
if (typeof t.msFirstPaint === 'number') { | |
firstPaint = t.msFirstPaint; | |
firstPaintTime = firstPaint - t.navigationStart; | |
// All the rest | |
} else if (performance.getEntriesByName !== undefined) { | |
var firstPaintPerformanceEntry = performance.getEntriesByName('first-paint'); | |
if (firstPaintPerformanceEntry.length === 1) { | |
firstPaintTime = firstPaintPerformanceEntry[0].startTime; | |
firstPaint = performance.timeOrigin + firstPaintTime; | |
firstPaintTime = firstPaintTime; | |
} | |
} | |
// By Olegs Belousovs @sgelob | |
// Push multiple variables and events to the data layer at once | |
dataLayer.push({ | |
// Custom Event | |
"event": "WebPerfRUM", | |
// Critical Rendering Path | |
"DOMInteractive": domInteractiveTime, | |
"DOMContentLoaded": dcl, | |
"DOMComplete": domCompleteTime, | |
// Navigation Timing API metrics | |
"TotalTimeFromStartToLoad": loadTime, | |
"TimeSpentConstructingDOMTree": domReadyTime, | |
"TimeSpentDuringRedirection": redirectTime, | |
"AppCache": appcacheTime, | |
"TimeSpentUnloadingDocuments": unloadEventTime, | |
"TimeSpentDuringRequest": requestTime, | |
"RequestToCompletionOfDOMLoading": initDomTreeTime, | |
"LoadEventTime": loadEventTime, | |
// Time to first paint | |
"TimeToFirstPaint": firstPaintTime | |
}); | |
} | |
})(); |
Hello, i was looking for a way to follow thes metrics with gtm and i've seen your code, which is really good.
I've a little question, how do you implement this snippet? You just use a javascript variable on gtm?
Good job!
Hey Bryan, thank you!
You need to implement a series of variables in GTM and also Track Type – Timing… This code runs on all pages after Window Loaded. I made a talk on this argument, unfortunately only in Italian: https://www.youtube.com/watch?v=nyD54NEn0ac
Here you can find a JSON container, exported from my GTM https://gist.github.com/sgelob/0842d451186c332a45bcfee58224b0f3
Let me know if it helps you to move forward 😊
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Implementation example in production https://www.bakeca.it/