Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions tools/oversight/elements/list-facet.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,37 @@ export default class ListFacet extends HTMLElement {
return li;
}

/**
* Creates a business metric chiclet (visual indicator) for displaying performance metrics
* in the facet list. The chiclet includes a meter/gauge with color-coded thresholds and
* a formatted number display.
*
* @param {Object} entry - The data entry containing metrics for this facet value
* @param {string} rate - The metric name to display (e.g., 'bounces', 'timeOnPage', 'organic')
* @param {string|null} baseline - The baseline metric for rate calculations. If null,
* displays absolute values (median). If string, calculates
* conversion rate between rate and baseline metrics.
* @param {number} low - Low threshold for the meter (red zone)
* @param {number} high - High threshold for the meter (yellow zone)
* @param {number} optimum - Optimum threshold for the meter (green zone)
* @returns {HTMLElement} A list item element containing the metric chiclet
*
* @example
* // Create a bounce rate chiclet (percentage-based)
* const bounceRateLI = this.createBusinessMetricChiclet(entry, 'bounces', 'visits', 60, 40, 20);
*
* @example
* // Create a time on page chiclet (absolute values)
* const timeOnPageLI = this.createBusinessMetricChiclet(entry, 'timeOnPage', null, 1, 2, 5);
*
* @description
* The method creates a visual meter with the following features:
* - Color-coded performance zones (red/yellow/green)
* - Formatted number display with precision control
* - Automatic meter scale (0-10 for small values, 0-100 for larger values)
* - Statistical significance indicators (when baseline is provided)
* - Support for both rate calculations and absolute value displays
*/
createBusinessMetricChiclet(entry, rate, baseline, low, high, optimum) {
const li = document.createElement('li');
li.classList.add('business-metric');
Expand Down
23 changes: 14 additions & 9 deletions tools/oversight/explorer.html
Original file line number Diff line number Diff line change
Expand Up @@ -451,20 +451,25 @@ <h2>TTFB</h2>
<a href="/docs/optel-explorer#facet-utm" class="help" target="_blank"
title="categorization of the UTM sources driving traffic to the site"></a>
</list-facet>
<list-facet facet="formsubmit.source"
href="/docs/optel-explorer#facet-formsubmit" class="help" target="_blank"
title="Which forms the user submitted">
<list-facet facet="formsubmit.source">
<legend>Form Submit Source (CSS Selector)</legend>
<a href="/docs/optel-explorer#facet-formsubmit" class="help" target="_blank"
title="Which forms the user submitted"></a>
</list-facet>
<list-facet facet="formsubmit.target"
href="/docs/optel-explorer#facet-formsubmit" class="help" target="_blank"
title="The endpoints where the user submitted the form">
<list-facet facet="formsubmit.target">
<legend>Form Submit Target</legend>
<a href="/docs/optel-explorer#facet-formsubmit" class="help" target="_blank"
title="The endpoints where the user submitted the form"></a>
</list-facet>
<list-facet facet="fill.source"
href="/docs/optel-explorer#facet-fill" class="help" target="_blank"
title="The fields of the form that the user filled">
<list-facet facet="formsubmit.histogram" sort="asc">
<legend>Form Submit Time (mm:ss)</legend>
<a href="/docs/optel-explorer#facet-formsubmit" class="help" target="_blank"
title="How much time did the user take to submit the form"></a>
</list-facet>
<list-facet facet="fill.source">
<legend>Form Field Source (CSS Selector)</legend>
<a href="/docs/optel-explorer#facet-fill" class="help" target="_blank"
title="The fields of the form that the user filled"></a>
</list-facet>
</facet-sidebar>
</div>
Expand Down
41 changes: 41 additions & 0 deletions tools/oversight/slicer.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ dataChunks.addSeries('timeOnPage', (bundle) => {
return (deltas.reduce((a, b) => Math.max(a, b), -Infinity)) / 1000;
});

/**
* Formats seconds to mm:ss format
* @param {number} seconds - Time in seconds
* @returns {string} Formatted time as mm:ss
*/
function formatTimeToMMSS(seconds) {
if (seconds === undefined || seconds === null || Number.isNaN(seconds)) {
return undefined;
}
const minutes = Math.floor(seconds / 60);
const remainingSeconds = Math.floor(seconds % 60);
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
}

function timeToSubmit(bundle) {
const filteredEvents = bundle.events.filter((evt) => evt.checkpoint === 'formsubmit' || evt.checkpoint === 'viewblock');
const submitEvent = filteredEvents.find((evt) => evt.checkpoint === 'formsubmit');
if (!submitEvent) {
return undefined;
}
const formViewEvent = filteredEvents.find((evt) => evt.checkpoint === 'viewblock' && evt.source === submitEvent.source);
if (!formViewEvent) {
return undefined;
}
return (submitEvent.timeDelta - formViewEvent.timeDelta) / 1000;
}
dataChunks.addSeries('contentEngagement', (bundle) => {
const viewEvents = bundle.events
.filter((evt) => evt.checkpoint === 'viewmedia' || evt.checkpoint === 'viewblock');
Expand Down Expand Up @@ -213,6 +239,8 @@ function updateDataFacets(filterText, params, checkpoint) {

dataChunks.addFacet('checkpoint', facets.checkpoint, 'every', 'none');

dataChunks.addFacet('formsubmit.time', timeToSubmit);

dataChunks.addFacet(
'conversions',
(bundle) => (dataChunks.hasConversion(bundle, conversionSpec) ? 'converted' : 'not-converted'),
Expand Down Expand Up @@ -285,6 +313,19 @@ function updateDataFacets(filterText, params, checkpoint) {
);
}

if (cp === 'formsubmit') {
dataChunks.addHistogramFacet(
'formsubmit.histogram',
'formsubmit.time',
{
count: 10, min: 0, max: 600, steps: 'quantiles',
},
{
format: formatTimeToMMSS,
},
);
}

// a bit of special handling here, so we can split the acquisition source
if (cp === 'acquisition') {
dataChunks.addFacet('acquisition.source', acquisitionSource);
Expand Down