@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
@@ -0,0 +1,303 @@
1
+ declare const __brand: unique symbol;
2
+ type Brand<T, B extends string> = T & {
3
+ readonly [__brand]: B;
4
+ };
5
+ type USD = Brand<number, 'USD'>;
6
+ type Count = Brand<number, 'Count'>;
7
+ type Percentage = Brand<number, 'Percentage'>;
8
+ type Minutes = Brand<number, 'Minutes'>;
9
+ type Seconds = Brand<number, 'Seconds'>;
10
+ type AnalyticsRange = '24h' | '7d' | '30d' | '90d' | 'all';
11
+ interface RevenueSummary {
12
+ totalRevenue: USD;
13
+ purchaseCount: Count;
14
+ avgOrderValue: USD;
15
+ }
16
+ interface RevenueDaily {
17
+ date: string;
18
+ revenue: USD;
19
+ count: Count;
20
+ }
21
+ interface RevenueByProduct {
22
+ productId: string;
23
+ productName: string;
24
+ revenue: USD;
25
+ count: Count;
26
+ }
27
+ interface RevenueByCountry {
28
+ country: string;
29
+ revenue: USD;
30
+ count: Count;
31
+ }
32
+ interface RecentPurchase {
33
+ id: string;
34
+ createdAt: Date;
35
+ totalAmount: USD;
36
+ productName: string;
37
+ productId: string;
38
+ country: string | null;
39
+ couponId: string | null;
40
+ userName: string | null;
41
+ userEmail: string | null;
42
+ }
43
+ interface AttributionCount {
44
+ type: string;
45
+ count: Count;
46
+ }
47
+ interface ShortlinkPerformance {
48
+ shortlinkId: string;
49
+ slug: string;
50
+ url: string;
51
+ clicks: Count;
52
+ }
53
+ interface RevenueBySource {
54
+ source: string;
55
+ medium: string;
56
+ campaign: string | null;
57
+ revenue: USD;
58
+ count: Count;
59
+ }
60
+ interface ConversionFunnel {
61
+ totalSignups: Count;
62
+ totalPurchases: Count;
63
+ attributedPurchases: Count;
64
+ unattributedPurchases: Count;
65
+ conversionRate: Percentage;
66
+ attributionCoverage: Percentage;
67
+ }
68
+ interface ContentCorrelation {
69
+ resourceId: string;
70
+ purchaserCount: Count;
71
+ }
72
+ interface AttributionCoverage {
73
+ totalRevenue: USD;
74
+ attributedRevenue: USD;
75
+ unattributedRevenue: USD;
76
+ attributionRate: Percentage;
77
+ totalPurchases: Count;
78
+ }
79
+ interface TrafficOverview {
80
+ sessions: Count;
81
+ totalUsers: Count;
82
+ newUsers: Count;
83
+ pageviews: Count;
84
+ avgSessionDuration: Seconds;
85
+ bounceRate: Percentage;
86
+ }
87
+ interface TrafficDaily {
88
+ date: string;
89
+ sessions: Count;
90
+ users: Count;
91
+ pageviews: Count;
92
+ }
93
+ interface TopPage {
94
+ path: string;
95
+ pageviews: Count;
96
+ users: Count;
97
+ avgDuration: Seconds;
98
+ }
99
+ interface TrafficSource {
100
+ source: string;
101
+ medium: string;
102
+ sessions: Count;
103
+ users: Count;
104
+ }
105
+ interface YouTubeChannelOverview {
106
+ subscriberCount: Count;
107
+ viewCount: Count;
108
+ videoCount: Count;
109
+ }
110
+ interface YouTubeVideoPerformance {
111
+ videoId: string;
112
+ views: Count;
113
+ watchMinutes: Minutes;
114
+ avgViewDuration: Seconds;
115
+ subscribersGained: Count;
116
+ likes: Count;
117
+ comments: Count;
118
+ }
119
+ interface YouTubeDaily {
120
+ date: string;
121
+ views: Count;
122
+ watchMinutes: Minutes;
123
+ }
124
+ interface YouTubeTrafficSource {
125
+ source: string;
126
+ views: Count;
127
+ watchMinutes: Minutes;
128
+ }
129
+ interface TrafficRevenueCorrelation {
130
+ traffic: TrafficDaily[];
131
+ revenue: RevenueDaily[];
132
+ }
133
+ interface YouTubeRevenueCorrelation {
134
+ youtube: YouTubeDaily[];
135
+ traffic: TrafficDaily[];
136
+ revenue: RevenueDaily[];
137
+ }
138
+ interface SurveySummary {
139
+ totalSurveys: Count;
140
+ totalResponses: Count;
141
+ uniqueRespondents: Count;
142
+ avgResponsesPerSurvey: number;
143
+ }
144
+ interface SurveyListItem {
145
+ surveyId: string;
146
+ surveyTitle: string;
147
+ surveySlug: string;
148
+ responses: Count;
149
+ uniqueRespondents: Count;
150
+ questionCount: Count;
151
+ }
152
+ interface SurveyResponsesDaily {
153
+ date: string;
154
+ responses: Count;
155
+ }
156
+ interface SurveyQuestionBreakdown {
157
+ questionId: string;
158
+ question: string;
159
+ type: string | null;
160
+ responses: Count;
161
+ answerDistribution: {
162
+ answer: string;
163
+ count: Count;
164
+ }[];
165
+ }
166
+ interface SurveyConversionByQuestion {
167
+ questionId: string;
168
+ questionTitle: string | null;
169
+ answer: string;
170
+ respondents: Count;
171
+ purchasers: Count;
172
+ conversionRate: Percentage;
173
+ revenue: USD;
174
+ prePurchaseCount: Count;
175
+ postPurchaseCount: Count;
176
+ }
177
+ interface EmailCampaignKitLink {
178
+ url: string;
179
+ uniqueClicks: Count;
180
+ clickToDeliveryRate: Percentage;
181
+ clickToOpenRate: Percentage;
182
+ shortlinkSlug?: string | null;
183
+ }
184
+ interface EmailCampaignShortlink {
185
+ slug: string;
186
+ url: string;
187
+ kitClicks: Count;
188
+ clickToDeliveryRate?: Percentage;
189
+ clickToOpenRate?: Percentage;
190
+ shortlinkClicks: Count;
191
+ signups: Count;
192
+ purchases: Count;
193
+ revenue: USD;
194
+ }
195
+ interface EmailCampaignFunnel {
196
+ broadcastId: number;
197
+ subject: string;
198
+ sentAt: string | null;
199
+ recipients: Count;
200
+ openRate: Percentage;
201
+ emailsOpened?: Count;
202
+ clickRate: Percentage;
203
+ totalClicks: Count;
204
+ showTotalClicks?: boolean;
205
+ unsubscribes: Count;
206
+ unsubscribeRate?: Percentage;
207
+ progress?: Percentage;
208
+ openTrackingDisabled?: boolean;
209
+ clickTrackingDisabled?: boolean;
210
+ kitLinks?: EmailCampaignKitLink[];
211
+ shortlinks: EmailCampaignShortlink[];
212
+ totalSignups: Count;
213
+ totalPurchases: Count;
214
+ totalRevenue: USD;
215
+ clickToPurchaseRate: Percentage;
216
+ }
217
+ interface EmailRevenueOverview {
218
+ configured: boolean;
219
+ totalBroadcasts: Count;
220
+ totalRecipients: Count;
221
+ totalRevenue: USD;
222
+ campaigns: EmailCampaignFunnel[];
223
+ }
224
+ interface SurveyResponseRow {
225
+ responseId: string;
226
+ surveyId: string;
227
+ surveyTitle: string;
228
+ surveySlug: string;
229
+ questionId: string;
230
+ questionText: string;
231
+ questionType: string | null;
232
+ answer: string;
233
+ userId: string | null;
234
+ userEmail: string | null;
235
+ emailListSubscriberId: string | null;
236
+ createdAt: string;
237
+ }
238
+ interface SurveyRevenueCorrelation {
239
+ totalRespondents: Count;
240
+ respondentsWhoPurchased: Count;
241
+ overallConversionRate: Percentage;
242
+ totalRevenueFromRespondents: USD;
243
+ prePurchaseRespondents: Count;
244
+ postPurchaseRespondents: Count;
245
+ neverPurchasedRespondents: Count;
246
+ baselineConversionRate: Percentage;
247
+ byQuestion: SurveyConversionByQuestion[];
248
+ }
249
+ interface SurfaceMap {
250
+ summary: RevenueSummary;
251
+ 'revenue/daily': RevenueDaily[];
252
+ 'revenue/products': RevenueByProduct[];
253
+ 'revenue/countries': RevenueByCountry[];
254
+ 'purchases/recent': RecentPurchase[];
255
+ attribution: AttributionCount[];
256
+ 'attribution/shortlinks': ShortlinkPerformance[];
257
+ 'attribution/sources': RevenueBySource[];
258
+ 'attribution/funnel': ConversionFunnel;
259
+ 'attribution/content': ContentCorrelation[];
260
+ 'attribution/coverage': AttributionCoverage;
261
+ traffic: TrafficOverview;
262
+ 'traffic/daily': TrafficDaily[];
263
+ 'traffic/pages': TopPage[];
264
+ 'traffic/sources': TrafficSource[];
265
+ youtube: YouTubeChannelOverview;
266
+ 'youtube/videos': YouTubeVideoPerformance[];
267
+ 'youtube/daily': YouTubeDaily[];
268
+ 'youtube/sources': YouTubeTrafficSource[];
269
+ 'correlation/traffic-revenue': TrafficRevenueCorrelation;
270
+ 'correlation/youtube-revenue': YouTubeRevenueCorrelation;
271
+ surveys: SurveySummary;
272
+ 'surveys/list': SurveyListItem[];
273
+ 'surveys/daily': SurveyResponsesDaily[];
274
+ 'surveys/questions': SurveyQuestionBreakdown[];
275
+ 'surveys/responses': SurveyResponseRow[];
276
+ 'correlation/survey-revenue': SurveyRevenueCorrelation;
277
+ 'attribution/email-campaigns': EmailRevenueOverview;
278
+ }
279
+ type SurfaceName = keyof SurfaceMap;
280
+ interface QueryOptions {
281
+ range?: AnalyticsRange;
282
+ limit?: number;
283
+ }
284
+ type QueryResult<S extends SurfaceName> = {
285
+ ok: true;
286
+ surface: S;
287
+ range: AnalyticsRange;
288
+ data: SurfaceMap[S];
289
+ meta: {
290
+ queryTimeMs: number;
291
+ truncated: boolean;
292
+ };
293
+ } | {
294
+ ok: false;
295
+ surface: S;
296
+ error: {
297
+ message: string;
298
+ code: string;
299
+ };
300
+ fix: string;
301
+ };
302
+
303
+ export type { AnalyticsRange, AttributionCount, AttributionCoverage, ContentCorrelation, ConversionFunnel, Count, EmailCampaignFunnel, EmailCampaignKitLink, EmailCampaignShortlink, EmailRevenueOverview, Minutes, Percentage, QueryOptions, QueryResult, RecentPurchase, RevenueByCountry, RevenueByProduct, RevenueBySource, RevenueDaily, RevenueSummary, Seconds, ShortlinkPerformance, SurfaceMap, SurfaceName, SurveyConversionByQuestion, SurveyListItem, SurveyQuestionBreakdown, SurveyResponseRow, SurveyResponsesDaily, SurveyRevenueCorrelation, SurveySummary, TopPage, TrafficDaily, TrafficOverview, TrafficRevenueCorrelation, TrafficSource, USD, YouTubeChannelOverview, YouTubeDaily, YouTubeRevenueCorrelation, YouTubeTrafficSource, YouTubeVideoPerformance };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "@coursebuilder/analytics",
3
+ "version": "1.1.0",
4
+ "files": [
5
+ "dist",
6
+ "src"
7
+ ],
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./types": {
16
+ "types": "./dist/types.d.ts",
17
+ "import": "./dist/types.js",
18
+ "default": "./dist/types.js"
19
+ },
20
+ "./engine": {
21
+ "types": "./dist/engine.d.ts",
22
+ "import": "./dist/engine.js",
23
+ "default": "./dist/engine.js"
24
+ },
25
+ "./catalog": {
26
+ "types": "./dist/catalog.d.ts",
27
+ "import": "./dist/catalog.js",
28
+ "default": "./dist/catalog.js"
29
+ },
30
+ "./providers": {
31
+ "types": "./dist/providers/index.d.ts",
32
+ "import": "./dist/providers/index.js",
33
+ "default": "./dist/providers/index.js"
34
+ },
35
+ "./providers/database": {
36
+ "types": "./dist/providers/database.d.ts",
37
+ "import": "./dist/providers/database.js",
38
+ "default": "./dist/providers/database.js"
39
+ },
40
+ "./providers/ga4": {
41
+ "types": "./dist/providers/ga4.d.ts",
42
+ "import": "./dist/providers/ga4.js",
43
+ "default": "./dist/providers/ga4.js"
44
+ },
45
+ "./providers/derived": {
46
+ "types": "./dist/providers/derived.d.ts",
47
+ "import": "./dist/providers/derived.js",
48
+ "default": "./dist/providers/derived.js"
49
+ },
50
+ "./providers/mux": {
51
+ "types": "./dist/providers/mux.d.ts",
52
+ "import": "./dist/providers/mux.js",
53
+ "default": "./dist/providers/mux.js"
54
+ },
55
+ "./providers/survey": {
56
+ "types": "./dist/providers/survey.d.ts",
57
+ "import": "./dist/providers/survey.js",
58
+ "default": "./dist/providers/survey.js"
59
+ },
60
+ "./components": {
61
+ "types": "./dist/components/index.d.ts",
62
+ "import": "./dist/components/index.js",
63
+ "default": "./dist/components/index.js"
64
+ },
65
+ "./api": {
66
+ "types": "./dist/api/index.d.ts",
67
+ "import": "./dist/api/index.js",
68
+ "default": "./dist/api/index.js"
69
+ }
70
+ },
71
+ "dependencies": {
72
+ "@google-analytics/data": "^4.0.0",
73
+ "zod": "^3.22.4"
74
+ },
75
+ "devDependencies": {
76
+ "@types/react": "19.2.7",
77
+ "drizzle-orm": "^0.30.0",
78
+ "lucide-react": "^0.344.0",
79
+ "next": "16.0.10",
80
+ "nuqs": "^2.0.0",
81
+ "react": "19.2.3",
82
+ "recharts": "^2.12.0",
83
+ "tsup": "8.0.2",
84
+ "typescript": "5.4.5",
85
+ "@coursebuilder/ui": "2.0.10"
86
+ },
87
+ "peerDependencies": {
88
+ "@coursebuilder/ui": "*",
89
+ "drizzle-orm": "*",
90
+ "lucide-react": "*",
91
+ "next": "*",
92
+ "nuqs": "*",
93
+ "react": ">=18",
94
+ "recharts": "*"
95
+ },
96
+ "scripts": {
97
+ "build": "tsup",
98
+ "dev": "tsup --watch",
99
+ "typecheck": "tsc --noEmit"
100
+ }
101
+ }