mirror of https://github.com/Qiskit/qiskit.org.git
195 lines
4.6 KiB
TypeScript
195 lines
4.6 KiB
TypeScript
import type { CtaClickedEventSegmentSchema } from "~/types/segment";
|
|
|
|
/**
|
|
* Set of configuration objects and flags required by Bluemix Analytics.
|
|
* Main configuration objects are `_analytics`, `bluemixAnalytics` and
|
|
* `digitalData`.
|
|
*
|
|
* See
|
|
* https://github.ibm.com/Bluemix/Bluemix.Analytics/blob/master/webpack.constants.js
|
|
* for default values.
|
|
*/
|
|
export interface AnalyticsContext {
|
|
_analytics?: any;
|
|
_analyticsReady?: Promise<Event>;
|
|
bluemixAnalytics?: any;
|
|
digitalData?: any;
|
|
}
|
|
|
|
declare global {
|
|
interface Window extends AnalyticsContext {}
|
|
}
|
|
|
|
function getOrFailProductTitle(digitalData: any): string {
|
|
return assertCanGet(
|
|
() => digitalData.page.pageInfo.productTitle,
|
|
"`digitalData.page.pageInfo.productTitle` is missing"
|
|
);
|
|
}
|
|
|
|
function getOrFailCategory(digitalData: any): string {
|
|
return assertCanGet(
|
|
() => digitalData.page.pageInfo.analytics.category,
|
|
"`digitalData.page.pageInfo.analytics.category` is missing"
|
|
);
|
|
}
|
|
|
|
function assertCanGet<T>(getter: () => T, error: string): T {
|
|
let result;
|
|
try {
|
|
result = getter();
|
|
} catch (ex) {}
|
|
if (!result) {
|
|
throw new Error(error);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Minimum configutarion for the analytics system.
|
|
* @param key public key to send analytics
|
|
*/
|
|
function configureAnalytics(key: string) {
|
|
window._analytics = {
|
|
segment_key: key,
|
|
coremetrics: false,
|
|
optimizely: false,
|
|
googleAddServices: false,
|
|
fullStory: false,
|
|
autoPageEventSpa: false,
|
|
autoFormEvents: false,
|
|
autoPageView: false,
|
|
};
|
|
|
|
window.digitalData = {
|
|
page: {
|
|
pageInfo: {
|
|
productTitle: "IBM Q Experience",
|
|
analytics: {
|
|
category: "Qiskit.org",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* This adds to the head the script tag with the configuration set in the env var.
|
|
* @param url to connect with the analytics server
|
|
*/
|
|
function installAnalytics(url: string) {
|
|
return new Promise<Event>((resolve, reject) => {
|
|
const script = document.createElement("script");
|
|
script.async = true;
|
|
script.src = url || "";
|
|
document.head.appendChild(script);
|
|
script.onload = resolve;
|
|
script.onerror = (err) => {
|
|
// eslint-disable-next-line no-console
|
|
console.warn("Error loading Bluemix Analytics script:", err);
|
|
reject(err);
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Send a page visitation event to segment.
|
|
* @param context the Bluemix Analytics object with the analytics configuration.
|
|
* This is usually `window`.
|
|
* @param routeName a unique name identifying the contents of the route.
|
|
* @param title the title meta tag of the page
|
|
*/
|
|
function trackPage(
|
|
context: AnalyticsContext,
|
|
routeName: string,
|
|
title: string
|
|
) {
|
|
const { bluemixAnalytics, digitalData } = context;
|
|
|
|
if (!bluemixAnalytics || !digitalData) {
|
|
return;
|
|
}
|
|
|
|
const category = getOrFailCategory(digitalData);
|
|
const productTitle = getOrFailProductTitle(digitalData);
|
|
|
|
bluemixAnalytics.pageEvent(category, routeName, {
|
|
navigationType: "pushState",
|
|
productTitle,
|
|
title,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Send the information of a CTA click event to Segment.
|
|
* @param context Window that extends Bluemix Analytics configuration
|
|
* @param cta The call to action
|
|
* @param location Location in the UI
|
|
*/
|
|
function trackClickEvent(
|
|
context: AnalyticsContext,
|
|
cta: string,
|
|
location: string
|
|
) {
|
|
const { bluemixAnalytics, digitalData } = context;
|
|
|
|
if (!bluemixAnalytics || !digitalData) {
|
|
return;
|
|
}
|
|
|
|
const productTitle = getOrFailProductTitle(digitalData);
|
|
const category = getOrFailCategory(digitalData);
|
|
|
|
const segmentOptions: CtaClickedEventSegmentSchema = {
|
|
category,
|
|
CTA: cta,
|
|
location,
|
|
productTitle,
|
|
};
|
|
|
|
bluemixAnalytics.trackEvent("CTA Clicked", segmentOptions);
|
|
}
|
|
|
|
/**
|
|
* Helper to wait until the analytics script is loaded
|
|
* @param callback
|
|
* @returns Promise<void>
|
|
*/
|
|
function afterAnalyticsReady<S extends any[]>(callback: (...S: any[]) => void) {
|
|
return async function (...args: S) {
|
|
try {
|
|
await useState("analyticsReady").value;
|
|
callback(window, ...args);
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn(err);
|
|
}
|
|
};
|
|
}
|
|
|
|
export const useSegment = () => {
|
|
const nuxtApp = useNuxtApp();
|
|
|
|
if (nuxtApp.ssrContext) {
|
|
return {
|
|
trackClickEvent: () => {},
|
|
trackPage: () => {},
|
|
};
|
|
}
|
|
|
|
const runtimeConfig = useRuntimeConfig();
|
|
|
|
if (runtimeConfig.public.isAnalyticsEnabled) {
|
|
configureAnalytics(runtimeConfig.public.analyticsKey);
|
|
|
|
useState("analyticsReady", () =>
|
|
installAnalytics(runtimeConfig.public.analyticsScriptUrl)
|
|
);
|
|
}
|
|
|
|
return {
|
|
trackClickEvent: afterAnalyticsReady(trackClickEvent),
|
|
trackPage: afterAnalyticsReady(trackPage),
|
|
};
|
|
};
|