Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/frontend/plugins/segmentAnalytics.ts
3855 views
1
2
import {
3
CtaClickedEventSegmentSchema,
4
PerformedSearchEventSegmentSchema,
5
UpdatedObjectEventSegmentSchema
6
} from '../constants/segment'
7
8
/**
9
* Set of configuration objects and flags required by Bluemix Analytics.
10
* Main configuration objects are `_analytics`, `bluemixAnalytics` and
11
* `digitalData`.
12
*
13
* See
14
* https://github.ibm.com/Bluemix/Bluemix.Analytics/blob/master/webpack.constants.js
15
* for default values.
16
*/
17
interface AnalyticsContext {
18
_analytics?: any
19
_analyticsReady?: Promise<Event>
20
bluemixAnalytics?: any
21
digitalData?: any
22
}
23
24
interface TextbookAnalytics {
25
textbookAnalytics: {
26
url: string,
27
key: string
28
}
29
}
30
31
declare global {
32
interface Window extends AnalyticsContext, TextbookAnalytics {}
33
}
34
35
function configureAnalytics (analyticsKey: string) {
36
window._analytics = {
37
segment_key: analyticsKey,
38
coremetrics: false,
39
optimizely: false,
40
googleAddServices: false,
41
fullStory: false,
42
autoPageEventSpa: false,
43
autoFormEvents: false,
44
autoPageView: false
45
}
46
47
window.digitalData = {
48
page: {
49
pageInfo: {
50
productTitle: 'IBM Q Experience',
51
analytics: {
52
category: 'Qiskit.org'
53
}
54
}
55
}
56
}
57
}
58
59
function installAnalyticsOnce (
60
analyticsScriptUrl: string = ''
61
): Promise<Event|void> {
62
window._analyticsReady = window._analyticsReady || new Promise<Event>((resolve, reject) => {
63
const script = document.createElement('script')
64
script.async = true
65
script.src = analyticsScriptUrl
66
document.head.appendChild(script)
67
script.onload = resolve
68
script.onerror = (err) => {
69
console.warn('Error loading Bluemix Analytics script:', err)
70
reject(err)
71
}
72
})
73
return window._analyticsReady
74
}
75
76
/**
77
* Send a page visitation event to segment.
78
* @param title the title meta tag of the page
79
*/
80
function trackPage (title: string) {
81
const { bluemixAnalytics, digitalData } = window
82
83
if (!bluemixAnalytics || !digitalData) { return }
84
85
const category = getOrFailCategory(digitalData)
86
const productTitle = getOrFailProductTitle(digitalData)
87
const routeName = 'project-platypus'
88
89
bluemixAnalytics.pageEvent(category, routeName, {
90
navigationType: 'pushState',
91
productTitle,
92
title
93
})
94
}
95
96
/**
97
* Send the information of a CTA click event to Segment.
98
* @param cta The call to action
99
* @param location Location in the UI
100
*/
101
function trackClickEvent (cta: string, location: string) {
102
const { bluemixAnalytics, digitalData } = window
103
104
if (!bluemixAnalytics || !digitalData) { return }
105
106
const productTitle = getOrFailProductTitle(digitalData)
107
const category = getOrFailCategory(digitalData)
108
109
const segmentOptions: CtaClickedEventSegmentSchema = {
110
category,
111
CTA: cta,
112
location,
113
productTitle
114
}
115
116
bluemixAnalytics.trackEvent('CTA Clicked', segmentOptions)
117
}
118
119
/**
120
* Send the information of a "Performed Search" event to Segment.
121
* @param context Bluemix Analytics configuration
122
* @param uiElement The UI element that was used to trigger this event
123
* @param field Search input
124
*/
125
function trackPerformedSearch (uiElement: string, field: string) {
126
const { bluemixAnalytics, digitalData } = window
127
128
if (!bluemixAnalytics || !digitalData) { return }
129
130
const productTitle = getOrFailProductTitle(digitalData)
131
const category = getOrFailCategory(digitalData)
132
133
const eventOptions: PerformedSearchEventSegmentSchema = {
134
category,
135
productTitle,
136
uiElement,
137
field
138
}
139
140
bluemixAnalytics.trackEvent('Performed Search', eventOptions)
141
}
142
143
/**
144
* Send the information of a "Updated Object" event to Segment.
145
* @param context Bluemix Analytics configuration
146
* @param objectType Type of object that was updated
147
* @param object Object that was updated
148
*/
149
function trackUpdatedObject (objectType: string, object: string) {
150
const { bluemixAnalytics, digitalData } = window
151
152
if (!bluemixAnalytics || !digitalData) { return }
153
154
const productTitle = getOrFailProductTitle(digitalData)
155
const category = getOrFailCategory(digitalData)
156
157
const eventOptions: UpdatedObjectEventSegmentSchema = {
158
category,
159
productTitle,
160
object,
161
objectType
162
}
163
164
bluemixAnalytics.trackEvent('Updated Object', eventOptions)
165
}
166
167
function getOrFailProductTitle (digitalData: any): string {
168
return assertCanGet(
169
() => digitalData.page.pageInfo.productTitle,
170
'`digitalData.page.pageInfo.productTitle` is missing'
171
)
172
}
173
174
function getOrFailCategory (digitalData: any): string {
175
return assertCanGet(
176
() => digitalData.page.pageInfo.analytics.category,
177
'`digitalData.page.pageInfo.analytics.category` is missing'
178
)
179
}
180
181
function assertCanGet<T> (getter: () => T, error: string): T {
182
let result
183
try {
184
result = getter()
185
} catch (ex) { }
186
if (!result) {
187
throw new Error(error)
188
}
189
return result
190
}
191
192
function initAnalytics (key: string, url: string): Promise<Event|void> {
193
configureAnalytics(key)
194
return installAnalyticsOnce(url)
195
}
196
197
function install (app: any, _options: any = {}) {
198
initAnalytics(window.textbookAnalytics.key, window.textbookAnalytics.url)
199
app.config.globalProperties.$trackClickEvent = trackClickEvent
200
app.config.globalProperties.$trackPage = trackPage
201
app.config.globalProperties.$trackPerformedSearch = trackPerformedSearch
202
app.config.globalProperties.$trackUpdatedObject = trackUpdatedObject
203
}
204
205
export {
206
initAnalytics,
207
install,
208
trackClickEvent,
209
trackPage,
210
trackPerformedSearch,
211
trackUpdatedObject
212
}
213
214
export type {
215
AnalyticsContext
216
}
217
218