@coursebuilder/analytics 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api/index.d.ts +158 -0
  3. package/dist/api/index.js +317 -0
  4. package/dist/api/index.js.map +1 -0
  5. package/dist/catalog.d.ts +14 -0
  6. package/dist/catalog.js +209 -0
  7. package/dist/catalog.js.map +1 -0
  8. package/dist/components/index.d.ts +172 -0
  9. package/dist/components/index.js +1258 -0
  10. package/dist/components/index.js.map +1 -0
  11. package/dist/engine.d.ts +20 -0
  12. package/dist/engine.js +350 -0
  13. package/dist/engine.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +353 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/providers/database.d.ts +79 -0
  18. package/dist/providers/database.js +533 -0
  19. package/dist/providers/database.js.map +1 -0
  20. package/dist/providers/derived.d.ts +45 -0
  21. package/dist/providers/derived.js +32 -0
  22. package/dist/providers/derived.js.map +1 -0
  23. package/dist/providers/ga4.d.ts +43 -0
  24. package/dist/providers/ga4.js +220 -0
  25. package/dist/providers/ga4.js.map +1 -0
  26. package/dist/providers/index.d.ts +8 -0
  27. package/dist/providers/index.js +1239 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/mux.d.ts +103 -0
  30. package/dist/providers/mux.js +241 -0
  31. package/dist/providers/mux.js.map +1 -0
  32. package/dist/providers/survey.d.ts +102 -0
  33. package/dist/providers/survey.js +233 -0
  34. package/dist/providers/survey.js.map +1 -0
  35. package/dist/types.d.ts +303 -0
  36. package/dist/types.js +1 -0
  37. package/dist/types.js.map +1 -0
  38. package/package.json +101 -0
  39. package/src/api/catalog-handler.ts +321 -0
  40. package/src/api/index.ts +4 -0
  41. package/src/api/token-handler.ts +71 -0
  42. package/src/catalog.ts +223 -0
  43. package/src/components/country-chart.tsx +114 -0
  44. package/src/components/index.ts +5 -0
  45. package/src/components/omnibus-dashboard.tsx +1460 -0
  46. package/src/components/revenue-chart.tsx +251 -0
  47. package/src/components/use-chart-colors.ts +75 -0
  48. package/src/engine.ts +201 -0
  49. package/src/index.ts +7 -0
  50. package/src/providers/database.ts +795 -0
  51. package/src/providers/derived.ts +79 -0
  52. package/src/providers/ga4.ts +173 -0
  53. package/src/providers/index.ts +44 -0
  54. package/src/providers/mux.ts +438 -0
  55. package/src/providers/survey.ts +487 -0
  56. package/src/types.ts +333 -0
