Skip to content

Commit

Permalink
feat: add in ootb event mappngs
Browse files Browse the repository at this point in the history
  • Loading branch information
convell committed Mar 12, 2024
1 parent bf97ccb commit e5ea7fc
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 14 deletions.
39 changes: 33 additions & 6 deletions config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,69 @@ export interface Config {
analytics: {
qm: {
/**
* Frontend root URL
* Controls if plugin is on or off
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
enabled: boolean;
/**
* Frontend root URL
* Turns on console.debug messages
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
debug: boolean;
/**
* Frontend root URL
* Sends events to console log instead of quantum metric
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
test: boolean;
/**
* Frontend root URL
* Quantum Metric CDN source URL
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
src: string;
/**
* Frontend root URL
* Controls wether or not to block on Quantum Metric API
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
async: number;
/**
* Frontend root URL
* Global attributes to be included on all events
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
attributes: any;

/**
* Event mapping of OOTB events like navigation/search to their Quantum Metric event IDs
* @deepvisibility frontend
*/
events: {
/**
* Global attributes to be included on all events
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
mappings: {
/**
* Global attributes to be included on all events
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
name: string;
/**
* Global attributes to be included on all events
* NOTE: Visibility applies to only this field
* @visibility frontend
*/
id: number;
}[];
};
};
};
};
}

78 changes: 70 additions & 8 deletions src/api/QuantumMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type QMConfig = {
debug: boolean;
src: string;
async: boolean;
events: eventsConfig[];
};

type QuantumMetricAPI = {
Expand All @@ -36,6 +37,8 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
private readonly capture: QuantumMetricAPI = {} as QuantumMetricAPI;
private test: boolean = false;
private debug: boolean = false;
private eventsMapping: eventsConfig[] = [{} as eventsConfig];
private quantumInstalled: boolean = false;

/*
* Class constructor is responsible for interpreting and respecting the provided options and config values, and setting
Expand All @@ -45,7 +48,7 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
identityApi?: IdentityApi;
qmConfig: QMConfig;
}) {
const { enabled, test, debug, src, async } = options.qmConfig;
const { enabled, test, debug, src, async, events } = options.qmConfig;

if (!enabled) {
if (debug) console.debug("Quantum Metric Analytics plugin disabled.");
Expand All @@ -55,7 +58,7 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
this.test = test;
this.debug = debug;

if (src) {
if (src && !window.hasOwnProperty("QuantumMetricAPI")) {
if (this.debug) console.debug(`Fetching Quantum Metric API from ${src}`);

this.installQuantum(async, src);
Expand All @@ -69,21 +72,36 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
if (options.identityApi) {
if (this.debug)
console.debug("Identity API provided; Identifying user by email");

if (this.debug) console.debug("Quantum Loaded");
options.identityApi.getProfileInfo().then((profile) => {
if (profile?.email) this.capture.identifyUser(profile.email);
});
}

if (events) {
this.eventsMapping = events;
} else if (!events && debug) {
console.debug(
"Events mapping not passed in, OOTB events will not be sent to Quantum Metric"
);
}
}

private installQuantum(async: boolean, src: string) {
if (this.quantumInstalled) {
return;
}

this.quantumInstalled = true;
const qtm = document.createElement("script");
qtm.type = "text/javascript";
qtm.async = async;
qtm.src = src;

// Install before any other script
const d = document.getElementsByTagName("script")[0];
if (d && d.parentNode) {
if (d.parentNode) {
d.parentNode.insertBefore(qtm, d);
}
}
Expand All @@ -98,6 +116,17 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
console.warn(
"Unexpected source provided; Expected source to start with https://cdn.quantummetric.com/"
);

if (config.events) {
const filteredEvents = config.events.filter(
(event) => event.name && event.id
);
if (filteredEvents.length !== config.events) {
console.warn(
"Event mapping passed in that did not specify a name or ID"
);
}
}
}

/**
Expand All @@ -117,13 +146,17 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
const async = config.getOptionalBoolean("app.analytics.qm.async") ?? false;
const test = config.getOptionalBoolean("app.analytics.qm.test") ?? false;
const debug = config.getOptionalBoolean("app.analytics.qm.debug") ?? false;
const events = (config.getOptional(
"app.analytics.qm.events.mappings"
) as eventsConfig[]) ?? [{} as eventsConfig];

const qmConfig: QMConfig = {
enabled, // Disables plugin
test, // When enabled, events are logged to console instead of sent to Quantum Metric
debug, // Turns on console.debug messages
src, // CDN location of Quantum Metric API
async, // Wether or not to block on loading Quantum Metric API onto the page
events, // Mapping of OOTB backstage events to Quantum Metric event IDs
};

this.validateConfig(qmConfig);
Expand All @@ -139,26 +172,55 @@ export class QuantumMetric implements AnalyticsApi, NewAnalyticsApi {
* captureEvent handles sending events to Quantum Metric via the fetched window API
*/
captureEvent(event: AnalyticsEvent | NewAnalyticsEvent) {
const { action, subject, value, attributes } = event;

if (this.test) {
console.log(`Test Event received: ${JSON.stringify(event)}; Returning`);
return;
}

if (this.debug) console.debug(`Event received: ${JSON.stringify(event)}`);

const { action, subject, value, attributes } = event;
const mappedEventNames = this.eventsMapping.map((mapping) => mapping.name);
const mappedEventIndex = mappedEventNames.indexOf(action);

// OOTB Events
if (mappedEventIndex !== -1) {
const eventId = this.eventsMapping[mappedEventIndex].id;
const eventValue = value ?? subject;

if (this.debug)
console.debug(
`Detected event mapping; Sending event id ${eventId} to Quantum Metric`
);
this.capture.sendEvent(
eventId,
0,
eventValue,
attributes as Record<string, string>
);

if (this.debug)
console.debug(`Event id ${eventId} sent to Quantum Metric`);

return;
}

if (action === "sendEvent") {
if (!value) return; // TODO comback and remove this hack
const eventId = value;
const eventValue = subject;
const eventId = subject;
const eventValue = value;

console.debug(
`Detected custom event; Sending event id ${eventId} to Quantum Metric`
);

this.capture.sendEvent(
eventId,
0,
eventValue,
attributes as Record<string, string>
);
if (this.debug)
console.debug(`Event id ${eventId} sent to Quantum Metric`);
}
}
}

0 comments on commit e5ea7fc

Please sign in to comment.