@datalyr/web 1.0.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.
- package/LICENSE +21 -0
- package/README.md +727 -0
- package/dist/attribution.d.ts +68 -0
- package/dist/attribution.d.ts.map +1 -0
- package/dist/container.d.ts +140 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/datalyr.cjs.js +2835 -0
- package/dist/datalyr.cjs.js.map +1 -0
- package/dist/datalyr.esm.js +2833 -0
- package/dist/datalyr.esm.js.map +1 -0
- package/dist/datalyr.esm.min.js +2 -0
- package/dist/datalyr.esm.min.js.map +1 -0
- package/dist/datalyr.js +2838 -0
- package/dist/datalyr.js.map +1 -0
- package/dist/datalyr.min.js +2 -0
- package/dist/datalyr.min.js.map +1 -0
- package/dist/fingerprint.d.ts +79 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/identity.d.ts +62 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.d.ts +175 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/queue.d.ts +99 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/session.d.ts +87 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/storage.d.ts +44 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
# @datalyr/web
|
|
2
|
+
|
|
3
|
+
The official Datalyr Web SDK for browser-based analytics. Track user behavior, measure conversions, and understand your customer journey with enterprise-grade analytics.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@datalyr/web)
|
|
6
|
+
[](https://bundlephobia.com/package/@datalyr/web)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://github.com/datalyr/web/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 🚀 **Zero Configuration** - Start tracking with just your workspace ID
|
|
13
|
+
- 📦 **Lightweight** - ~15KB minified + gzipped with zero dependencies
|
|
14
|
+
- 🔒 **Privacy First** - GDPR compliant with built-in consent management
|
|
15
|
+
- 🎯 **Smart Batching** - Optimized network usage with intelligent event queuing
|
|
16
|
+
- 📱 **Cross-Platform** - Works on all modern browsers including mobile
|
|
17
|
+
- 🔄 **Offline Support** - Events are queued and sent when connection restored
|
|
18
|
+
- 🏷️ **Attribution Tracking** - Automatic UTM and click ID capture
|
|
19
|
+
- 🔍 **Session Management** - Automatic session tracking with configurable timeout
|
|
20
|
+
- 🎨 **TypeScript Support** - Full type definitions included
|
|
21
|
+
- 🔌 **Extensible** - Plugin system for custom functionality
|
|
22
|
+
- 📦 **Container Scripts** - Securely manage third-party pixels and tracking scripts
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @datalyr/web
|
|
28
|
+
# or
|
|
29
|
+
yarn add @datalyr/web
|
|
30
|
+
# or
|
|
31
|
+
pnpm add @datalyr/web
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import { Datalyr } from '@datalyr/web';
|
|
38
|
+
|
|
39
|
+
// Initialize with your workspace ID
|
|
40
|
+
const datalyr = new Datalyr({
|
|
41
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Initialize the SDK
|
|
45
|
+
await datalyr.init();
|
|
46
|
+
|
|
47
|
+
// Track an event
|
|
48
|
+
datalyr.track('Button Clicked', {
|
|
49
|
+
button_name: 'Sign Up',
|
|
50
|
+
location: 'Header'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Identify a user
|
|
54
|
+
datalyr.identify('user_123', {
|
|
55
|
+
email: 'user@example.com',
|
|
56
|
+
name: 'John Doe',
|
|
57
|
+
plan: 'premium'
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Core Methods
|
|
62
|
+
|
|
63
|
+
### Initialization
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
const datalyr = new Datalyr({
|
|
67
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
68
|
+
|
|
69
|
+
// Optional configuration
|
|
70
|
+
// endpoint: 'https://custom.endpoint.com', // Optional: Custom endpoint
|
|
71
|
+
debug: false, // Enable debug logging
|
|
72
|
+
// batchSize: 10, // Optional: Events per batch
|
|
73
|
+
// flushInterval: 5000, // Optional: Flush interval (ms)
|
|
74
|
+
sessionTimeout: 1800000, // 30 minutes
|
|
75
|
+
privacyMode: 'standard', // 'standard' or 'strict'
|
|
76
|
+
respectDoNotTrack: false, // Honor browser DNT
|
|
77
|
+
respectGlobalPrivacyControl: true, // Honor GPC
|
|
78
|
+
cookieDomain: 'auto', // Auto-detect for subdomains
|
|
79
|
+
trackSPA: true, // Track SPA route changes
|
|
80
|
+
trackPageViews: true // Track initial page view
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await datalyr.init();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Track Events
|
|
87
|
+
|
|
88
|
+
Track custom events with properties:
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
// Simple event
|
|
92
|
+
datalyr.track('Video Played');
|
|
93
|
+
|
|
94
|
+
// Event with properties
|
|
95
|
+
datalyr.track('Product Viewed', {
|
|
96
|
+
product_id: 'SKU-123',
|
|
97
|
+
product_name: 'Premium Widget',
|
|
98
|
+
category: 'Electronics',
|
|
99
|
+
price: 99.99,
|
|
100
|
+
currency: 'USD'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// E-commerce events
|
|
104
|
+
datalyr.track('Purchase', {
|
|
105
|
+
order_id: 'ORD-456',
|
|
106
|
+
total: 299.99,
|
|
107
|
+
currency: 'USD',
|
|
108
|
+
items: [
|
|
109
|
+
{ product_id: 'SKU-123', quantity: 2, price: 99.99 },
|
|
110
|
+
{ product_id: 'SKU-456', quantity: 1, price: 100.01 }
|
|
111
|
+
]
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Identify Users
|
|
116
|
+
|
|
117
|
+
Associate events with users:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
// Identify with user ID only
|
|
121
|
+
datalyr.identify('user_123');
|
|
122
|
+
|
|
123
|
+
// Identify with traits
|
|
124
|
+
datalyr.identify('user_123', {
|
|
125
|
+
email: 'user@example.com',
|
|
126
|
+
name: 'John Doe',
|
|
127
|
+
firstName: 'John',
|
|
128
|
+
lastName: 'Doe',
|
|
129
|
+
phone: '+1234567890',
|
|
130
|
+
plan: 'premium',
|
|
131
|
+
createdAt: '2024-01-01'
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Update user traits without changing ID
|
|
135
|
+
datalyr.identify(null, {
|
|
136
|
+
plan: 'enterprise',
|
|
137
|
+
company: 'Acme Corp'
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Page Tracking
|
|
142
|
+
|
|
143
|
+
Track page views:
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// Track current page
|
|
147
|
+
datalyr.page();
|
|
148
|
+
|
|
149
|
+
// Track with custom properties
|
|
150
|
+
datalyr.page({
|
|
151
|
+
title: 'Pricing Page',
|
|
152
|
+
category: 'Marketing',
|
|
153
|
+
author: 'Marketing Team'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Track with page name
|
|
157
|
+
datalyr.page('Pricing', {
|
|
158
|
+
plan: 'premium',
|
|
159
|
+
variant: 'A'
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Managing Identity
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
// Get current user IDs
|
|
167
|
+
const anonymousId = datalyr.getAnonymousId();
|
|
168
|
+
const userId = datalyr.getUserId();
|
|
169
|
+
const distinctId = datalyr.getDistinctId();
|
|
170
|
+
|
|
171
|
+
// Reset identity (for logout)
|
|
172
|
+
datalyr.reset();
|
|
173
|
+
|
|
174
|
+
// Create alias (link anonymous to identified user)
|
|
175
|
+
datalyr.alias('user_123');
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### User Consent
|
|
179
|
+
|
|
180
|
+
Manage user privacy preferences:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
// Opt user out of tracking
|
|
184
|
+
datalyr.optOut();
|
|
185
|
+
|
|
186
|
+
// Opt user back in
|
|
187
|
+
datalyr.optIn();
|
|
188
|
+
|
|
189
|
+
// Check opt-out status
|
|
190
|
+
const isOptedOut = datalyr.isOptedOut();
|
|
191
|
+
|
|
192
|
+
// Set consent preferences
|
|
193
|
+
datalyr.setConsent({
|
|
194
|
+
analytics: true,
|
|
195
|
+
marketing: false,
|
|
196
|
+
preferences: true,
|
|
197
|
+
sale: false // CCPA "Do Not Sell"
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Session Management
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
// Get current session ID
|
|
205
|
+
const sessionId = datalyr.getSessionId();
|
|
206
|
+
|
|
207
|
+
// Manually end session
|
|
208
|
+
datalyr.endSession();
|
|
209
|
+
|
|
210
|
+
// Start new session
|
|
211
|
+
datalyr.startNewSession();
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Advanced Features
|
|
215
|
+
|
|
216
|
+
### Event Priority
|
|
217
|
+
|
|
218
|
+
Important events like purchases are automatically prioritized for faster delivery:
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Important conversion events
|
|
222
|
+
datalyr.track('Purchase', { value: 99.99 });
|
|
223
|
+
datalyr.track('Signup', { plan: 'premium' });
|
|
224
|
+
datalyr.track('Subscribe', { plan: 'annual' });
|
|
225
|
+
|
|
226
|
+
// E-commerce events
|
|
227
|
+
datalyr.track('Add to Cart', { product_id: 'SKU-123' });
|
|
228
|
+
datalyr.track('Begin Checkout', { cart_value: 199.99 });
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Attribution Tracking
|
|
232
|
+
|
|
233
|
+
The SDK automatically captures:
|
|
234
|
+
- UTM parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content)
|
|
235
|
+
- Click IDs (gclid, fbclid, ttclid, msclkid, twclid, li_fat_id)
|
|
236
|
+
- Referrer information
|
|
237
|
+
- Landing page
|
|
238
|
+
- Customer journey touchpoints
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
// Attribution data is automatically added to events
|
|
242
|
+
datalyr.track('Signup');
|
|
243
|
+
// Includes: utm_source, utm_medium, first_touch_source, last_touch_source, etc.
|
|
244
|
+
|
|
245
|
+
// Track custom URL parameters
|
|
246
|
+
const datalyr = new Datalyr({
|
|
247
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
248
|
+
trackedParams: ['ref', 'affiliate_id', 'promo_code']
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### SPA Support
|
|
253
|
+
|
|
254
|
+
For single-page applications:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
const datalyr = new Datalyr({
|
|
258
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
259
|
+
trackSPA: true // Auto-track route changes (default: true)
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Manual route tracking
|
|
263
|
+
datalyr.page('Product Details', {
|
|
264
|
+
product_id: 'SKU-123'
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Privacy Modes
|
|
269
|
+
|
|
270
|
+
Control data collection:
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
// Standard mode (default) - balanced privacy
|
|
274
|
+
const datalyr = new Datalyr({
|
|
275
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
276
|
+
privacyMode: 'standard'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Strict mode - minimal data collection
|
|
280
|
+
const datalyr = new Datalyr({
|
|
281
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
282
|
+
privacyMode: 'strict'
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Offline Support
|
|
287
|
+
|
|
288
|
+
Events are automatically saved when offline and sent when connection is restored:
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
// Events work seamlessly offline
|
|
292
|
+
datalyr.track('Button Clicked'); // Automatically queued if offline
|
|
293
|
+
|
|
294
|
+
// Manually flush pending events
|
|
295
|
+
await datalyr.flush();
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Cross-Subdomain Tracking
|
|
299
|
+
|
|
300
|
+
Automatically track users across subdomains:
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
// Auto-detect domain for *.example.com
|
|
304
|
+
const datalyr = new Datalyr({
|
|
305
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
306
|
+
cookieDomain: 'auto' // Default
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Or set explicitly
|
|
310
|
+
const datalyr = new Datalyr({
|
|
311
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
312
|
+
cookieDomain: '.example.com'
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Container Scripts
|
|
317
|
+
|
|
318
|
+
The SDK can automatically load and manage third-party tracking scripts with built-in security:
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
const datalyr = new Datalyr({
|
|
322
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
323
|
+
enableContainer: true // Default: true
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Container scripts are loaded automatically based on your
|
|
327
|
+
// configuration in the Datalyr dashboard
|
|
328
|
+
|
|
329
|
+
// Manually trigger a custom script
|
|
330
|
+
datalyr.loadScript('custom-script-id');
|
|
331
|
+
|
|
332
|
+
// Get list of loaded scripts
|
|
333
|
+
const loadedScripts = datalyr.getLoadedScripts();
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
The container manager supports:
|
|
337
|
+
- **Third-party pixels**: Meta (Facebook), Google, TikTok
|
|
338
|
+
- **Custom scripts**: Inline JavaScript or external scripts
|
|
339
|
+
- **Tracking pixels**: Image-based tracking pixels
|
|
340
|
+
- **Conditional loading**: Based on URL, device type, etc.
|
|
341
|
+
- **Frequency control**: Once per session, once per page, or always
|
|
342
|
+
|
|
343
|
+
**Security Features:**
|
|
344
|
+
- ✅ HTTPS-only script loading (except localhost)
|
|
345
|
+
- ✅ XSS protection with pattern detection
|
|
346
|
+
- ✅ URL validation and protocol blocking
|
|
347
|
+
- ✅ CSP nonce support for inline scripts
|
|
348
|
+
- ✅ Automatic async loading for better performance
|
|
349
|
+
|
|
350
|
+
### Plugins
|
|
351
|
+
|
|
352
|
+
Extend SDK functionality:
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
// Create a plugin
|
|
356
|
+
const myPlugin = {
|
|
357
|
+
name: 'my-plugin',
|
|
358
|
+
|
|
359
|
+
initialize(datalyr) {
|
|
360
|
+
console.log('Plugin initialized');
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
track(eventName, properties) {
|
|
364
|
+
console.log('Event tracked:', eventName);
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
identify(userId, traits) {
|
|
368
|
+
console.log('User identified:', userId);
|
|
369
|
+
},
|
|
370
|
+
|
|
371
|
+
page(properties) {
|
|
372
|
+
console.log('Page tracked');
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// Register plugin
|
|
377
|
+
const datalyr = new Datalyr({
|
|
378
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
379
|
+
plugins: [myPlugin]
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## TypeScript Support
|
|
384
|
+
|
|
385
|
+
Full TypeScript definitions are included:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { Datalyr, EventProperties, UserTraits } from '@datalyr/web';
|
|
389
|
+
|
|
390
|
+
const datalyr = new Datalyr({
|
|
391
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Type-safe event properties
|
|
395
|
+
const properties: EventProperties = {
|
|
396
|
+
product_id: 'SKU-123',
|
|
397
|
+
price: 99.99,
|
|
398
|
+
quantity: 2
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
datalyr.track('Product Added', properties);
|
|
402
|
+
|
|
403
|
+
// Type-safe user traits
|
|
404
|
+
const traits: UserTraits = {
|
|
405
|
+
email: 'user@example.com',
|
|
406
|
+
name: 'John Doe',
|
|
407
|
+
plan: 'premium'
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
datalyr.identify('user_123', traits);
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Framework Integration
|
|
414
|
+
|
|
415
|
+
### React
|
|
416
|
+
|
|
417
|
+
```jsx
|
|
418
|
+
import { useEffect } from 'react';
|
|
419
|
+
import { Datalyr } from '@datalyr/web';
|
|
420
|
+
|
|
421
|
+
const datalyr = new Datalyr({
|
|
422
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
function App() {
|
|
426
|
+
useEffect(() => {
|
|
427
|
+
datalyr.init();
|
|
428
|
+
}, []);
|
|
429
|
+
|
|
430
|
+
const handleClick = () => {
|
|
431
|
+
datalyr.track('Button Clicked', {
|
|
432
|
+
button_name: 'CTA'
|
|
433
|
+
});
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
return <button onClick={handleClick}>Click Me</button>;
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Vue
|
|
441
|
+
|
|
442
|
+
```vue
|
|
443
|
+
<script setup>
|
|
444
|
+
import { onMounted } from 'vue';
|
|
445
|
+
import { Datalyr } from '@datalyr/web';
|
|
446
|
+
|
|
447
|
+
const datalyr = new Datalyr({
|
|
448
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
onMounted(() => {
|
|
452
|
+
datalyr.init();
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
const trackClick = () => {
|
|
456
|
+
datalyr.track('Button Clicked');
|
|
457
|
+
};
|
|
458
|
+
</script>
|
|
459
|
+
|
|
460
|
+
<template>
|
|
461
|
+
<button @click="trackClick">Click Me</button>
|
|
462
|
+
</template>
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Next.js
|
|
466
|
+
|
|
467
|
+
```jsx
|
|
468
|
+
// app/providers.tsx
|
|
469
|
+
'use client';
|
|
470
|
+
|
|
471
|
+
import { useEffect } from 'react';
|
|
472
|
+
import { Datalyr } from '@datalyr/web';
|
|
473
|
+
|
|
474
|
+
const datalyr = new Datalyr({
|
|
475
|
+
workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
export function AnalyticsProvider({ children }) {
|
|
479
|
+
useEffect(() => {
|
|
480
|
+
datalyr.init();
|
|
481
|
+
}, []);
|
|
482
|
+
|
|
483
|
+
return children;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// app/layout.tsx
|
|
487
|
+
import { AnalyticsProvider } from './providers';
|
|
488
|
+
|
|
489
|
+
export default function RootLayout({ children }) {
|
|
490
|
+
return (
|
|
491
|
+
<html>
|
|
492
|
+
<body>
|
|
493
|
+
<AnalyticsProvider>
|
|
494
|
+
{children}
|
|
495
|
+
</AnalyticsProvider>
|
|
496
|
+
</body>
|
|
497
|
+
</html>
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Best Practices
|
|
503
|
+
|
|
504
|
+
### 1. Initialize Early
|
|
505
|
+
Initialize the SDK as early as possible in your application lifecycle:
|
|
506
|
+
|
|
507
|
+
```javascript
|
|
508
|
+
// In your main entry file
|
|
509
|
+
import { Datalyr } from '@datalyr/web';
|
|
510
|
+
|
|
511
|
+
const datalyr = new Datalyr({
|
|
512
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// Initialize before other code
|
|
516
|
+
datalyr.init().then(() => {
|
|
517
|
+
// Start your app
|
|
518
|
+
});
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### 2. Use Consistent Event Naming
|
|
522
|
+
Adopt a naming convention for your events:
|
|
523
|
+
|
|
524
|
+
```javascript
|
|
525
|
+
// Good: Consistent, descriptive names
|
|
526
|
+
datalyr.track('Product Viewed');
|
|
527
|
+
datalyr.track('Cart Updated');
|
|
528
|
+
datalyr.track('Checkout Started');
|
|
529
|
+
|
|
530
|
+
// Avoid: Inconsistent naming
|
|
531
|
+
datalyr.track('view_product');
|
|
532
|
+
datalyr.track('Cart-Update');
|
|
533
|
+
datalyr.track('CHECKOUT_START');
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 3. Include Relevant Properties
|
|
537
|
+
Add properties that will help with analysis:
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
// Good: Rich context
|
|
541
|
+
datalyr.track('Product Viewed', {
|
|
542
|
+
product_id: 'SKU-123',
|
|
543
|
+
product_name: 'Premium Widget',
|
|
544
|
+
category: 'Electronics',
|
|
545
|
+
price: 99.99,
|
|
546
|
+
currency: 'USD',
|
|
547
|
+
in_stock: true,
|
|
548
|
+
view_type: 'quick_view'
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// Avoid: Missing context
|
|
552
|
+
datalyr.track('Product Viewed', {
|
|
553
|
+
id: '123'
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### 4. Identify Users After Authentication
|
|
558
|
+
Call identify as soon as you know who the user is:
|
|
559
|
+
|
|
560
|
+
```javascript
|
|
561
|
+
// After login
|
|
562
|
+
async function handleLogin(email, password) {
|
|
563
|
+
const user = await loginUser(email, password);
|
|
564
|
+
|
|
565
|
+
// Identify immediately after login
|
|
566
|
+
datalyr.identify(user.id, {
|
|
567
|
+
email: user.email,
|
|
568
|
+
name: user.name,
|
|
569
|
+
plan: user.subscription
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// After signup
|
|
574
|
+
async function handleSignup(data) {
|
|
575
|
+
const user = await createUser(data);
|
|
576
|
+
|
|
577
|
+
datalyr.identify(user.id, {
|
|
578
|
+
email: data.email,
|
|
579
|
+
name: data.name,
|
|
580
|
+
signup_date: new Date().toISOString()
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
datalyr.track('Signup Completed', {
|
|
584
|
+
method: 'email'
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### 5. Handle Errors Gracefully
|
|
590
|
+
The SDK handles errors internally, but you can add your own error tracking:
|
|
591
|
+
|
|
592
|
+
```javascript
|
|
593
|
+
window.addEventListener('error', (event) => {
|
|
594
|
+
datalyr.track('JavaScript Error', {
|
|
595
|
+
message: event.message,
|
|
596
|
+
source: event.filename,
|
|
597
|
+
line: event.lineno,
|
|
598
|
+
column: event.colno,
|
|
599
|
+
error: event.error?.toString()
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
## Migration from Script Tag
|
|
605
|
+
|
|
606
|
+
If you're currently using the Datalyr script tag, migration is straightforward:
|
|
607
|
+
|
|
608
|
+
### Before (Script Tag):
|
|
609
|
+
```html
|
|
610
|
+
<script>
|
|
611
|
+
window.datalyr = window.datalyr || [];
|
|
612
|
+
window.datalyr.push(['init', { workspace_id: 'YOUR_WORKSPACE_ID' }]);
|
|
613
|
+
window.datalyr.push(['track', 'Button Clicked']);
|
|
614
|
+
</script>
|
|
615
|
+
<script async src="https://cdn.datalyr.io/datalyr.js"></script>
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### After (Web SDK):
|
|
619
|
+
```javascript
|
|
620
|
+
import { Datalyr } from '@datalyr/web';
|
|
621
|
+
|
|
622
|
+
const datalyr = new Datalyr({
|
|
623
|
+
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
await datalyr.init();
|
|
627
|
+
datalyr.track('Button Clicked');
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
## Browser Support
|
|
631
|
+
|
|
632
|
+
The SDK supports all modern browsers:
|
|
633
|
+
- Chrome/Edge 90+
|
|
634
|
+
- Firefox 88+
|
|
635
|
+
- Safari 14+
|
|
636
|
+
- Opera 76+
|
|
637
|
+
|
|
638
|
+
For older browsers, the SDK will gracefully degrade with fallback implementations.
|
|
639
|
+
|
|
640
|
+
## Performance
|
|
641
|
+
|
|
642
|
+
- **Bundle Size**: ~15KB minified + gzipped
|
|
643
|
+
- **Zero Dependencies**: No external dependencies
|
|
644
|
+
- **Optimized**: Smart event batching reduces network requests
|
|
645
|
+
- **Fast**: Deferred loading for non-critical operations
|
|
646
|
+
- **Memory Management**: Automatic cleanup of resources
|
|
647
|
+
|
|
648
|
+
## Privacy & Compliance
|
|
649
|
+
|
|
650
|
+
The SDK is designed with privacy in mind:
|
|
651
|
+
|
|
652
|
+
- **GDPR Compliant**: Built-in consent management
|
|
653
|
+
- **CCPA Support**: "Do Not Sell" preference support
|
|
654
|
+
- **Cookie Control**: Configurable cookie settings
|
|
655
|
+
- **Data Minimization**: Collect only what you need
|
|
656
|
+
- **User Rights**: Easy opt-out and data deletion
|
|
657
|
+
|
|
658
|
+
## Debugging
|
|
659
|
+
|
|
660
|
+
Enable debug mode for detailed logging:
|
|
661
|
+
|
|
662
|
+
```javascript
|
|
663
|
+
const datalyr = new Datalyr({
|
|
664
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
665
|
+
debug: true
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// Check console for detailed logs:
|
|
669
|
+
// [Datalyr] Event tracked: Button Clicked
|
|
670
|
+
// [Datalyr] Events sent successfully
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
## API Reference
|
|
674
|
+
|
|
675
|
+
### Constructor Options
|
|
676
|
+
|
|
677
|
+
| Option | Type | Default | Description |
|
|
678
|
+
|--------|------|---------|-------------|
|
|
679
|
+
| `workspaceId` | `string` | *required* | Your Datalyr workspace ID |
|
|
680
|
+
| `endpoint` | `string` | Default API | Custom endpoint URL |
|
|
681
|
+
| `debug` | `boolean` | `false` | Enable debug logging |
|
|
682
|
+
| `batchSize` | `number` | `10` | Number of events per batch |
|
|
683
|
+
| `flushInterval` | `number` | `5000` | Time between flushes (ms) |
|
|
684
|
+
| `sessionTimeout` | `number` | `1800000` | Session timeout (ms) |
|
|
685
|
+
| `privacyMode` | `'standard' \| 'strict'` | `'standard'` | Privacy level |
|
|
686
|
+
| `respectDoNotTrack` | `boolean` | `false` | Honor browser DNT |
|
|
687
|
+
| `respectGlobalPrivacyControl` | `boolean` | `true` | Honor GPC |
|
|
688
|
+
| `cookieDomain` | `string \| 'auto'` | `'auto'` | Cookie domain |
|
|
689
|
+
| `trackSPA` | `boolean` | `true` | Track SPA routes |
|
|
690
|
+
| `trackPageViews` | `boolean` | `true` | Track page views |
|
|
691
|
+
| `enableContainer` | `boolean` | `true` | Enable secure container script loading |
|
|
692
|
+
|
|
693
|
+
### Methods
|
|
694
|
+
|
|
695
|
+
| Method | Description |
|
|
696
|
+
|--------|-------------|
|
|
697
|
+
| `init()` | Initialize the SDK |
|
|
698
|
+
| `track(event, properties?)` | Track an event |
|
|
699
|
+
| `identify(userId?, traits?)` | Identify a user |
|
|
700
|
+
| `page(name?, properties?)` | Track a page view |
|
|
701
|
+
| `alias(userId)` | Create an alias |
|
|
702
|
+
| `reset()` | Reset identity |
|
|
703
|
+
| `optOut()` | Opt out of tracking |
|
|
704
|
+
| `optIn()` | Opt back in |
|
|
705
|
+
| `setConsent(config)` | Set consent preferences |
|
|
706
|
+
| `flush()` | Force send events |
|
|
707
|
+
| `getAnonymousId()` | Get anonymous ID |
|
|
708
|
+
| `getUserId()` | Get user ID |
|
|
709
|
+
| `getDistinctId()` | Get distinct ID |
|
|
710
|
+
| `getSessionId()` | Get session ID |
|
|
711
|
+
| `loadScript(scriptId)` | Manually trigger a container script |
|
|
712
|
+
| `getLoadedScripts()` | Get list of loaded container scripts |
|
|
713
|
+
| `destroy()` | Clean up resources |
|
|
714
|
+
|
|
715
|
+
## Support
|
|
716
|
+
|
|
717
|
+
- **Documentation**: [https://docs.datalyr.com](https://docs.datalyr.com)
|
|
718
|
+
- **Issues**: [GitHub Issues](https://github.com/datalyr/web/issues)
|
|
719
|
+
- **Email**: support@datalyr.com
|
|
720
|
+
|
|
721
|
+
## License
|
|
722
|
+
|
|
723
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
Built with ❤️ by the Datalyr team
|