@mostly-good-metrics/javascript 0.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 (54) hide show
  1. package/README.md +319 -0
  2. package/dist/cjs/client.js +416 -0
  3. package/dist/cjs/client.js.map +1 -0
  4. package/dist/cjs/index.js +65 -0
  5. package/dist/cjs/index.js.map +1 -0
  6. package/dist/cjs/logger.js +64 -0
  7. package/dist/cjs/logger.js.map +1 -0
  8. package/dist/cjs/network.js +192 -0
  9. package/dist/cjs/network.js.map +1 -0
  10. package/dist/cjs/storage.js +227 -0
  11. package/dist/cjs/storage.js.map +1 -0
  12. package/dist/cjs/types.js +70 -0
  13. package/dist/cjs/types.js.map +1 -0
  14. package/dist/cjs/utils.js +249 -0
  15. package/dist/cjs/utils.js.map +1 -0
  16. package/dist/esm/client.js +412 -0
  17. package/dist/esm/client.js.map +1 -0
  18. package/dist/esm/index.js +40 -0
  19. package/dist/esm/index.js.map +1 -0
  20. package/dist/esm/logger.js +55 -0
  21. package/dist/esm/logger.js.map +1 -0
  22. package/dist/esm/network.js +187 -0
  23. package/dist/esm/network.js.map +1 -0
  24. package/dist/esm/storage.js +221 -0
  25. package/dist/esm/storage.js.map +1 -0
  26. package/dist/esm/types.js +66 -0
  27. package/dist/esm/types.js.map +1 -0
  28. package/dist/esm/utils.js +236 -0
  29. package/dist/esm/utils.js.map +1 -0
  30. package/dist/types/client.d.ts +126 -0
  31. package/dist/types/client.d.ts.map +1 -0
  32. package/dist/types/index.d.ts +34 -0
  33. package/dist/types/index.d.ts.map +1 -0
  34. package/dist/types/logger.d.ts +37 -0
  35. package/dist/types/logger.d.ts.map +1 -0
  36. package/dist/types/network.d.ts +28 -0
  37. package/dist/types/network.d.ts.map +1 -0
  38. package/dist/types/storage.d.ts +76 -0
  39. package/dist/types/storage.d.ts.map +1 -0
  40. package/dist/types/types.d.ts +279 -0
  41. package/dist/types/types.d.ts.map +1 -0
  42. package/dist/types/utils.d.ts +48 -0
  43. package/dist/types/utils.d.ts.map +1 -0
  44. package/package.json +68 -0
  45. package/src/client.test.ts +346 -0
  46. package/src/client.ts +510 -0
  47. package/src/index.ts +79 -0
  48. package/src/logger.ts +63 -0
  49. package/src/network.ts +230 -0
  50. package/src/storage.test.ts +175 -0
  51. package/src/storage.ts +249 -0
  52. package/src/types.ts +347 -0
  53. package/src/utils.test.ts +239 -0
  54. package/src/utils.ts +315 -0
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # MostlyGoodMetrics JavaScript SDK
2
+
3
+ A lightweight JavaScript/TypeScript SDK for tracking analytics events with [MostlyGoodMetrics](https://mostlygoodmetrics.com).
4
+
5
+ ## Requirements
6
+
7
+ - Node.js 16+ (for build tools)
8
+ - Modern browser with ES2020 support, or Node.js runtime
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @mostly-good-metrics/javascript
14
+ ```
15
+
16
+ Or with yarn:
17
+
18
+ ```bash
19
+ yarn add @mostly-good-metrics/javascript
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### 1. Initialize the SDK
25
+
26
+ Initialize once at app startup:
27
+
28
+ ```typescript
29
+ import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';
30
+
31
+ MostlyGoodMetrics.configure({
32
+ apiKey: 'mgm_proj_your_api_key',
33
+ });
34
+ ```
35
+
36
+ ### 2. Track Events
37
+
38
+ ```typescript
39
+ // Simple event
40
+ MostlyGoodMetrics.track('button_clicked');
41
+
42
+ // Event with properties
43
+ MostlyGoodMetrics.track('purchase_completed', {
44
+ product_id: 'SKU123',
45
+ price: 29.99,
46
+ currency: 'USD',
47
+ });
48
+ ```
49
+
50
+ ### 3. Identify Users
51
+
52
+ ```typescript
53
+ // Set user identity
54
+ MostlyGoodMetrics.identify('user_123');
55
+
56
+ // Reset identity (e.g., on logout)
57
+ MostlyGoodMetrics.resetIdentity();
58
+ ```
59
+
60
+ That's it! Events are automatically batched and sent.
61
+
62
+ ## Configuration Options
63
+
64
+ For more control, pass additional configuration:
65
+
66
+ ```typescript
67
+ MostlyGoodMetrics.configure({
68
+ apiKey: 'mgm_proj_your_api_key',
69
+ baseURL: 'https://mostlygoodmetrics.com',
70
+ environment: 'production',
71
+ appVersion: '1.0.0',
72
+ maxBatchSize: 100,
73
+ flushInterval: 30,
74
+ maxStoredEvents: 10000,
75
+ enableDebugLogging: process.env.NODE_ENV === 'development',
76
+ trackAppLifecycleEvents: true,
77
+ });
78
+ ```
79
+
80
+ | Option | Default | Description |
81
+ |--------|---------|-------------|
82
+ | `apiKey` | - | **Required.** Your API key |
83
+ | `baseURL` | `https://mostlygoodmetrics.com` | API endpoint |
84
+ | `environment` | `"production"` | Environment name |
85
+ | `appVersion` | - | App version string (required for install/update tracking) |
86
+ | `maxBatchSize` | `100` | Events per batch (1-1000) |
87
+ | `flushInterval` | `30` | Auto-flush interval in seconds |
88
+ | `maxStoredEvents` | `10000` | Max cached events |
89
+ | `enableDebugLogging` | `false` | Enable console output |
90
+ | `trackAppLifecycleEvents` | `true` | Auto-track lifecycle events |
91
+ | `bundleId` | auto-detected | Custom bundle identifier |
92
+ | `storage` | auto-detected | Custom storage adapter |
93
+ | `networkClient` | fetch-based | Custom network client |
94
+
95
+ ## Automatic Events
96
+
97
+ When `trackAppLifecycleEvents` is enabled (default), the SDK automatically tracks:
98
+
99
+ | Event | When | Properties |
100
+ |-------|------|------------|
101
+ | `$app_installed` | First visit (localStorage) | `$version` |
102
+ | `$app_updated` | Version change detected | `$version`, `$previous_version` |
103
+ | `$app_opened` | Page load / tab visible | - |
104
+ | `$app_backgrounded` | Tab hidden / page unload | - |
105
+
106
+ > **Note:** Install and update detection require `appVersion` to be configured.
107
+
108
+ ## Automatic Properties
109
+
110
+ The SDK automatically includes these properties with every event:
111
+
112
+ | Property | Description |
113
+ |----------|-------------|
114
+ | `$device_type` | Device type (`desktop`, `phone`, `tablet`) |
115
+ | `$device_model` | Browser name and version |
116
+
117
+ Additionally, `osVersion` and `appVersion` (if configured) are included at the event level.
118
+
119
+ ## Event Naming
120
+
121
+ Event names must:
122
+ - Start with a letter (or `$` for system events)
123
+ - Contain only alphanumeric characters and underscores
124
+ - Be 255 characters or less
125
+
126
+ ```typescript
127
+ // Valid
128
+ MostlyGoodMetrics.track('button_clicked');
129
+ MostlyGoodMetrics.track('PurchaseCompleted');
130
+ MostlyGoodMetrics.track('step_1_completed');
131
+
132
+ // Invalid (will be ignored)
133
+ MostlyGoodMetrics.track('123_event'); // starts with number
134
+ MostlyGoodMetrics.track('event-name'); // contains hyphen
135
+ MostlyGoodMetrics.track('event name'); // contains space
136
+ ```
137
+
138
+ ## Properties
139
+
140
+ Events support various property types:
141
+
142
+ ```typescript
143
+ MostlyGoodMetrics.track('checkout', {
144
+ string_prop: 'value',
145
+ int_prop: 42,
146
+ double_prop: 3.14,
147
+ bool_prop: true,
148
+ null_prop: null,
149
+ list_prop: ['a', 'b', 'c'],
150
+ nested: {
151
+ key: 'value',
152
+ },
153
+ });
154
+ ```
155
+
156
+ **Limits:**
157
+ - String values: truncated to 1000 characters
158
+ - Nesting depth: max 3 levels
159
+ - Total properties size: max 10KB
160
+
161
+ ## Manual Flush
162
+
163
+ Events are automatically flushed periodically and when the page is hidden. You can also trigger a manual flush:
164
+
165
+ ```typescript
166
+ await MostlyGoodMetrics.flush();
167
+ ```
168
+
169
+ To check pending events:
170
+
171
+ ```typescript
172
+ const count = await MostlyGoodMetrics.getPendingEventCount();
173
+ console.log(`${count} events pending`);
174
+ ```
175
+
176
+ ## Automatic Behavior
177
+
178
+ The SDK automatically:
179
+
180
+ - **Persists events** to localStorage (with in-memory fallback)
181
+ - **Batches events** for efficient network usage
182
+ - **Flushes on interval** (default: every 30 seconds)
183
+ - **Flushes on visibility change** when the tab is hidden
184
+ - **Compresses payloads** using gzip for large batches (>1KB)
185
+ - **Retries on failure** for network errors (events are preserved)
186
+ - **Handles rate limiting** with exponential backoff
187
+ - **Persists user ID** across page loads
188
+ - **Generates session IDs** per page load
189
+
190
+ ## Debug Logging
191
+
192
+ Enable debug logging to see SDK activity:
193
+
194
+ ```typescript
195
+ MostlyGoodMetrics.configure({
196
+ apiKey: 'mgm_proj_your_api_key',
197
+ enableDebugLogging: true,
198
+ });
199
+ ```
200
+
201
+ Output example:
202
+ ```
203
+ [MostlyGoodMetrics] [INFO] MostlyGoodMetrics initialized with environment: production
204
+ [MostlyGoodMetrics] [DEBUG] Tracking event: button_clicked
205
+ [MostlyGoodMetrics] [DEBUG] Starting flush
206
+ [MostlyGoodMetrics] [DEBUG] Successfully sent 5 events
207
+ ```
208
+
209
+ ## Custom Storage
210
+
211
+ You can provide a custom storage adapter for environments where localStorage isn't available:
212
+
213
+ ```typescript
214
+ import { MostlyGoodMetrics, IEventStorage, InMemoryEventStorage } from '@mostly-good-metrics/javascript';
215
+
216
+ // Use in-memory storage
217
+ MostlyGoodMetrics.configure({
218
+ apiKey: 'mgm_proj_your_api_key',
219
+ storage: new InMemoryEventStorage(10000),
220
+ });
221
+
222
+ // Or implement your own
223
+ class MyCustomStorage implements IEventStorage {
224
+ async store(event: MGMEvent): Promise<void> { /* ... */ }
225
+ async fetchEvents(limit: number): Promise<MGMEvent[]> { /* ... */ }
226
+ async removeEvents(count: number): Promise<void> { /* ... */ }
227
+ async eventCount(): Promise<number> { /* ... */ }
228
+ async clear(): Promise<void> { /* ... */ }
229
+ }
230
+ ```
231
+
232
+ ## Framework Integration
233
+
234
+ ### React
235
+
236
+ ```typescript
237
+ // src/analytics.ts
238
+ import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';
239
+
240
+ export function initAnalytics() {
241
+ MostlyGoodMetrics.configure({
242
+ apiKey: process.env.REACT_APP_MGM_API_KEY!,
243
+ environment: process.env.NODE_ENV,
244
+ appVersion: process.env.REACT_APP_VERSION,
245
+ });
246
+ }
247
+
248
+ // src/index.tsx
249
+ import { initAnalytics } from './analytics';
250
+ initAnalytics();
251
+ ```
252
+
253
+ ### Next.js
254
+
255
+ ```typescript
256
+ // lib/analytics.ts
257
+ import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';
258
+
259
+ export function initAnalytics() {
260
+ if (typeof window !== 'undefined') {
261
+ MostlyGoodMetrics.configure({
262
+ apiKey: process.env.NEXT_PUBLIC_MGM_API_KEY!,
263
+ environment: process.env.NODE_ENV,
264
+ });
265
+ }
266
+ }
267
+
268
+ // app/layout.tsx or pages/_app.tsx
269
+ 'use client';
270
+ import { useEffect } from 'react';
271
+ import { initAnalytics } from '@/lib/analytics';
272
+
273
+ export default function RootLayout({ children }) {
274
+ useEffect(() => {
275
+ initAnalytics();
276
+ }, []);
277
+
278
+ return <html>...</html>;
279
+ }
280
+ ```
281
+
282
+ ### Vue
283
+
284
+ ```typescript
285
+ // src/plugins/analytics.ts
286
+ import { MostlyGoodMetrics } from '@mostly-good-metrics/javascript';
287
+
288
+ export default {
289
+ install() {
290
+ MostlyGoodMetrics.configure({
291
+ apiKey: import.meta.env.VITE_MGM_API_KEY,
292
+ environment: import.meta.env.MODE,
293
+ });
294
+ }
295
+ };
296
+
297
+ // src/main.ts
298
+ import analytics from './plugins/analytics';
299
+ app.use(analytics);
300
+ ```
301
+
302
+ ## TypeScript Support
303
+
304
+ Full TypeScript support with exported types:
305
+
306
+ ```typescript
307
+ import {
308
+ MostlyGoodMetrics,
309
+ MGMConfiguration,
310
+ MGMEvent,
311
+ EventProperties,
312
+ IEventStorage,
313
+ INetworkClient,
314
+ } from '@mostly-good-metrics/javascript';
315
+ ```
316
+
317
+ ## License
318
+
319
+ MIT