@drivemetadata-ai/sdk 0.1.1-beta.4 → 0.1.1

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.
@@ -33,12 +33,72 @@ const browserConfig = {
33
33
  };
34
34
  ```
35
35
 
36
+ Use camelCase config keys in npm integrations. The backend payload still sends the backend-required `metaData` shape, but SDK configuration should use `clientId`, `workspaceId`, `appId`, `apiHost`, `capturePageview`, `capturePageleave`, `schemaValidation`, and `beforeSend`.
37
+
36
38
  Node integrations use a server token stored only in backend environment variables:
37
39
 
38
40
  ```bash
39
41
  DMD_SERVER_TOKEN=server_write_key
40
42
  ```
41
43
 
44
+ ### Environment Variables
45
+
46
+ For React/Vite-style browser builds, expose only public browser values:
47
+
48
+ ```bash
49
+ VITE_DMD_CLIENT_ID=client_xxx
50
+ VITE_DMD_WORKSPACE_ID=workspace_xxx
51
+ VITE_DMD_APP_ID=app_xxx
52
+ VITE_DMD_TOKEN=public_token
53
+ ```
54
+
55
+ For Next.js browser integrations, use `NEXT_PUBLIC_` only for public browser values:
56
+
57
+ ```bash
58
+ NEXT_PUBLIC_DMD_CLIENT_ID=client_xxx
59
+ NEXT_PUBLIC_DMD_WORKSPACE_ID=workspace_xxx
60
+ NEXT_PUBLIC_DMD_APP_ID=app_xxx
61
+ NEXT_PUBLIC_DMD_TOKEN=public_token
62
+ ```
63
+
64
+ For Node/server integrations, do not use `NEXT_PUBLIC_`:
65
+
66
+ ```bash
67
+ DMD_SERVER_TOKEN=server_write_key
68
+ ```
69
+
70
+ ## Common Browser Config
71
+
72
+ ```ts
73
+ const config = {
74
+ clientId: 'client_xxx',
75
+ workspaceId: 'workspace_xxx',
76
+ appId: 'app_xxx',
77
+ token: 'public_token',
78
+ apiHost: 'https://sdk.drivemetadata.com/v2',
79
+ consent: { analytics: 'pending', advertising: 'denied' },
80
+ capturePageview: true,
81
+ capturePageleave: true,
82
+ schemaValidation: 'warn',
83
+ delivery: {
84
+ retryDelayMs: 1000,
85
+ maxRetryDelayMs: 30000,
86
+ maxQueueSize: 100,
87
+ useBeacon: true
88
+ }
89
+ };
90
+ ```
91
+
92
+ Recommended defaults:
93
+
94
+ | Option | Recommended | Notes |
95
+ |---|---|---|
96
+ | `consent.analytics` | `pending` | Grant after consent manager resolves |
97
+ | `capturePageview` | `true` | Sends automatic page views in browser runtimes |
98
+ | `capturePageleave` | `true` | Sends lifecycle/page leave events |
99
+ | `schemaValidation` | `warn` | Use `strict` in controlled integrations after testing |
100
+ | `delivery.useBeacon` | `true` | Helps lifecycle delivery during navigation |
101
+
42
102
  ## Consent First Setup
43
103
 
44
104
  Enterprise integrations should start with analytics consent as `pending` or `denied`, then grant it after the consent manager resolves.
@@ -92,6 +152,20 @@ await flush();
92
152
  console.log(getDmdHealth());
93
153
  ```
94
154
 
155
+ Browser API methods:
156
+
157
+ | Method | Use for |
158
+ |---|---|
159
+ | `track(event, properties, options)` | custom events |
160
+ | `page(name, properties, options)` | page views |
161
+ | `identify(userId, traits, options)` | known users |
162
+ | `group(groupId, traits, options)` | accounts/workspaces/organizations |
163
+ | `alias(previousId, userId, options)` | identity merge |
164
+ | `flush()` | force queued delivery |
165
+ | `reset()` | reset identity/session state |
166
+ | `setConsent(consent)` / `consent.update(consent)` | consent updates |
167
+ | `getDmdHealth()` | diagnostics |
168
+
95
169
  ## Backend Timestamp Fields
96
170
 
97
171
  Every collector request sends these timestamp fields inside `metaData`:
@@ -104,6 +178,42 @@ Every collector request sends these timestamp fields inside `metaData`:
104
178
 