package/src/types.ts ADDED
@@ -0,0 +1,333 @@
1
+ declare const __brand: unique symbol
2
+
3
+ type Brand<T, B extends string> = T & { readonly [__brand]: B }
4
+
5
+ export type USD = Brand<number, 'USD'>
6
+ export type Count = Brand<number, 'Count'>
7
+ export type Percentage = Brand<number, 'Percentage'>
8
+ export type Minutes = Brand<number, 'Minutes'>
9
+ export type Seconds = Brand<number, 'Seconds'>
10
+
11
+ export type AnalyticsRange = '24h' | '7d' | '30d' | '90d' | 'all'
12
+
13
+ export interface RevenueSummary {
14
+ totalRevenue: USD
15
+ purchaseCount: Count
16
+ avgOrderValue: USD
17
+ }
18
+
19
+ export interface RevenueDaily {
20
+ date: string
21
+ revenue: USD
22
+ count: Count
23
+ }
24
+
25
+ export interface RevenueByProduct {
26
+ productId: string
27
+ productName: string
28
+ revenue: USD
29
+ count: Count
30
+ }
31
+
32
+ export interface RevenueByCountry {
33
+ country: string
34
+ revenue: USD
35
+ count: Count
36
+ }
37
+
38
+ export interface RecentPurchase {
39
+ id: string
40
+ createdAt: Date
41
+ totalAmount: USD
42
+ productName: string
43
+ productId: string
44
+ country: string | null
45
+ couponId: string | null
46
+ userName: string | null
47
+ userEmail: string | null
48
+ }
49
+
50
+ export interface AttributionCount {
51
+ type: string
52
+ count: Count
53
+ }
54
+
55
+ export interface ShortlinkPerformance {
56
+ shortlinkId: string
57
+ slug: string
58
+ url: string
59
+ clicks: Count
60
+ }
61
+
62
+ export interface RevenueBySource {
63
+ source: string
64
+ medium: string
65
+ campaign: string | null
66
+ revenue: USD
67
+ count: Count
68
+ }
69
+
70
+ export interface ConversionFunnel {
71
+ totalSignups: Count
72
+ totalPurchases: Count
73
+ attributedPurchases: Count
74
+ unattributedPurchases: Count
75
+ conversionRate: Percentage
76
+ attributionCoverage: Percentage
77
+ }
78
+
79
+ export interface ContentCorrelation {
80
+ resourceId: string
81
+ purchaserCount: Count
82
+ }
83
+
84
+ export interface AttributionCoverage {
85
+ totalRevenue: USD
86
+ attributedRevenue: USD
87
+ unattributedRevenue: USD
88
+ attributionRate: Percentage
89
+ totalPurchases: Count
90
+ }
91
+
92
+ export interface TrafficOverview {
93
+ sessions: Count
94
+ totalUsers: Count
95
+ newUsers: Count
96
+ pageviews: Count
97
+ avgSessionDuration: Seconds
98
+ bounceRate: Percentage
99
+ }
100
+
101
+ export interface TrafficDaily {
102
+ date: string
103
+ sessions: Count
104
+ users: Count
105
+ pageviews: Count
106
+ }
107
+
108
+ export interface TopPage {
109
+ path: string
110
+ pageviews: Count
111
+ users: Count
112
+ avgDuration: Seconds
113
+ }
114
+
115
+ export interface TrafficSource {
116
+ source: string
117
+ medium: string
118
+ sessions: Count
119
+ users: Count
120
+ }
121
+
122
+ export interface YouTubeChannelOverview {
123
+ subscriberCount: Count
124
+ viewCount: Count
125
+ videoCount: Count
126
+ }
127
+
128
+ export interface YouTubeVideoPerformance {
129
+ videoId: string
130
+ views: Count
131
+ watchMinutes: Minutes
132
+ avgViewDuration: Seconds
133
+ subscribersGained: Count
134
+ likes: Count
135
+ comments: Count
136
+ }
137
+
138
+ export interface YouTubeDaily {
139
+ date: string
140
+ views: Count
141
+ watchMinutes: Minutes
142
+ }
143
+
144
+ export interface YouTubeTrafficSource {
145
+ source: string
146
+ views: Count
147
+ watchMinutes: Minutes
148
+ }
149
+
150
+ export interface TrafficRevenueCorrelation {
151
+ traffic: TrafficDaily[]
152
+ revenue: RevenueDaily[]
153
+ }
154
+
155
+ export interface YouTubeRevenueCorrelation {
156
+ youtube: YouTubeDaily[]
157
+ traffic: TrafficDaily[]
158
+ revenue: RevenueDaily[]
159
+ }
160
+
161
+ export interface SurveySummary {
162
+ totalSurveys: Count
163
+ totalResponses: Count
164
+ uniqueRespondents: Count
165
+ avgResponsesPerSurvey: number
166
+ }
167
+
168
+ export interface SurveyListItem {
169
+ surveyId: string
170
+ surveyTitle: string
171
+ surveySlug: string
172
+ responses: Count
173
+ uniqueRespondents: Count
174
+ questionCount: Count
175
+ }
176
+
177
+ export interface SurveyResponsesDaily {
178
+ date: string
179
+ responses: Count
180
+ }
181
+
182
+ export interface SurveyQuestionBreakdown {
183
+ questionId: string
184
+ question: string
185
+ type: string | null
186
+ responses: Count
187
+ answerDistribution: { answer: string; count: Count }[]
188
+ }
189
+
190
+ export interface SurveyConversionByQuestion {
191
+ questionId: string
192
+ questionTitle: string | null
193
+ answer: string
194
+ respondents: Count
195
+ purchasers: Count
196
+ conversionRate: Percentage
197
+ revenue: USD
198
+ prePurchaseCount: Count
199
+ postPurchaseCount: Count
200
+ }
201
+
202
+ // ─── Newsletter (Kit) email campaign types ───────────────────────────────────
203
+
204
+ export interface EmailCampaignKitLink {
205
+ url: string
206
+ uniqueClicks: Count
207
+ clickToDeliveryRate: Percentage
208
+ clickToOpenRate: Percentage
209
+ shortlinkSlug?: string | null
210
+ }
211
+
212
+ export interface EmailCampaignShortlink {
213
+ slug: string
214
+ url: string
215
+ kitClicks: Count
216
+ clickToDeliveryRate?: Percentage
217
+ clickToOpenRate?: Percentage
218
+ shortlinkClicks: Count
219
+ signups: Count
220
+ purchases: Count
221
+ revenue: USD
222
+ }
223
+
224
+ export interface EmailCampaignFunnel {
225
+ broadcastId: number
226
+ subject: string
227
+ sentAt: string | null
228
+ recipients: Count
229
+ openRate: Percentage
230
+ emailsOpened?: Count
231
+ clickRate: Percentage
232
+ totalClicks: Count
233
+ showTotalClicks?: boolean
234
+ unsubscribes: Count
235
+ unsubscribeRate?: Percentage
236
+ progress?: Percentage
237
+ openTrackingDisabled?: boolean
238
+ clickTrackingDisabled?: boolean
239
+ kitLinks?: EmailCampaignKitLink[]
240
+ shortlinks: EmailCampaignShortlink[]
241
+ totalSignups: Count
242
+ totalPurchases: Count
243
+ totalRevenue: USD
244
+ clickToPurchaseRate: Percentage
245
+ }
246
+
247
+ export interface EmailRevenueOverview {
248
+ configured: boolean
249
+ totalBroadcasts: Count
250
+ totalRecipients: Count
251
+ totalRevenue: USD
252
+ campaigns: EmailCampaignFunnel[]
253
+ }
254
+
255
+ export interface SurveyResponseRow {
256
+ responseId: string
257
+ surveyId: string
258
+ surveyTitle: string
259
+ surveySlug: string
260
+ questionId: string
261
+ questionText: string
262
+ questionType: string | null
263
+ answer: string
264
+ userId: string | null
265
+ userEmail: string | null
266
+ emailListSubscriberId: string | null
267
+ createdAt: string
268
+ }
269
+
270
+ export interface SurveyRevenueCorrelation {
271
+ totalRespondents: Count
272
+ respondentsWhoPurchased: Count
273
+ overallConversionRate: Percentage
274
+ totalRevenueFromRespondents: USD
275
+ prePurchaseRespondents: Count
276
+ postPurchaseRespondents: Count
277
+ neverPurchasedRespondents: Count
278
+ baselineConversionRate: Percentage
279
+ byQuestion: SurveyConversionByQuestion[]
280
+ }
281
+
282
+ export interface SurfaceMap {
283
+ summary: RevenueSummary
284
+ 'revenue/daily': RevenueDaily[]
285
+ 'revenue/products': RevenueByProduct[]
286
+ 'revenue/countries': RevenueByCountry[]
287
+ 'purchases/recent': RecentPurchase[]
288
+ attribution: AttributionCount[]
289
+ 'attribution/shortlinks': ShortlinkPerformance[]
290
+ 'attribution/sources': RevenueBySource[]
291
+ 'attribution/funnel': ConversionFunnel
292
+ 'attribution/content': ContentCorrelation[]
293
+ 'attribution/coverage': AttributionCoverage
294
+ traffic: TrafficOverview
295
+ 'traffic/daily': TrafficDaily[]
296
+ 'traffic/pages': TopPage[]
297
+ 'traffic/sources': TrafficSource[]
298
+ youtube: YouTubeChannelOverview
299
+ 'youtube/videos': YouTubeVideoPerformance[]
300
+ 'youtube/daily': YouTubeDaily[]
301
+ 'youtube/sources': YouTubeTrafficSource[]
302
+ 'correlation/traffic-revenue': TrafficRevenueCorrelation
303
+ 'correlation/youtube-revenue': YouTubeRevenueCorrelation
304
+ surveys: SurveySummary
305
+ 'surveys/list': SurveyListItem[]
306
+ 'surveys/daily': SurveyResponsesDaily[]
307
+ 'surveys/questions': SurveyQuestionBreakdown[]
308
+ 'surveys/responses': SurveyResponseRow[]
309
+ 'correlation/survey-revenue': SurveyRevenueCorrelation
310
+ 'attribution/email-campaigns': EmailRevenueOverview
311
+ }
312
+
313
+ export type SurfaceName = keyof SurfaceMap
314
+
315
+ export interface QueryOptions {
316
+ range?: AnalyticsRange
317
+ limit?: number
318
+ }
319
+
320
+ export type QueryResult<S extends SurfaceName> =
321
+ | {
322
+ ok: true
323
+ surface: S
324
+ range: AnalyticsRange
325
+ data: SurfaceMap[S]
326
+ meta: { queryTimeMs: number; truncated: boolean }
327
+ }
328
+ | {
329
+ ok: false
330
+ surface: S
331
+ error: { message: string; code: string }
332
+ fix: string
333
+ }