Skip to content
Draft
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
2 changes: 2 additions & 0 deletions src/frontend/ec.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers';
import ecTwoSlash from 'expressive-code-twoslash';
import { tsImport } from 'tsx/esm/api';
import { pluginDisableCopy } from './src/expressive-code-plugins/disable-copy.mjs';
import { pluginFunnelMetadata } from './src/expressive-code-plugins/funnel-metadata.mjs';
import {
TWOSLASH_ENABLED,
TWOSLASH_LANGUAGES,
Expand Down Expand Up @@ -47,6 +48,7 @@ export default {
pluginLineNumbers(),
pluginIcon(),
pluginDisableCopy(),
pluginFunnelMetadata(),
...(TWOSLASH_ENABLED
? [
ecTwoSlash({
Expand Down
134 changes: 130 additions & 4 deletions src/frontend/public/scripts/analytics/1ds.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,88 @@
/* global location, oneDS, window */
/* global document, location, oneDS, window */

(function () {
const NOT_FOUND_REFERRER_MARKER_KEY = 'aspire-last-route-not-found';

function isNotFoundPage() {
return Boolean(document.querySelector('[data-funnel="not_found_recovery"][data-funnel-view]'));
}

function consumeNotFoundReferrerMarker() {
try {
const wasNotFound = window.sessionStorage.getItem(NOT_FOUND_REFERRER_MARKER_KEY) === 'true';
window.sessionStorage.removeItem(NOT_FOUND_REFERRER_MARKER_KEY);
return wasNotFound;
} catch (err) {
console.debug('[1ds] Failed to read the 404 referrer marker:', err);
return false;
}
}

function rememberNotFoundRoute(notFound) {
try {
if (notFound) {
window.sessionStorage.setItem(NOT_FOUND_REFERRER_MARKER_KEY, 'true');
} else {
window.sessionStorage.removeItem(NOT_FOUND_REFERRER_MARKER_KEY);
}
} catch (err) {
console.debug('[1ds] Failed to update the 404 referrer marker:', err);
}
}

let previousRouteWasNotFound = consumeNotFoundReferrerMarker();
let currentRouteIsNotFound = isNotFoundPage();

function sanitizeTelemetryUrl(value, isReferrer) {
if (typeof value !== 'string' || !value) return value;

try {
const url = new URL(value, location.origin);
if (isReferrer && url.origin !== location.origin) {
return url.origin === 'null' ? '' : url.origin + '/';
}
if (
url.origin === location.origin &&
((isReferrer && previousRouteWasNotFound) ||
(currentRouteIsNotFound && url.pathname === location.pathname))
) {
url.pathname = '/404/';
}
url.search = '';
url.hash = '';
return url.toString();
} catch (err) {
console.debug('[1ds] Dropping invalid telemetry URL:', err);
return '';
}
}

function sanitizeTelemetryUrls(item) {
[item && item.baseData, item && item.data].forEach(function (properties) {
if (!properties) return;

['uri', 'targetUri', 'refUri', 'referrerUri'].forEach(function (property) {
if (property in properties) {
properties[property] = sanitizeTelemetryUrl(
properties[property],
property === 'refUri' || property === 'referrerUri'
);
}
});
});
}

function getTelemetryPageName() {
if (currentRouteIsNotFound) return '404';

const segments = location.pathname.split('/').filter(Boolean);
return segments.length ? segments[segments.length - 1] : 'Home';
}

function getTelemetryRouteKey(notFound) {
return location.origin + (notFound ? '/404/' : location.pathname);
}

if (typeof location !== 'undefined' && location.origin !== 'https://aspire.dev') {
console.debug('[1ds] Skipping load for origin:', location.origin);
return;
Expand All @@ -16,6 +98,7 @@
}

try {
const initialReferrerUri = sanitizeTelemetryUrl(document.referrer || '', true);
const analytics = new oneDS.ApplicationInsights();
analytics.initialize(
{
Expand All @@ -24,11 +107,15 @@
channelConfiguration: { eventsLimitInMem: 50 },
propertyConfiguration: { env: 'PROD' },
webAnalyticsConfiguration: {
urlCollectQuery: true,
urlCollectQuery: false,
callback: { pageName: getTelemetryPageName },
coreData: { referrerUri: initialReferrerUri },
autoCapture: {
scroll: true,
pageView: true,
onLoad: true,
// Capture these manually after URL sanitization is registered so the
// initial document stays private and Astro routes are not double-counted.
pageView: false,
onLoad: false,
onUnload: true,
click: true,
resize: true,
Expand All @@ -39,6 +126,45 @@
[]
);

analytics.addTelemetryInitializer(sanitizeTelemetryUrls);

let lastPageViewKey = '';
let previousPageViewUri = initialReferrerUri;
let hasCapturedRoute = false;
const captureRouteView = function () {
const nextRouteIsNotFound = isNotFoundPage();
const routeKey = getTelemetryRouteKey(nextRouteIsNotFound);
if (routeKey === lastPageViewKey) return;

if (hasCapturedRoute) {
previousRouteWasNotFound = currentRouteIsNotFound;
}
currentRouteIsNotFound = nextRouteIsNotFound;
lastPageViewKey = routeKey;

analytics.capturePageView({ isAuto: true, referrerUri: previousPageViewUri });
if (hasCapturedRoute) {
analytics.captureContentUpdate({ isAuto: true, isDomComplete: true });
}

previousPageViewUri = routeKey;
rememberNotFoundRoute(currentRouteIsNotFound);
hasCapturedRoute = true;
};

document.addEventListener('astro:page-load', captureRouteView);
captureRouteView();

const captureLoadEvents = function () {
analytics.capturePageViewPerformance({ isAuto: true });
analytics.captureContentUpdate({ isAuto: true, isDomComplete: true });
};
if (document.readyState === 'complete') {
captureLoadEvents();
} else {
window.addEventListener('load', captureLoadEvents, { once: true });
}

analytics.__initialized = true;
window.analytics = analytics;
} catch (err) {
Expand Down
Loading
Loading