105
179
  If a caller provides an invalid timestamp string, the SDK normalizes it to the current UTC time instead of sending the invalid value to the backend.
106
180
 
181
+ ## Default Page Context
182
+
183
+ Browser, React, Next.js, and Angular integrations automatically add browser page context to each collector payload.
184
+
185
+ ```json
186
+ {
187
+ "metaData": {
188
+ "page": {
189
+ "url": "https://example.com/products/sku-123?utm_source=paid",
190
+ "path": "/products/sku-123",
191
+ "search": "?utm_source=paid",
192
+ "title": "Product Detail",
193
+ "referrer": "https://google.com/search?q=%5BREDACTED%5D"
194
+ }
195
+ }
196
+ }
197
+ ```
198
+
199
+ The SDK reads this from `window.location`, `document.title`, and `document.referrer`. Query strings in `search` and `referrer` are redacted by default except common attribution parameters such as `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, and `utm_content`.
200
+
201
+ Node/server integrations do not automatically capture page context. Pass page details explicitly in server event properties if needed.
202
+
203
+ ## Default Identity, Session, Attribution
204
+
205
+ Browser, React, Next.js, and Angular integrations also add these fields by default:
206
+
207
+ | Field | Behavior |
208
+ |---|---|
209
+ | `requestId` | generated UUID for each event |
210
+ | `anonymousId` | persisted anonymous browser visitor ID |
211
+ | `sessionId` | persisted browser session ID with idle timeout |
212
+ | `attributionData` | stored click IDs and `_fbc`/`_fbp` when available |
213
+ | `utmParameter` | stored UTM values when available |
214
+
215
+ The SDK stores anonymous/session/attribution state using the configured browser persistence mode and falls back safely when browser storage is blocked.
216
+
107
217
  ## React Integration
108
218
 
109
219
  Wrap the app once:
@@ -128,6 +238,18 @@ export function App() {
128
238
  }
129
239
  ```
130
240
 
241
+ For Vite React apps, the provider config commonly comes from `import.meta.env`:
242
+
243
+ ```tsx
244
+ const config = {
245
+ clientId: import.meta.env.VITE_DMD_CLIENT_ID,
246
+ workspaceId: import.meta.env.VITE_DMD_WORKSPACE_ID,
247
+ appId: import.meta.env.VITE_DMD_APP_ID,
248
+ token: import.meta.env.VITE_DMD_TOKEN,
249
+ consent: { analytics: 'pending' as const, advertising: 'denied' as const }
250
+ };
251
+ ```
252
+
131
253
  Track from components:
132
254
 
133
255
  ```tsx
@@ -140,7 +262,7 @@ export function CheckoutButton() {
140
262
  const consent = useDmdConsent();
141
263
 
142
264
  async function onClick() {
143
- consent.update({ analytics: 'granted' });
265
+ consent({ analytics: 'granted' });
144
266
  identify('user_123', { plan: 'enterprise' });
145
267
  track('Checkout Started', { source: 'cart' });
146
268
  await flush();
@@ -159,13 +281,18 @@ Create a client provider:
159
281
 
160
282
  import { DmdProvider, useDmdAppRouterPageTracking } from '@drivemetadata-ai/sdk/next';
161
283
  import { usePathname, useSearchParams } from 'next/navigation';
284
+ import type { ReactNode } from 'react';
162
285
 
163
- export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
286
+ function RouteTracking() {
164
287
  const pathname = usePathname();
165
288
  const searchParams = useSearchParams();
166
289
 
167
290
  useDmdAppRouterPageTracking(pathname, searchParams.toString());
168
291
 
292
+ return null;
293
+ }
294
+
295
+ export function AnalyticsProvider({ children }: { children: ReactNode }) {
169
296
  return (
170
297
  <DmdProvider
171
298
  config={{
@@ -176,6 +303,7 @@ export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
176
303
  consent: { analytics: 'pending', advertising: 'denied' }
177
304
  }}
178
305
  >
306
+ <RouteTracking />
179
307
  {children}
180
308
  </DmdProvider>
181
309
  );
@@ -186,8 +314,9 @@ Use it from `app/layout.tsx`:
186
314
 
187
315
  ```tsx
188
316
  import { AnalyticsProvider } from './AnalyticsProvider';
317
+ import type { ReactNode } from 'react';
189
318
 
