@datalyr/web 1.2.2 → 1.4.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/README.md +590 -290
- package/dist/datalyr.cjs.js +60 -4
- package/dist/datalyr.cjs.js.map +1 -1
- package/dist/datalyr.esm.js +60 -4
- package/dist/datalyr.esm.js.map +1 -1
- package/dist/datalyr.esm.min.js +1 -1
- package/dist/datalyr.esm.min.js.map +1 -1
- package/dist/datalyr.js +60 -4
- package/dist/datalyr.js.map +1 -1
- package/dist/datalyr.min.js +1 -1
- package/dist/datalyr.min.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @datalyr/web
|
|
2
2
|
|
|
3
|
-
Browser
|
|
3
|
+
Browser SDK for event tracking, user identity, and attribution. Version 1.4.0.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -8,26 +8,20 @@ Browser analytics and attribution SDK for web applications. Track events, identi
|
|
|
8
8
|
- [Quick Start](#quick-start)
|
|
9
9
|
- [How It Works](#how-it-works)
|
|
10
10
|
- [Configuration](#configuration)
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
23
|
-
- [Offline Support](#offline-support)
|
|
24
|
-
- [Privacy and Consent](#privacy-and-consent)
|
|
11
|
+
- [API Reference](#api-reference)
|
|
12
|
+
- [Event Tracking](#event-tracking)
|
|
13
|
+
- [User Identity](#user-identity)
|
|
14
|
+
- [Session](#session)
|
|
15
|
+
- [Attribution](#attribution)
|
|
16
|
+
- [Super Properties](#super-properties)
|
|
17
|
+
- [Privacy and Consent](#privacy-and-consent)
|
|
18
|
+
- [Queue and Network](#queue-and-network)
|
|
19
|
+
- [Container Scripts](#container-scripts)
|
|
20
|
+
- [Debugging](#debugging)
|
|
21
|
+
- [Lifecycle](#lifecycle)
|
|
22
|
+
- [Web-to-App Attribution](#web-to-app-attribution)
|
|
25
23
|
- [SPA Support](#spa-support)
|
|
26
|
-
- [Container Scripts](#container-scripts)
|
|
27
24
|
- [Framework Integration](#framework-integration)
|
|
28
|
-
- [React](#react)
|
|
29
|
-
- [Vue](#vue)
|
|
30
|
-
- [Next.js](#nextjs)
|
|
31
25
|
- [TypeScript](#typescript)
|
|
32
26
|
- [Troubleshooting](#troubleshooting)
|
|
33
27
|
- [License](#license)
|
|
@@ -36,7 +30,7 @@ Browser analytics and attribution SDK for web applications. Track events, identi
|
|
|
36
30
|
|
|
37
31
|
## Installation
|
|
38
32
|
|
|
39
|
-
### NPM
|
|
33
|
+
### NPM
|
|
40
34
|
|
|
41
35
|
```bash
|
|
42
36
|
npm install @datalyr/web
|
|
@@ -49,7 +43,16 @@ npm install @datalyr/web
|
|
|
49
43
|
data-workspace-id="YOUR_WORKSPACE_ID"></script>
|
|
50
44
|
```
|
|
51
45
|
|
|
52
|
-
The script tag loads externally (zero bundle size) and auto-initializes.
|
|
46
|
+
The script tag loads externally (zero bundle size) and auto-initializes. Access the SDK via `window.datalyr`.
|
|
47
|
+
|
|
48
|
+
Choose one installation method. Using both causes conflicts.
|
|
49
|
+
|
|
50
|
+
| Feature | Script Tag | NPM |
|
|
51
|
+
|---------|-----------|-----|
|
|
52
|
+
| Bundle Size | 0 (external) | ~15KB |
|
|
53
|
+
| TypeScript | No | Yes |
|
|
54
|
+
| Access | `window.datalyr` | `import datalyr` |
|
|
55
|
+
| Initialize | Automatic | `datalyr.init()` |
|
|
53
56
|
|
|
54
57
|
---
|
|
55
58
|
|
|
@@ -58,34 +61,32 @@ The script tag loads externally (zero bundle size) and auto-initializes. Use `wi
|
|
|
58
61
|
```javascript
|
|
59
62
|
import datalyr from '@datalyr/web';
|
|
60
63
|
|
|
61
|
-
// Initialize
|
|
62
64
|
datalyr.init({
|
|
63
65
|
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
64
66
|
});
|
|
65
67
|
|
|
68
|
+
// Wait for async initialization (encryption, container, initial page view)
|
|
69
|
+
await datalyr.ready();
|
|
70
|
+
|
|
66
71
|
// Track events
|
|
67
72
|
datalyr.track('button_clicked', { button: 'signup' });
|
|
68
73
|
|
|
69
74
|
// Identify users
|
|
70
75
|
datalyr.identify('user_123', { email: 'user@example.com' });
|
|
71
76
|
|
|
72
|
-
// Track page views
|
|
73
|
-
datalyr.page('Pricing',
|
|
77
|
+
// Track page views (page name goes in properties)
|
|
78
|
+
datalyr.page({ title: 'Pricing', variant: 'A' });
|
|
74
79
|
```
|
|
75
80
|
|
|
76
81
|
---
|
|
77
82
|
|
|
78
83
|
## How It Works
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
2. Each event includes device info, session data, and attribution parameters
|
|
86
|
-
3. Events are queued locally and sent in batches
|
|
87
|
-
4. If offline, events are stored and sent when connectivity returns
|
|
88
|
-
5. Events are processed server-side for analytics and attribution reporting
|
|
85
|
+
1. Events are created with `track()`, `page()`, `identify()`, etc.
|
|
86
|
+
2. Each event includes device context, session data, and attribution parameters.
|
|
87
|
+
3. Events are queued locally and sent in batches.
|
|
88
|
+
4. If the browser is offline, events are stored and sent when connectivity returns.
|
|
89
|
+
5. Events are processed server-side for analytics and attribution reporting.
|
|
89
90
|
|
|
90
91
|
### Event Payload
|
|
91
92
|
|
|
@@ -93,25 +94,30 @@ Every event includes:
|
|
|
93
94
|
|
|
94
95
|
```javascript
|
|
95
96
|
{
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
event_name: 'purchase',
|
|
98
|
+
event_data: { ... }, // Custom + attribution + session properties
|
|
98
99
|
|
|
99
100
|
// Identity
|
|
100
|
-
anonymous_id: 'anon_xxxxx',
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
anonymous_id: 'anon_xxxxx', // Persistent browser ID
|
|
102
|
+
distinct_id: 'user_123', // user_id if identified, else anonymous_id
|
|
103
|
+
user_id: 'user_123', // Set after identify()
|
|
104
|
+
session_id: 'sess_xxxxx', // Current session
|
|
105
|
+
|
|
106
|
+
// Context (in event_data)
|
|
107
|
+
url: 'https://example.com/pricing',
|
|
108
|
+
title: 'Pricing',
|
|
107
109
|
referrer: 'https://google.com',
|
|
108
110
|
|
|
109
|
-
// Attribution (if captured)
|
|
111
|
+
// Attribution (in event_data, if captured)
|
|
110
112
|
utm_source: 'facebook',
|
|
111
113
|
fbclid: 'abc123',
|
|
112
114
|
|
|
113
|
-
//
|
|
115
|
+
// Metadata
|
|
116
|
+
workspace_id: 'wk_xxxxx',
|
|
117
|
+
source: 'web',
|
|
114
118
|
timestamp: '2024-01-15T10:30:00Z',
|
|
119
|
+
sdk_version: '1.4.0',
|
|
120
|
+
sdk_name: 'datalyr-web-sdk'
|
|
115
121
|
}
|
|
116
122
|
```
|
|
117
123
|
|
|
@@ -119,53 +125,94 @@ Every event includes:
|
|
|
119
125
|
|
|
120
126
|
## Configuration
|
|
121
127
|
|
|
122
|
-
|
|
128
|
+
All properties of `DatalyrConfig`:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
123
131
|
datalyr.init({
|
|
124
132
|
// Required
|
|
125
133
|
workspaceId: string,
|
|
126
134
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
trackSPA?: boolean, // Track SPA route changes (default: true)
|
|
135
|
+
// Endpoint
|
|
136
|
+
endpoint?: string, // Default: 'https://ingest.datalyr.com'
|
|
137
|
+
fallbackEndpoints?: string[], // Default: [] - Additional endpoints to try on failure
|
|
131
138
|
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
flushInterval?: number, // Send interval ms (default: 5000)
|
|
139
|
+
// Debugging
|
|
140
|
+
debug?: boolean, // Default: false - Enable console logging
|
|
135
141
|
|
|
136
|
-
//
|
|
137
|
-
|
|
142
|
+
// Batching
|
|
143
|
+
batchSize?: number, // Default: 10 - Events per batch
|
|
144
|
+
flushInterval?: number, // Default: 5000 - Flush interval in ms
|
|
145
|
+
flushAt?: number, // Default: 10 - Flush when N events queued
|
|
138
146
|
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
respectGlobalPrivacyControl?: boolean, // Honor GPC (default: true)
|
|
147
|
+
// Priority events (bypass normal batching)
|
|
148
|
+
criticalEvents?: string[], // Default: undefined (disabled). Events flushed immediately.
|
|
149
|
+
highPriorityEvents?: string[], // Default: undefined (disabled). Events given queue priority.
|
|
143
150
|
|
|
144
|
-
//
|
|
145
|
-
|
|
151
|
+
// Session
|
|
152
|
+
sessionTimeout?: number, // Default: 3600000 (60 min)
|
|
153
|
+
trackSessions?: boolean, // Default: true
|
|
146
154
|
|
|
147
|
-
//
|
|
148
|
-
|
|
155
|
+
// Attribution
|
|
156
|
+
attributionWindow?: number, // Default: 7776000000 (90 days)
|
|
157
|
+
trackedParams?: string[], // Default: [] - Additional URL params to capture
|
|
149
158
|
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
// Privacy
|
|
160
|
+
respectDoNotTrack?: boolean, // Default: false - Honor browser DNT header
|
|
161
|
+
respectGlobalPrivacyControl?: boolean, // Default: true - Honor GPC signal
|
|
162
|
+
privacyMode?: 'standard' | 'strict', // Default: 'standard' - 'strict' limits data collection
|
|
163
|
+
|
|
164
|
+
// Cookies / Storage
|
|
165
|
+
cookieDomain?: string | 'auto', // Default: 'auto'
|
|
166
|
+
cookieExpires?: number, // Default: 365 (days)
|
|
167
|
+
secureCookie?: boolean | 'auto', // Default: 'auto'
|
|
168
|
+
sameSite?: 'Strict' | 'Lax' | 'None', // Default: 'Lax'
|
|
169
|
+
cookiePrefix?: string, // Default: '__dl_'
|
|
170
|
+
|
|
171
|
+
// Performance
|
|
172
|
+
enablePerformanceTracking?: boolean, // Default: true - Collect navigation timing metrics
|
|
173
|
+
enableFingerprinting?: boolean, // Default: true - Minimal device fingerprinting (standard mode only)
|
|
174
|
+
|
|
175
|
+
// Retry / Offline
|
|
176
|
+
maxRetries?: number, // Default: 5
|
|
177
|
+
retryDelay?: number, // Default: 1000 (ms)
|
|
178
|
+
maxOfflineQueueSize?: number, // Default: 100
|
|
179
|
+
|
|
180
|
+
// SPA
|
|
181
|
+
trackSPA?: boolean, // Default: true - Auto-track route changes
|
|
182
|
+
trackPageViews?: boolean, // Default: true - Auto-track initial page view
|
|
183
|
+
|
|
184
|
+
// Container scripts
|
|
185
|
+
enableContainer?: boolean, // Default: true - Load third-party scripts from dashboard
|
|
186
|
+
|
|
187
|
+
// Auto-Identify (opt-in)
|
|
188
|
+
autoIdentify?: boolean, // Default: false - Automatically identify users
|
|
189
|
+
autoIdentifyForms?: boolean, // Default: true - Capture email from forms (when autoIdentify enabled)
|
|
190
|
+
autoIdentifyAPI?: boolean, // Default: true - Capture email from API responses (when autoIdentify enabled)
|
|
191
|
+
autoIdentifyShopify?: boolean, // Default: true - Capture email from Shopify endpoints (when autoIdentify enabled)
|
|
192
|
+
autoIdentifyTrustedDomains?: string[], // Default: [] - Additional domains to trust for API capture
|
|
193
|
+
|
|
194
|
+
// Plugins
|
|
195
|
+
plugins?: DatalyrPlugin[], // Default: [] - Custom plugin instances
|
|
153
196
|
});
|
|
154
197
|
```
|
|
155
198
|
|
|
156
199
|
---
|
|
157
200
|
|
|
158
|
-
##
|
|
201
|
+
## API Reference
|
|
202
|
+
|
|
203
|
+
### Event Tracking
|
|
204
|
+
|
|
205
|
+
#### `track(eventName, properties?)`
|
|
159
206
|
|
|
160
|
-
|
|
207
|
+
Track a custom event.
|
|
161
208
|
|
|
162
|
-
|
|
209
|
+
```typescript
|
|
210
|
+
track(eventName: string, properties?: EventProperties): void
|
|
211
|
+
```
|
|
163
212
|
|
|
164
213
|
```javascript
|
|
165
|
-
// Simple event
|
|
166
214
|
datalyr.track('signup_started');
|
|
167
215
|
|
|
168
|
-
// Event with properties
|
|
169
216
|
datalyr.track('product_viewed', {
|
|
170
217
|
product_id: 'SKU123',
|
|
171
218
|
product_name: 'Blue Shirt',
|
|
@@ -173,148 +220,235 @@ datalyr.track('product_viewed', {
|
|
|
173
220
|
currency: 'USD',
|
|
174
221
|
category: 'Apparel',
|
|
175
222
|
});
|
|
176
|
-
|
|
177
|
-
// Event with value
|
|
178
|
-
datalyr.track('level_completed', {
|
|
179
|
-
level: 5,
|
|
180
|
-
score: 1250,
|
|
181
|
-
time_seconds: 120,
|
|
182
|
-
});
|
|
183
223
|
```
|
|
184
224
|
|
|
185
|
-
|
|
225
|
+
#### `page(properties?)`
|
|
186
226
|
|
|
187
|
-
Track
|
|
227
|
+
Track a page view. The page `title`, `url`, `path`, `search`, and `referrer` are captured automatically. Pass `properties` to add or override values.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
page(properties?: PageProperties): void
|
|
231
|
+
```
|
|
188
232
|
|
|
189
233
|
```javascript
|
|
190
|
-
// Track current page
|
|
234
|
+
// Track current page (all properties auto-captured)
|
|
191
235
|
datalyr.page();
|
|
192
236
|
|
|
193
|
-
//
|
|
194
|
-
datalyr.page('Pricing');
|
|
237
|
+
// Override title, add custom properties
|
|
238
|
+
datalyr.page({ title: 'Pricing', variant: 'A' });
|
|
195
239
|
|
|
196
|
-
//
|
|
197
|
-
datalyr.page(
|
|
198
|
-
product_id: 'SKU123',
|
|
199
|
-
source: 'search',
|
|
200
|
-
});
|
|
240
|
+
// Add custom properties
|
|
241
|
+
datalyr.page({ product_id: 'SKU123', source: 'search' });
|
|
201
242
|
```
|
|
202
243
|
|
|
203
|
-
|
|
244
|
+
Note: `page()` does not accept a name string as the first argument. To set the page name, pass it as `title` in the properties object.
|
|
204
245
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
```javascript
|
|
208
|
-
// View product
|
|
209
|
-
datalyr.track('Product Viewed', {
|
|
210
|
-
product_id: 'SKU123',
|
|
211
|
-
product_name: 'Blue Shirt',
|
|
212
|
-
price: 29.99,
|
|
213
|
-
currency: 'USD'
|
|
214
|
-
});
|
|
246
|
+
#### `screen(screenName, properties?)`
|
|
215
247
|
|
|
216
|
-
|
|
217
|
-
datalyr.track('Add to Cart', {
|
|
218
|
-
product_id: 'SKU123',
|
|
219
|
-
quantity: 1,
|
|
220
|
-
price: 29.99
|
|
221
|
-
});
|
|
248
|
+
Track a screen view. Intended for SPAs or hybrid apps.
|
|
222
249
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
currency: 'USD',
|
|
227
|
-
item_count: 2
|
|
228
|
-
});
|
|
250
|
+
```typescript
|
|
251
|
+
screen(screenName: string, properties?: Record<string, any>): void
|
|
252
|
+
```
|
|
229
253
|
|
|
230
|
-
|
|
231
|
-
datalyr.
|
|
232
|
-
|
|
233
|
-
total: 59.98,
|
|
234
|
-
currency: 'USD',
|
|
235
|
-
items: [
|
|
236
|
-
{ product_id: 'SKU123', quantity: 2, price: 29.99 }
|
|
237
|
-
]
|
|
238
|
-
});
|
|
254
|
+
```javascript
|
|
255
|
+
datalyr.screen('Dashboard');
|
|
256
|
+
datalyr.screen('Product Details', { product_id: 'SKU123' });
|
|
239
257
|
```
|
|
240
258
|
|
|
241
|
-
|
|
259
|
+
Internally fires a `pageview` event with the `screen` property set.
|
|
242
260
|
|
|
243
|
-
|
|
261
|
+
#### `trackAppDownloadClick(options)`
|
|
244
262
|
|
|
245
|
-
|
|
263
|
+
Track an app download click, then redirect to the app store. Fires a `$app_download_click` event with full attribution, flushes via `sendBeacon`, and redirects.
|
|
246
264
|
|
|
247
|
-
|
|
265
|
+
```typescript
|
|
266
|
+
trackAppDownloadClick(options: {
|
|
267
|
+
targetPlatform: 'ios' | 'android';
|
|
268
|
+
appStoreUrl: string;
|
|
269
|
+
}): void
|
|
270
|
+
```
|
|
248
271
|
|
|
249
272
|
```javascript
|
|
250
|
-
|
|
251
|
-
|
|
273
|
+
datalyr.trackAppDownloadClick({
|
|
274
|
+
targetPlatform: 'ios',
|
|
275
|
+
appStoreUrl: 'https://apps.apple.com/app/your-app/id123456789',
|
|
276
|
+
});
|
|
252
277
|
```
|
|
253
278
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
- Can be passed to your backend for server-side attribution
|
|
279
|
+
For Android Play Store URLs, attribution parameters are automatically encoded into the `referrer` query parameter for deterministic install attribution.
|
|
280
|
+
|
|
281
|
+
---
|
|
258
282
|
|
|
259
|
-
###
|
|
283
|
+
### User Identity
|
|
260
284
|
|
|
261
|
-
|
|
285
|
+
#### `identify(userId, traits?)`
|
|
286
|
+
|
|
287
|
+
Link the anonymous visitor to a known user. Rotates the session ID on call (prevents session fixation). User traits are encrypted at rest.
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
identify(userId: string, traits?: UserTraits): void
|
|
291
|
+
```
|
|
262
292
|
|
|
263
293
|
```javascript
|
|
264
294
|
datalyr.identify('user_123', {
|
|
265
295
|
email: 'user@example.com',
|
|
296
|
+
name: 'John Doe',
|
|
297
|
+
plan: 'premium',
|
|
298
|
+
company: 'Acme Inc',
|
|
266
299
|
});
|
|
267
300
|
```
|
|
268
301
|
|
|
269
|
-
|
|
270
|
-
- All future events include `user_id`
|
|
271
|
-
- Historical anonymous events can be linked server-side
|
|
272
|
-
- Attribution data is preserved on the user
|
|
302
|
+
#### `alias(userId, previousId?)`
|
|
273
303
|
|
|
274
|
-
|
|
304
|
+
Create an alias linking one user ID to another. If `previousId` is omitted, the current anonymous ID is used.
|
|
275
305
|
|
|
276
|
-
|
|
306
|
+
```typescript
|
|
307
|
+
alias(userId: string, previousId?: string): void
|
|
308
|
+
```
|
|
277
309
|
|
|
278
310
|
```javascript
|
|
279
|
-
datalyr.
|
|
280
|
-
|
|
281
|
-
email: 'user@example.com',
|
|
282
|
-
name: 'John Doe',
|
|
283
|
-
phone: '+1234567890',
|
|
311
|
+
datalyr.alias('user_123', 'temp_user_456');
|
|
312
|
+
```
|
|
284
313
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
314
|
+
#### `group(groupId, traits?)`
|
|
315
|
+
|
|
316
|
+
Associate the current user with a group or account.
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
group(groupId: string, traits?: Record<string, any>): void
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
datalyr.group('company_abc', { name: 'Acme Inc', plan: 'enterprise' });
|
|
290
324
|
```
|
|
291
325
|
|
|
292
|
-
|
|
326
|
+
#### `reset()`
|
|
293
327
|
|
|
294
|
-
Clear user
|
|
328
|
+
Clear user identity and start a new session. The anonymous ID is preserved.
|
|
295
329
|
|
|
296
330
|
```javascript
|
|
297
331
|
datalyr.reset();
|
|
298
332
|
```
|
|
299
333
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
334
|
+
#### `getAnonymousId()`
|
|
335
|
+
|
|
336
|
+
Returns the persistent anonymous ID assigned on first visit.
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
getAnonymousId(): string
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### `getUserId()`
|
|
343
|
+
|
|
344
|
+
Returns the current user ID set by `identify()`, or `null` if not identified.
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
getUserId(): string | null
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### `getDistinctId()`
|
|
351
|
+
|
|
352
|
+
Returns the distinct ID. This is `userId` if identified, otherwise `anonymousId`.
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
getDistinctId(): string
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### Session
|
|
361
|
+
|
|
362
|
+
#### `getSessionId()`
|
|
363
|
+
|
|
364
|
+
Returns the current session ID.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
getSessionId(): string
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
#### `startNewSession()`
|
|
371
|
+
|
|
372
|
+
Force-start a new session. Returns the new session ID.
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
startNewSession(): string
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
const newSessionId = datalyr.startNewSession();
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### `getSessionData()`
|
|
383
|
+
|
|
384
|
+
Returns the current session metadata, or `null` if no active session.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
getSessionData(): SessionData | null
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
interface SessionData {
|
|
392
|
+
id: string;
|
|
393
|
+
startTime: number;
|
|
394
|
+
lastActivity: number;
|
|
395
|
+
pageViews: number;
|
|
396
|
+
events: number;
|
|
397
|
+
duration: number;
|
|
398
|
+
isActive: boolean;
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
#### `ready()`
|
|
403
|
+
|
|
404
|
+
Returns a promise that resolves when async initialization is complete (encryption, container loading, initial page view).
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
ready(): Promise<void>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
datalyr.init({ workspaceId: 'YOUR_WORKSPACE_ID' });
|
|
412
|
+
await datalyr.ready();
|
|
413
|
+
// Encryption is initialized, container is loaded, safe to track
|
|
414
|
+
```
|
|
304
415
|
|
|
305
416
|
---
|
|
306
417
|
|
|
307
|
-
|
|
418
|
+
### Attribution
|
|
308
419
|
|
|
309
|
-
|
|
420
|
+
#### `getAttribution()`
|
|
310
421
|
|
|
311
|
-
|
|
422
|
+
Returns the current captured attribution data.
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
getAttribution(): Attribution
|
|
426
|
+
```
|
|
312
427
|
|
|
313
428
|
```javascript
|
|
314
|
-
const attribution = datalyr.
|
|
429
|
+
const attribution = datalyr.getAttribution();
|
|
430
|
+
console.log(attribution.source, attribution.medium, attribution.campaign);
|
|
315
431
|
```
|
|
316
432
|
|
|
317
|
-
|
|
433
|
+
```typescript
|
|
434
|
+
interface Attribution {
|
|
435
|
+
source?: string | null;
|
|
436
|
+
medium?: string | null;
|
|
437
|
+
campaign?: string | null;
|
|
438
|
+
term?: string | null;
|
|
439
|
+
content?: string | null;
|
|
440
|
+
clickId?: string | null;
|
|
441
|
+
clickIdType?: string | null; // 'fbclid', 'gclid', etc.
|
|
442
|
+
referrer?: string | null;
|
|
443
|
+
referrerHost?: string | null;
|
|
444
|
+
landingPage?: string | null;
|
|
445
|
+
landingPath?: string | null;
|
|
446
|
+
timestamp?: number;
|
|
447
|
+
[key: string]: any; // Custom tracked params
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
Captured automatically from URLs:
|
|
318
452
|
|
|
319
453
|
| Type | Parameters |
|
|
320
454
|
|------|------------|
|
|
@@ -322,173 +456,313 @@ Captured parameters:
|
|
|
322
456
|
| Click IDs | `fbclid`, `gclid`, `ttclid`, `twclid`, `li_fat_id`, `msclkid` |
|
|
323
457
|
| Referrer | `referrer`, `landing_page` |
|
|
324
458
|
|
|
325
|
-
Attribution
|
|
326
|
-
- First-touch attribution (90-day window)
|
|
327
|
-
- Last-touch attribution
|
|
328
|
-
- Customer journey tracking (up to 30 touchpoints)
|
|
459
|
+
Attribution supports first-touch (90-day window), last-touch, and journey tracking.
|
|
329
460
|
|
|
330
|
-
|
|
461
|
+
#### `setAttribution(attribution)`
|
|
331
462
|
|
|
332
|
-
|
|
463
|
+
Manually set or override attribution data.
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
setAttribution(attribution: Partial<Attribution>): void
|
|
467
|
+
```
|
|
333
468
|
|
|
334
469
|
```javascript
|
|
335
|
-
datalyr.
|
|
336
|
-
|
|
337
|
-
|
|
470
|
+
datalyr.setAttribution({
|
|
471
|
+
source: 'partner',
|
|
472
|
+
medium: 'referral',
|
|
473
|
+
campaign: 'spring_promo',
|
|
338
474
|
});
|
|
339
475
|
```
|
|
340
476
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
## Event Queue
|
|
477
|
+
#### `getJourney()`
|
|
344
478
|
|
|
345
|
-
|
|
479
|
+
Returns the customer journey as an array of touchpoints (up to 30).
|
|
346
480
|
|
|
347
|
-
|
|
481
|
+
```typescript
|
|
482
|
+
getJourney(): TouchPoint[]
|
|
483
|
+
```
|
|
348
484
|
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
485
|
+
```typescript
|
|
486
|
+
interface TouchPoint {
|
|
487
|
+
timestamp: number;
|
|
488
|
+
source?: string;
|
|
489
|
+
medium?: string;
|
|
490
|
+
campaign?: string;
|
|
491
|
+
sessionId: string;
|
|
492
|
+
}
|
|
355
493
|
```
|
|
356
494
|
|
|
357
|
-
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
### Super Properties
|
|
498
|
+
|
|
499
|
+
Super properties are included with every subsequent event.
|
|
500
|
+
|
|
501
|
+
#### `setSuperProperties(properties)`
|
|
502
|
+
|
|
503
|
+
Merge properties into the super properties store.
|
|
358
504
|
|
|
359
|
-
|
|
505
|
+
```typescript
|
|
506
|
+
setSuperProperties(properties: Record<string, any>): void
|
|
507
|
+
```
|
|
360
508
|
|
|
361
509
|
```javascript
|
|
362
|
-
|
|
510
|
+
datalyr.setSuperProperties({ app_version: '2.1.0', environment: 'production' });
|
|
363
511
|
```
|
|
364
512
|
|
|
365
|
-
|
|
513
|
+
#### `unsetSuperProperty(propertyName)`
|
|
366
514
|
|
|
367
|
-
|
|
515
|
+
Remove a single super property by key.
|
|
368
516
|
|
|
369
|
-
|
|
517
|
+
```typescript
|
|
518
|
+
unsetSuperProperty(propertyName: string): void
|
|
519
|
+
```
|
|
370
520
|
|
|
371
|
-
|
|
521
|
+
```javascript
|
|
522
|
+
datalyr.unsetSuperProperty('environment');
|
|
523
|
+
```
|
|
372
524
|
|
|
373
|
-
|
|
374
|
-
- Events are stored locally
|
|
375
|
-
- Queue persists across page refreshes
|
|
376
|
-
- Events are sent when connectivity returns
|
|
525
|
+
#### `getSuperProperties()`
|
|
377
526
|
|
|
378
|
-
|
|
379
|
-
// Events work seamlessly offline
|
|
380
|
-
datalyr.track('Button Clicked'); // Automatically queued if offline
|
|
527
|
+
Returns a copy of the current super properties.
|
|
381
528
|
|
|
382
|
-
|
|
383
|
-
|
|
529
|
+
```typescript
|
|
530
|
+
getSuperProperties(): Record<string, any>
|
|
384
531
|
```
|
|
385
532
|
|
|
386
533
|
---
|
|
387
534
|
|
|
388
|
-
|
|
535
|
+
### Privacy and Consent
|
|
536
|
+
|
|
537
|
+
#### `optOut()`
|
|
389
538
|
|
|
390
|
-
|
|
539
|
+
Opt the user out of all tracking. Clears the event queue and persists the preference in a cookie.
|
|
391
540
|
|
|
392
541
|
```javascript
|
|
393
|
-
// Opt user out of tracking
|
|
394
542
|
datalyr.optOut();
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
#### `optIn()`
|
|
546
|
+
|
|
547
|
+
Opt the user back in.
|
|
395
548
|
|
|
396
|
-
|
|
549
|
+
```javascript
|
|
397
550
|
datalyr.optIn();
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
#### `isOptedOut()`
|
|
554
|
+
|
|
555
|
+
Returns `true` if the user has opted out.
|
|
398
556
|
|
|
399
|
-
|
|
400
|
-
|
|
557
|
+
```typescript
|
|
558
|
+
isOptedOut(): boolean
|
|
401
559
|
```
|
|
402
560
|
|
|
403
|
-
|
|
561
|
+
#### `setConsent(consent)`
|
|
562
|
+
|
|
563
|
+
Set granular consent preferences.
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
setConsent(consent: ConsentConfig): void
|
|
567
|
+
```
|
|
404
568
|
|
|
405
569
|
```javascript
|
|
406
570
|
datalyr.setConsent({
|
|
407
571
|
analytics: true,
|
|
408
572
|
marketing: false,
|
|
409
573
|
preferences: true,
|
|
410
|
-
sale: false
|
|
574
|
+
sale: false // CCPA "Do Not Sell"
|
|
411
575
|
});
|
|
412
576
|
```
|
|
413
577
|
|
|
414
|
-
|
|
578
|
+
```typescript
|
|
579
|
+
interface ConsentConfig {
|
|
580
|
+
analytics?: boolean;
|
|
581
|
+
marketing?: boolean;
|
|
582
|
+
preferences?: boolean;
|
|
583
|
+
sale?: boolean;
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
#### Privacy Modes
|
|
415
588
|
|
|
416
589
|
```javascript
|
|
417
|
-
// Standard mode (default)
|
|
418
|
-
datalyr.init({
|
|
419
|
-
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
420
|
-
privacyMode: 'standard'
|
|
421
|
-
});
|
|
590
|
+
// Standard mode (default) - normal fingerprinting + tracking
|
|
591
|
+
datalyr.init({ workspaceId: '...', privacyMode: 'standard' });
|
|
422
592
|
|
|
423
|
-
// Strict mode - minimal data collection
|
|
424
|
-
datalyr.init({
|
|
425
|
-
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
426
|
-
privacyMode: 'strict'
|
|
427
|
-
});
|
|
593
|
+
// Strict mode - minimal data collection, no fingerprinting
|
|
594
|
+
datalyr.init({ workspaceId: '...', privacyMode: 'strict' });
|
|
428
595
|
```
|
|
429
596
|
|
|
597
|
+
The SDK also respects `respectDoNotTrack` and `respectGlobalPrivacyControl` config flags.
|
|
598
|
+
|
|
430
599
|
---
|
|
431
600
|
|
|
432
|
-
|
|
601
|
+
### Queue and Network
|
|
602
|
+
|
|
603
|
+
#### `flush()`
|
|
433
604
|
|
|
434
|
-
|
|
605
|
+
Manually flush the event queue. Returns a promise that resolves when all queued events are sent.
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
flush(): Promise<void>
|
|
609
|
+
```
|
|
435
610
|
|
|
436
611
|
```javascript
|
|
437
|
-
datalyr.
|
|
438
|
-
|
|
439
|
-
trackSPA: true // Auto-track route changes (default: true)
|
|
440
|
-
});
|
|
612
|
+
await datalyr.flush();
|
|
613
|
+
```
|
|
441
614
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
615
|
+
#### `getNetworkStatus()`
|
|
616
|
+
|
|
617
|
+
Returns the current network status as tracked by the SDK.
|
|
618
|
+
|
|
619
|
+
```typescript
|
|
620
|
+
getNetworkStatus(): NetworkStatus
|
|
446
621
|
```
|
|
447
622
|
|
|
623
|
+
```typescript
|
|
624
|
+
interface NetworkStatus {
|
|
625
|
+
isOnline: boolean;
|
|
626
|
+
lastOfflineAt: number | null;
|
|
627
|
+
lastOnlineAt: number | null;
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Events are automatically stored when offline and sent when connectivity returns.
|
|
632
|
+
|
|
448
633
|
---
|
|
449
634
|
|
|
450
|
-
|
|
635
|
+
### Container Scripts
|
|
451
636
|
|
|
452
637
|
Container scripts manage third-party tracking pixels (Meta, Google, TikTok) configured in your Datalyr dashboard.
|
|
453
638
|
|
|
454
|
-
|
|
639
|
+
#### `loadScript(scriptId)`
|
|
455
640
|
|
|
456
|
-
|
|
641
|
+
Trigger a container script by ID.
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
loadScript(scriptId: string): void
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
```javascript
|
|
648
|
+
datalyr.loadScript('custom-script-id');
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
#### `getLoadedScripts()`
|
|
652
|
+
|
|
653
|
+
Returns an array of loaded script IDs.
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
getLoadedScripts(): string[]
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Container script tag installation (loads pixels from your dashboard config):
|
|
457
660
|
|
|
458
661
|
```html
|
|
459
662
|
<script defer src="https://track.datalyr.com/container.js"
|
|
460
663
|
data-workspace-id="YOUR_WORKSPACE_ID"></script>
|
|
461
664
|
```
|
|
462
665
|
|
|
463
|
-
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Debugging
|
|
669
|
+
|
|
670
|
+
#### `getErrors()`
|
|
671
|
+
|
|
672
|
+
Returns an array of SDK errors (up to 50 most recent).
|
|
673
|
+
|
|
674
|
+
```typescript
|
|
675
|
+
getErrors(): ErrorInfo[]
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
interface ErrorInfo {
|
|
680
|
+
message: string;
|
|
681
|
+
stack?: string;
|
|
682
|
+
context?: any;
|
|
683
|
+
timestamp: string;
|
|
684
|
+
url: string;
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
```javascript
|
|
689
|
+
console.log(datalyr.getErrors());
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Enable `debug: true` in config to log all SDK activity to the console.
|
|
693
|
+
|
|
694
|
+
---
|
|
464
695
|
|
|
465
|
-
###
|
|
696
|
+
### Lifecycle
|
|
697
|
+
|
|
698
|
+
#### `destroy()`
|
|
699
|
+
|
|
700
|
+
Tear down the SDK instance. Restores patched `history.pushState` / `replaceState`, removes event listeners, cleans up the queue, session, container iframes, auto-identify listeners, and encryption keys. Resets all in-memory state.
|
|
701
|
+
|
|
702
|
+
```typescript
|
|
703
|
+
destroy(): void
|
|
704
|
+
```
|
|
466
705
|
|
|
467
706
|
```javascript
|
|
468
|
-
datalyr.
|
|
469
|
-
|
|
470
|
-
enableContainer: true // Default: true
|
|
471
|
-
});
|
|
707
|
+
datalyr.destroy();
|
|
708
|
+
```
|
|
472
709
|
|
|
473
|
-
|
|
474
|
-
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## Web-to-App Attribution
|
|
713
|
+
|
|
714
|
+
Track users who click a "Download App" button on your website and attribute their app install back to the original web session.
|
|
715
|
+
|
|
716
|
+
### Flow
|
|
717
|
+
|
|
718
|
+
1. User clicks an ad and lands on your page (web SDK captures `fbclid`, UTMs, etc.)
|
|
719
|
+
2. User clicks "Download App" -- `trackAppDownloadClick()` fires with full attribution
|
|
720
|
+
3. User installs from App Store / Play Store
|
|
721
|
+
4. First app open -- mobile SDK recovers the web attribution:
|
|
722
|
+
- **Android**: Deterministic match via Play Store `referrer` parameter (~95% accuracy)
|
|
723
|
+
- **iOS**: IP-based match against recent web events within 24 hours (~90%+ accuracy)
|
|
724
|
+
|
|
725
|
+
### Usage
|
|
726
|
+
|
|
727
|
+
```javascript
|
|
728
|
+
document.querySelector('#download-btn').addEventListener('click', () => {
|
|
729
|
+
datalyr.trackAppDownloadClick({
|
|
730
|
+
targetPlatform: 'ios',
|
|
731
|
+
appStoreUrl: 'https://apps.apple.com/app/your-app/id123456789',
|
|
732
|
+
});
|
|
733
|
+
});
|
|
734
|
+
```
|
|
475
735
|
|
|
476
|
-
|
|
477
|
-
|
|
736
|
+
```javascript
|
|
737
|
+
// Android - attribution params auto-encoded into Play Store referrer
|
|
738
|
+
datalyr.trackAppDownloadClick({
|
|
739
|
+
targetPlatform: 'android',
|
|
740
|
+
appStoreUrl: 'https://play.google.com/store/apps/details?id=com.yourapp',
|
|
741
|
+
});
|
|
478
742
|
```
|
|
479
743
|
|
|
480
|
-
###
|
|
744
|
+
### Requirements
|
|
745
|
+
|
|
746
|
+
- Web SDK initialized on the prelander page
|
|
747
|
+
- Mobile SDK (`@datalyr/react-native` or `@datalyr/swift`) installed in the app
|
|
748
|
+
- Attribution is recovered automatically on first app launch
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
## SPA Support
|
|
753
|
+
|
|
754
|
+
Route changes are tracked automatically when `trackSPA: true` (the default). The SDK patches `history.pushState`, `history.replaceState`, and listens for `popstate` and `hashchange` events. Attribution cache is cleared on each navigation so new URL parameters are captured.
|
|
481
755
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
756
|
+
```javascript
|
|
757
|
+
datalyr.init({
|
|
758
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
759
|
+
trackSPA: true, // default
|
|
760
|
+
trackPageViews: true, // auto-track initial page view, default
|
|
761
|
+
});
|
|
486
762
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
- URL validation
|
|
491
|
-
- CSP nonce support
|
|
763
|
+
// Manual page tracking
|
|
764
|
+
datalyr.page({ title: 'Product Details', product_id: 'SKU-123' });
|
|
765
|
+
```
|
|
492
766
|
|
|
493
767
|
---
|
|
494
768
|
|
|
@@ -502,13 +776,11 @@ import datalyr from '@datalyr/web';
|
|
|
502
776
|
|
|
503
777
|
function App() {
|
|
504
778
|
useEffect(() => {
|
|
505
|
-
datalyr.init({
|
|
506
|
-
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
507
|
-
});
|
|
779
|
+
datalyr.init({ workspaceId: 'YOUR_WORKSPACE_ID' });
|
|
508
780
|
}, []);
|
|
509
781
|
|
|
510
782
|
const handleClick = () => {
|
|
511
|
-
datalyr.track('
|
|
783
|
+
datalyr.track('button_clicked', { button_name: 'CTA' });
|
|
512
784
|
};
|
|
513
785
|
|
|
514
786
|
return <button onClick={handleClick}>Click Me</button>;
|
|
@@ -523,13 +795,11 @@ import { onMounted } from 'vue';
|
|
|
523
795
|
import datalyr from '@datalyr/web';
|
|
524
796
|
|
|
525
797
|
onMounted(() => {
|
|
526
|
-
datalyr.init({
|
|
527
|
-
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
528
|
-
});
|
|
798
|
+
datalyr.init({ workspaceId: 'YOUR_WORKSPACE_ID' });
|
|
529
799
|
});
|
|
530
800
|
|
|
531
801
|
const trackClick = () => {
|
|
532
|
-
datalyr.track('
|
|
802
|
+
datalyr.track('button_clicked');
|
|
533
803
|
};
|
|
534
804
|
</script>
|
|
535
805
|
|
|
@@ -540,34 +810,32 @@ const trackClick = () => {
|
|
|
540
810
|
|
|
541
811
|
### Next.js
|
|
542
812
|
|
|
543
|
-
```
|
|
813
|
+
```tsx
|
|
544
814
|
// app/providers.tsx
|
|
545
815
|
'use client';
|
|
546
816
|
|
|
547
817
|
import { useEffect } from 'react';
|
|
548
818
|
import datalyr from '@datalyr/web';
|
|
549
819
|
|
|
550
|
-
export function AnalyticsProvider({ children }) {
|
|
820
|
+
export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
|
|
551
821
|
useEffect(() => {
|
|
552
822
|
datalyr.init({
|
|
553
|
-
workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID
|
|
554
|
-
debug: process.env.NODE_ENV === 'development'
|
|
823
|
+
workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
|
|
824
|
+
debug: process.env.NODE_ENV === 'development',
|
|
555
825
|
});
|
|
556
826
|
}, []);
|
|
557
827
|
|
|
558
|
-
return children
|
|
828
|
+
return <>{children}</>;
|
|
559
829
|
}
|
|
560
830
|
|
|
561
831
|
// app/layout.tsx
|
|
562
832
|
import { AnalyticsProvider } from './providers';
|
|
563
833
|
|
|
564
|
-
export default function RootLayout({ children }) {
|
|
834
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
565
835
|
return (
|
|
566
836
|
<html>
|
|
567
837
|
<body>
|
|
568
|
-
<AnalyticsProvider>
|
|
569
|
-
{children}
|
|
570
|
-
</AnalyticsProvider>
|
|
838
|
+
<AnalyticsProvider>{children}</AnalyticsProvider>
|
|
571
839
|
</body>
|
|
572
840
|
</html>
|
|
573
841
|
);
|
|
@@ -578,77 +846,109 @@ export default function RootLayout({ children }) {
|
|
|
578
846
|
|
|
579
847
|
## TypeScript
|
|
580
848
|
|
|
849
|
+
All types are exported from the package:
|
|
850
|
+
|
|
581
851
|
```typescript
|
|
582
|
-
import datalyr
|
|
852
|
+
import datalyr from '@datalyr/web';
|
|
853
|
+
import type {
|
|
854
|
+
DatalyrConfig,
|
|
855
|
+
EventProperties,
|
|
856
|
+
UserTraits,
|
|
857
|
+
PageProperties,
|
|
858
|
+
SessionData,
|
|
859
|
+
Attribution,
|
|
860
|
+
TouchPoint,
|
|
861
|
+
ConsentConfig,
|
|
862
|
+
DatalyrPlugin,
|
|
863
|
+
FingerprintData,
|
|
864
|
+
IngestEventPayload,
|
|
865
|
+
IngestBatchPayload,
|
|
866
|
+
NetworkStatus,
|
|
867
|
+
ErrorInfo,
|
|
868
|
+
PerformanceMetrics,
|
|
869
|
+
} from '@datalyr/web';
|
|
870
|
+
```
|
|
583
871
|
|
|
584
|
-
|
|
872
|
+
```typescript
|
|
585
873
|
const properties: EventProperties = {
|
|
586
874
|
product_id: 'SKU-123',
|
|
587
875
|
price: 99.99,
|
|
588
|
-
quantity: 2
|
|
876
|
+
quantity: 2,
|
|
589
877
|
};
|
|
878
|
+
datalyr.track('product_added', properties);
|
|
590
879
|
|
|
591
|
-
datalyr.track('Product Added', properties);
|
|
592
|
-
|
|
593
|
-
// Type-safe user traits
|
|
594
880
|
const traits: UserTraits = {
|
|
595
881
|
email: 'user@example.com',
|
|
596
882
|
name: 'John Doe',
|
|
597
|
-
plan: 'premium'
|
|
883
|
+
plan: 'premium',
|
|
598
884
|
};
|
|
599
|
-
|
|
600
885
|
datalyr.identify('user_123', traits);
|
|
601
886
|
```
|
|
602
887
|
|
|
888
|
+
### Plugin Interface
|
|
889
|
+
|
|
890
|
+
```typescript
|
|
891
|
+
interface DatalyrPlugin {
|
|
892
|
+
name: string;
|
|
893
|
+
initialize(datalyr: any): void;
|
|
894
|
+
page?(properties: PageProperties): void;
|
|
895
|
+
track?(eventName: string, properties: EventProperties): void;
|
|
896
|
+
identify?(userId: string, traits: UserTraits): void;
|
|
897
|
+
loaded?(): void;
|
|
898
|
+
}
|
|
899
|
+
```
|
|
900
|
+
|
|
603
901
|
---
|
|
604
902
|
|
|
605
903
|
## Troubleshooting
|
|
606
904
|
|
|
607
905
|
### Events not appearing
|
|
608
906
|
|
|
609
|
-
1.
|
|
610
|
-
2.
|
|
611
|
-
3.
|
|
612
|
-
4. Check Network tab for requests to `ingest.datalyr.com
|
|
613
|
-
5. Disable ad blockers
|
|
907
|
+
1. Verify `workspaceId` is correct.
|
|
908
|
+
2. Set `debug: true` and check the console.
|
|
909
|
+
3. Confirm `datalyr.getAnonymousId()` returns a value.
|
|
910
|
+
4. Check the Network tab for requests to `ingest.datalyr.com`.
|
|
911
|
+
5. Disable ad blockers or privacy extensions.
|
|
614
912
|
|
|
615
913
|
### SDK not initialized
|
|
616
914
|
|
|
617
915
|
```javascript
|
|
618
|
-
// Check initialization
|
|
619
916
|
console.log('Anonymous ID:', datalyr.getAnonymousId());
|
|
620
917
|
console.log('Session ID:', datalyr.getSessionId());
|
|
918
|
+
console.log('User ID:', datalyr.getUserId());
|
|
919
|
+
console.log('Network:', datalyr.getNetworkStatus());
|
|
621
920
|
console.log('Errors:', datalyr.getErrors());
|
|
622
921
|
```
|
|
623
922
|
|
|
624
|
-
If these return `undefined`, the SDK
|
|
923
|
+
If these return `undefined`, the SDK is not initialized. Call `datalyr.init()` first.
|
|
924
|
+
|
|
925
|
+
### Async initialization
|
|
926
|
+
|
|
927
|
+
`init()` returns synchronously, but encryption and container loading happen asynchronously. If you need to ensure everything is ready before tracking:
|
|
928
|
+
|
|
929
|
+
```javascript
|
|
930
|
+
datalyr.init({ workspaceId: '...' });
|
|
931
|
+
await datalyr.ready();
|
|
932
|
+
datalyr.track('post_init_event');
|
|
933
|
+
```
|
|
625
934
|
|
|
626
|
-
### Next.js SSR
|
|
935
|
+
### Next.js SSR
|
|
627
936
|
|
|
628
|
-
|
|
937
|
+
SDK methods only work in the browser. Always call them inside `useEffect` or other client-side hooks:
|
|
629
938
|
|
|
630
939
|
```jsx
|
|
631
940
|
'use client';
|
|
632
|
-
|
|
633
941
|
import { useEffect } from 'react';
|
|
634
942
|
import datalyr from '@datalyr/web';
|
|
635
943
|
|
|
636
944
|
useEffect(() => {
|
|
637
|
-
// SDK methods only work in browser
|
|
638
945
|
datalyr.init({ workspaceId: '...' });
|
|
639
946
|
}, []);
|
|
640
947
|
```
|
|
641
948
|
|
|
642
949
|
### Script tag vs NPM
|
|
643
950
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
| Feature | Script Tag | NPM |
|
|
647
|
-
|---------|-----------|-----|
|
|
648
|
-
| Bundle Size | 0 (external) | ~15KB |
|
|
649
|
-
| TypeScript | No | Yes |
|
|
650
|
-
| Access | `window.datalyr` | `import datalyr` |
|
|
651
|
-
| Initialize | Automatic | `datalyr.init()` |
|
|
951
|
+
Use one installation method, not both. Using both creates duplicate instances.
|
|
652
952
|
|
|
653
953
|
---
|
|
654
954
|
|