Last active
April 22, 2022 17:00
-
-
Save nicjansma/3940d4b8cbf5cae4caff43460cb2bd71 to your computer and use it in GitHub Desktop.
Boomerang CWV plugin that sends an additional Exit beacon before unload with FID (if it didn't happen by page load) and the SUM of CLS
This file contains hidden or 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
/** | |
* The Boomerang CWV plugin assists in sending Core Web Vitals metrics First Input Delay (FID) and | |
* Cumulative Layout Shift (CLS) at the end of the page session. It does this by sending | |
* an additional "Page Exit" beacon prior to unload. | |
* | |
* The main changes in behavior over the EventTiming plugin (which sends FID) and Continuity | |
* plugin (which sends CLS) are: | |
* | |
* * If FID was _not_ on the Page Load beacon, this plugin sends FID on the Page Exit beacon. | |
* If FID was on the Page Load beacon, it is _not_ repeated on the Page Exit beacon. | |
* * Any time CLS is added to a beacon (`c.cls`) by the Continuity plugin, this plugin | |
* accumulates it locally and removes it from the outgoing beacon. At the end of the page, | |
* it sends `c.cls` a single time with the SUM of CLS values for that page. | |
* | |
* This plugin does not work well in Single Page Applications (SPAs). | |
* | |
* To ensure this plugin works, the following configuration must be set: | |
* ``` | |
* Continuity: { | |
* enabled: true, | |
* afterOnload: true, | |
* afterOnloadMaxLength: false | |
* }, | |
* EventTiming: { | |
* enabled: true | |
* } | |
* ``` | |
* | |
* This plugin depends on the Continuity and EventTiming plugins being enabled. | |
* | |
* ## Beacon Parameters | |
* | |
* This plugin adds the following parameters to the beacon: | |
* | |
* * `c.cls`: Accumulated CLS data | |
* * `et.fid`: First Input Delay | |
*/ | |
window.BOOMR = window.BOOMR || {}; | |
window.BOOMR.plugins = window.BOOMR.plugins || {}; | |
window.BOOMR.plugins.CWV = { | |
// local variables | |
cls: 0.0, | |
initialized: false, | |
unloadSent: false, | |
extraVars: {}, | |
extractedDimensions: false, | |
// functions | |
init: function(config) { | |
if (this.initialized) { | |
return; | |
} | |
this.initialized = true; | |
// extracts CLS values from all outgoing beacons, keeps the SUM locally | |
function extractCls(data) { | |
if (this.unloadSent) { | |
return; | |
} | |
// extract CLS from any previous beacons | |
if (data["c.cls"]) { | |
this.cls += parseFloat(data["c.cls"], 10); | |
// stop CLS from going out on pre-unload beacons | |
delete data["c.cls"]; | |
} | |
} | |
// extracts page dimensions from the first beacon for use with the exit beacon | |
function extractDimensions(data) { | |
if (this.unloadSent || this.extractedDimensions) { | |
return; | |
} | |
// extract any other dimensions from the base page | |
if (!data["http.initiator"]) { | |
this.extractedDimensions = true; | |
// page group | |
if (data["h.pg"]) { | |
this.extraVars["h.pg"] = data["h.pg"]; | |
} | |
// custom dimensions | |
for (var varName in data) { | |
if (varName.indexOf("cdim.") === 0) { | |
this.extraVars[varName] = data[varName]; | |
} | |
} | |
} | |
} | |
// Subscribe to both before_beacon and beacon as it depends on the load | |
// order when the Continuity plugin will run vs. this plugin | |
BOOMR.subscribe("before_beacon", extractCls, null, this); | |
BOOMR.subscribe("beacon", extractCls, null, this); | |
BOOMR.subscribe("before_beacon", extractDimensions, null, this); | |
BOOMR.subscribe("beacon", extractDimensions, null, this); | |
// At page_unload, send an 'Exit' (manual) beacon | |
BOOMR.subscribe("page_unload", function(data) { | |
if (this.unloadSent) { | |
return; | |
} | |
this.unloadSent = true; | |
var data = {}; | |
// when this beacon fired | |
data["rt.tstart"] = data["rt.end"] = BOOMR.now(); | |
// crumb | |
data.d = BOOMR.session.domain; | |
data["h.key"] = BOOMR.getVar("h.key"); | |
data["h.d"] = BOOMR.getVar("h.d"); | |
data["h.cr"] = BOOMR.getVar("h.cr"); | |
data["h.t"] = BOOMR.getVar("h.t"); | |
// page id | |
data.pid = BOOMR.pageId; | |
// start event = manual | |
data["rt.start"] = "manual"; | |
// session data | |
if (BOOMR.session && BOOMR.session.ID !== false) { | |
data["rt.si"] = BOOMR.session.ID + "-" + Math.round(BOOMR.session.start / 1000).toString(36); | |
data["rt.ss"] = BOOMR.session.start; | |
data["rt.sl"] = BOOMR.session.length; | |
} | |
// API info | |
data.api = 1; | |
data["api.v"] = 2; | |
data["api.l"] = "boomr"; | |
data.v = BOOMR.version; | |
data.n = ++BOOMR.beaconsSent; | |
// extra dimensions we captured from the first beacon | |
for (var varName in this.extraVars) { | |
data[varName] = this.extraVars[varName]; | |
} | |
// CWV data | |
var fid = BOOMR.plugins.EventTiming.metrics.firstInputDelay() || | |
BOOMR.plugins.Continuity.metrics.firstInputDelay(); | |
if (fid !== null) { | |
data["et.fid"] = fid; | |
} | |
if (window.LayoutShift) { | |
// add any CLS from the last beacon | |
this.cls = this.cls + BOOMR.plugins.Continuity.metrics.clsScore(); | |
data["c.cls"] = this.cls; | |
} | |
// send the beacon data to the specified URL | |
if (typeof fid === "number" || typeof this.cls === "number") { | |
BOOMR.sendBeaconData(data); | |
} | |
}, null, this); | |
}, | |
is_complete: function() { | |
return true; | |
} | |
}; |
The following options should be set via BOOMR_config
or edge configuration (mPulse):
window.BOOMR_config = window.BOOMR_config || {};
window.BOOMR_config.Continuity = window.BOOMR_config.Continuity || {};
window.BOOMR_config.Continuity.enabled = true;
window.BOOMR_config.Continuity.afterOnload = true;
window.BOOMR_config.Continuity.afterOnloadMaxLength = false;
Edge config:
{
"Continuity": {
"enabled": true,
"afterOnload": true,
"afterOnloadMaxLength": false
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Minified: