@code-mancers/gatsby-plugin-google-tagmanager
Version:
Gatsby plugin to add google tagmanager onto a site
96 lines (84 loc) • 3.07 kB
JavaScript
const listOfMetricsSend = new Set();
function debounce(fn, timeout) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, timeout, ...args);
};
}
function sendWebVitals(dataLayerName = `dataLayer`) {
const win = window;
function sendData(data) {
if (listOfMetricsSend.has(data.name)) {
return;
}
listOfMetricsSend.add(data.name);
sendToGTM(data, win[dataLayerName]);
}
return import(`web-vitals/base`).then(({ getLCP, getFID, getCLS }) => {
const debouncedCLS = debounce(sendData, 3000);
// we don't need to debounce FID - we send it when it happens
const debouncedFID = sendData;
// LCP can occur multiple times so we debounce it
const debouncedLCP = debounce(sendData, 3000);
// With the true flag, we measure all previous occurences too, in case we start listening to late.
getCLS(debouncedCLS, true);
getFID(debouncedFID, true);
getLCP(debouncedLCP, true);
});
}
function sendToGTM({ name, value, id }, dataLayer) {
dataLayer.push({
event: `core-web-vitals`,
webVitalsMeasurement: {
name: name,
// 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).
id,
// 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).
value: Math.round(name === `CLS` ? value * 1000 : value),
},
});
}
export function onRouteUpdate({ prevLocation }, pluginOptions) {
if (
process.env.NODE_ENV === `production` ||
pluginOptions.includeInDevelopment
) {
// so when gatsby detects that this is the first page load and this option is true
// then do not fire the gtm event.
// but when option is true and page load is not the first page then only fire the gtm event.
const isFirstPage = prevLocation === null;
let fireGtm = true;
if (isFirstPage && !pluginOptions.fireGtmOnFirstPageLoad) {
fireGtm = false;
}
if (fireGtm) {
// wrap inside a timeout to ensure the title has properly been changed
setTimeout(() => {
const data = pluginOptions.dataLayerName
? window[pluginOptions.dataLayerName]
: window.dataLayer;
const eventName = pluginOptions.routeChangeEventName
? pluginOptions.routeChangeEventName
: `gatsby-route-change`;
data.push({ event: eventName });
}, 50);
}
}
}
export function onInitialClientRender(_, pluginOptions) {
// we only load the polyfill in production so we can't enable it in development
if (
process.env.NODE_ENV === `production` &&
pluginOptions.enableWebVitalsTracking
) {
sendWebVitals(pluginOptions.dataLayerName);
}
}