190
- export default function RootLayout({ children }: { children: React.ReactNode }) {
319
+ export default function RootLayout({ children }: { children: ReactNode }) {
191
320
  return (
192
321
  <html lang="en">
193
322
  <body>
@@ -205,6 +334,14 @@ import type { AppProps } from 'next/app';
205
334
  import { useRouter } from 'next/router';
206
335
  import { DmdProvider, useDmdPagesRouterPageTracking } from '@drivemetadata-ai/sdk/next';
207
336
 
337
+ const config = {
338
+ clientId: process.env.NEXT_PUBLIC_DMD_CLIENT_ID!,
339
+ workspaceId: process.env.NEXT_PUBLIC_DMD_WORKSPACE_ID!,
340
+ appId: process.env.NEXT_PUBLIC_DMD_APP_ID!,
341
+ token: process.env.NEXT_PUBLIC_DMD_TOKEN!,
342
+ consent: { analytics: 'pending' as const, advertising: 'denied' as const }
343
+ };
344
+
208
345
  function PageTracking() {
209
346
  const router = useRouter();
210
347
  useDmdPagesRouterPageTracking(router);
@@ -242,10 +379,24 @@ export const appConfig: ApplicationConfig = {
242
379
  };
243
380
  ```
244
381
 
382
+ For Angular environment files, keep only the public browser token in frontend config:
383
+
384
+ ```ts
385
+ export const environment = {
386
+ dmd: {
387
+ clientId: 'client_xxx',
388
+ workspaceId: 'workspace_xxx',
389
+ appId: 'app_xxx',
390
+ token: 'public_token'
391
+ }
392
+ };
393
+ ```
394
+
245
395
  Initialize and track:
246
396
 
247
397
  ```ts
248
- import { Component, OnInit } from '@angular/core';
398
+ import { isPlatformBrowser } from '@angular/common';
399
+ import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core';
249
400
  import { DmdAnalyticsService } from '@drivemetadata-ai/sdk/angular';
250
401
 
251
402
  @Component({
@@ -253,10 +404,16 @@ import { DmdAnalyticsService } from '@drivemetadata-ai/sdk/angular';
253
404
  template: '<router-outlet />'
254
405
  })
255
406
  export class AppComponent implements OnInit {
256
- constructor(private readonly dmd: DmdAnalyticsService) {}
407
+ constructor(
408
+ private readonly dmd: DmdAnalyticsService,
409
+ @Inject(PLATFORM_ID) private readonly platformId: object
410
+ ) {}
257
411
 
258
412
  ngOnInit() {
413
+ if (!isPlatformBrowser(this.platformId)) return;
414
+
259
415
  this.dmd.init();
416
+ this.dmd.setConsent({ analytics: 'granted' });
260
417
  this.dmd.track('App Loaded');
261
418
  }
262
419
  }
@@ -296,6 +453,21 @@ await dmd.track({
296
453
 
297
454
  Use `messageId` for a unique event ID and `idempotencyKey` for business events that may retry, such as orders, invoices, subscriptions, and webhooks.
298
455
 
456
+ Server-side page context is explicit:
457
+
458
+ ```ts
459
+ await dmd.page({
460
+ userId: 'user_123',
461
+ properties: {
462
+ page: {
463
+ url: 'https://example.com/orders/123',
464
+ path: '/orders/123',
465
+ title: 'Order Detail'
466
+ }
467
+ }
468
+ });
469
+ ```
470
+
299
471
  ## Diagnostics
300
472
 
301
473
  Use health diagnostics when events do not appear:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drivemetadata-ai/sdk",
3
- "version": "0.1.1-beta.4",
3
+ "version": "0.1.1",
4
4
  "description": "DriveMetaData JavaScript and TypeScript SDK.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -59,6 +59,7 @@
59
59
  "test": "vitest run",
60
60
  "test:package": "npm run build && vitest run tests/package/package-contents.test.ts tests/package/package-install-smoke.test.ts",
61
61
  "pack:check": "npm run build && npm pack --dry-run",
62
+ "release:version": "node scripts/release-version.mjs",
62
63
  "release:check": "npm run ci && npm_config_cache=/tmp/npm-cache npm run pack:check",
63
64
  "ci": "npm run typecheck && npm run test && npm run build && npm run test:package",
64
65
  "ci:phase1": "npm run typecheck && npm run test && npm run build"