@datalyr/web 1.3.0 → 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 +578 -323
- package/dist/datalyr.cjs.js +6 -4
- package/dist/datalyr.cjs.js.map +1 -1
- package/dist/datalyr.esm.js +6 -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 +6 -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 +3 -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,27 +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
|
-
- [
|
|
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
22
|
- [Web-to-App Attribution](#web-to-app-attribution)
|
|
23
|
-
- [Event Queue](#event-queue)
|
|
24
|
-
- [Offline Support](#offline-support)
|
|
25
|
-
- [Privacy and Consent](#privacy-and-consent)
|
|
26
23
|
- [SPA Support](#spa-support)
|
|
27
|
-
- [Container Scripts](#container-scripts)
|
|
28
24
|
- [Framework Integration](#framework-integration)
|
|
29
|
-
- [React](#react)
|
|
30
|
-
- [Vue](#vue)
|
|
31
|
-
- [Next.js](#nextjs)
|
|
32
25
|
- [TypeScript](#typescript)
|
|
33
26
|
- [Troubleshooting](#troubleshooting)
|
|
34
27
|
- [License](#license)
|
|
@@ -37,7 +30,7 @@ Browser analytics and attribution SDK for web applications. Track events, identi
|
|
|
37
30
|
|
|
38
31
|
## Installation
|
|
39
32
|
|
|
40
|
-
### NPM
|
|
33
|
+
### NPM
|
|
41
34
|
|
|
42
35
|
```bash
|
|
43
36
|
npm install @datalyr/web
|
|
@@ -50,7 +43,16 @@ npm install @datalyr/web
|
|
|
50
43
|
data-workspace-id="YOUR_WORKSPACE_ID"></script>
|
|
51
44
|
```
|
|
52
45
|
|
|
53
|
-
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()` |
|
|
54
56
|
|
|
55
57
|
---
|
|
56
58
|
|
|
@@ -59,34 +61,32 @@ The script tag loads externally (zero bundle size) and auto-initializes. Use `wi
|
|
|
59
61
|
```javascript
|
|
60
62
|
import datalyr from '@datalyr/web';
|
|
61
63
|
|
|
62
|
-
// Initialize
|
|
63
64
|
datalyr.init({
|
|
64
65
|
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
65
66
|
});
|
|
66
67
|
|
|
68
|
+
// Wait for async initialization (encryption, container, initial page view)
|
|
69
|
+
await datalyr.ready();
|
|
70
|
+
|
|
67
71
|
// Track events
|
|
68
72
|
datalyr.track('button_clicked', { button: 'signup' });
|
|
69
73
|
|
|
70
74
|
// Identify users
|
|
71
75
|
datalyr.identify('user_123', { email: 'user@example.com' });
|
|
72
76
|
|
|
73
|
-
// Track page views
|
|
74
|
-
datalyr.page('Pricing',
|
|
77
|
+
// Track page views (page name goes in properties)
|
|
78
|
+
datalyr.page({ title: 'Pricing', variant: 'A' });
|
|
75
79
|
```
|
|
76
80
|
|
|
77
81
|
---
|
|
78
82
|
|
|
79
83
|
## How It Works
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
2. Each event includes device info, session data, and attribution parameters
|
|
87
|
-
3. Events are queued locally and sent in batches
|
|
88
|
-
4. If offline, events are stored and sent when connectivity returns
|
|
89
|
-
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.
|
|
90
90
|
|
|
91
91
|
### Event Payload
|
|
92
92
|
|
|
@@ -94,25 +94,30 @@ Every event includes:
|
|
|
94
94
|
|
|
95
95
|
```javascript
|
|
96
96
|
{
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
event_name: 'purchase',
|
|
98
|
+
event_data: { ... }, // Custom + attribution + session properties
|
|
99
99
|
|
|
100
100
|
// Identity
|
|
101
|
-
anonymous_id: 'anon_xxxxx',
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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',
|
|
108
109
|
referrer: 'https://google.com',
|
|
109
110
|
|
|
110
|
-
// Attribution (if captured)
|
|
111
|
+
// Attribution (in event_data, if captured)
|
|
111
112
|
utm_source: 'facebook',
|
|
112
113
|
fbclid: 'abc123',
|
|
113
114
|
|
|
114
|
-
//
|
|
115
|
+
// Metadata
|
|
116
|
+
workspace_id: 'wk_xxxxx',
|
|
117
|
+
source: 'web',
|
|
115
118
|
timestamp: '2024-01-15T10:30:00Z',
|
|
119
|
+
sdk_version: '1.4.0',
|
|
120
|
+
sdk_name: 'datalyr-web-sdk'
|
|
116
121
|
}
|
|
117
122
|
```
|
|
118
123
|
|
|
@@ -120,53 +125,94 @@ Every event includes:
|
|
|
120
125
|
|
|
121
126
|
## Configuration
|
|
122
127
|
|
|
123
|
-
|
|
128
|
+
All properties of `DatalyrConfig`:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
124
131
|
datalyr.init({
|
|
125
132
|
// Required
|
|
126
133
|
workspaceId: string,
|
|
127
134
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
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
|
|
132
138
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
flushInterval?: number, // Send interval ms (default: 5000)
|
|
139
|
+
// Debugging
|
|
140
|
+
debug?: boolean, // Default: false - Enable console logging
|
|
136
141
|
|
|
137
|
-
//
|
|
138
|
-
|
|
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
|
|
139
146
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
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.
|
|
144
150
|
|
|
145
|
-
//
|
|
146
|
-
|
|
151
|
+
// Session
|
|
152
|
+
sessionTimeout?: number, // Default: 3600000 (60 min)
|
|
153
|
+
trackSessions?: boolean, // Default: true
|
|
147
154
|
|
|
148
|
-
//
|
|
149
|
-
|
|
155
|
+
// Attribution
|
|
156
|
+
attributionWindow?: number, // Default: 7776000000 (90 days)
|
|
157
|
+
trackedParams?: string[], // Default: [] - Additional URL params to capture
|
|
150
158
|
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
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
|
|
154
196
|
});
|
|
155
197
|
```
|
|
156
198
|
|
|
157
199
|
---
|
|
158
200
|
|
|
159
|
-
##
|
|
201
|
+
## API Reference
|
|
160
202
|
|
|
161
|
-
###
|
|
203
|
+
### Event Tracking
|
|
162
204
|
|
|
163
|
-
|
|
205
|
+
#### `track(eventName, properties?)`
|
|
206
|
+
|
|
207
|
+
Track a custom event.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
track(eventName: string, properties?: EventProperties): void
|
|
211
|
+
```
|
|
164
212
|
|
|
165
213
|
```javascript
|
|
166
|
-
// Simple event
|
|
167
214
|
datalyr.track('signup_started');
|
|
168
215
|
|
|
169
|
-
// Event with properties
|
|
170
216
|
datalyr.track('product_viewed', {
|
|
171
217
|
product_id: 'SKU123',
|
|
172
218
|
product_name: 'Blue Shirt',
|
|
@@ -174,366 +220,549 @@ datalyr.track('product_viewed', {
|
|
|
174
220
|
currency: 'USD',
|
|
175
221
|
category: 'Apparel',
|
|
176
222
|
});
|
|
177
|
-
|
|
178
|
-
// Event with value
|
|
179
|
-
datalyr.track('level_completed', {
|
|
180
|
-
level: 5,
|
|
181
|
-
score: 1250,
|
|
182
|
-
time_seconds: 120,
|
|
183
|
-
});
|
|
184
223
|
```
|
|
185
224
|
|
|
186
|
-
|
|
225
|
+
#### `page(properties?)`
|
|
187
226
|
|
|
188
|
-
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
|
+
```
|
|
189
232
|
|
|
190
233
|
```javascript
|
|
191
|
-
// Track current page
|
|
234
|
+
// Track current page (all properties auto-captured)
|
|
192
235
|
datalyr.page();
|
|
193
236
|
|
|
194
|
-
//
|
|
195
|
-
datalyr.page('Pricing');
|
|
237
|
+
// Override title, add custom properties
|
|
238
|
+
datalyr.page({ title: 'Pricing', variant: 'A' });
|
|
196
239
|
|
|
197
|
-
//
|
|
198
|
-
datalyr.page(
|
|
199
|
-
product_id: 'SKU123',
|
|
200
|
-
source: 'search',
|
|
201
|
-
});
|
|
240
|
+
// Add custom properties
|
|
241
|
+
datalyr.page({ product_id: 'SKU123', source: 'search' });
|
|
202
242
|
```
|
|
203
243
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Standard e-commerce tracking:
|
|
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.
|
|
207
245
|
|
|
208
|
-
|
|
209
|
-
// View product
|
|
210
|
-
datalyr.track('Product Viewed', {
|
|
211
|
-
product_id: 'SKU123',
|
|
212
|
-
product_name: 'Blue Shirt',
|
|
213
|
-
price: 29.99,
|
|
214
|
-
currency: 'USD'
|
|
215
|
-
});
|
|
246
|
+
#### `screen(screenName, properties?)`
|
|
216
247
|
|
|
217
|
-
|
|
218
|
-
datalyr.track('Add to Cart', {
|
|
219
|
-
product_id: 'SKU123',
|
|
220
|
-
quantity: 1,
|
|
221
|
-
price: 29.99
|
|
222
|
-
});
|
|
248
|
+
Track a screen view. Intended for SPAs or hybrid apps.
|
|
223
249
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
currency: 'USD',
|
|
228
|
-
item_count: 2
|
|
229
|
-
});
|
|
250
|
+
```typescript
|
|
251
|
+
screen(screenName: string, properties?: Record<string, any>): void
|
|
252
|
+
```
|
|
230
253
|
|
|
231
|
-
|
|
232
|
-
datalyr.
|
|
233
|
-
|
|
234
|
-
total: 59.98,
|
|
235
|
-
currency: 'USD',
|
|
236
|
-
items: [
|
|
237
|
-
{ product_id: 'SKU123', quantity: 2, price: 29.99 }
|
|
238
|
-
]
|
|
239
|
-
});
|
|
254
|
+
```javascript
|
|
255
|
+
datalyr.screen('Dashboard');
|
|
256
|
+
datalyr.screen('Product Details', { product_id: 'SKU123' });
|
|
240
257
|
```
|
|
241
258
|
|
|
242
|
-
|
|
259
|
+
Internally fires a `pageview` event with the `screen` property set.
|
|
243
260
|
|
|
244
|
-
|
|
261
|
+
#### `trackAppDownloadClick(options)`
|
|
245
262
|
|
|
246
|
-
|
|
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.
|
|
247
264
|
|
|
248
|
-
|
|
265
|
+
```typescript
|
|
266
|
+
trackAppDownloadClick(options: {
|
|
267
|
+
targetPlatform: 'ios' | 'android';
|
|
268
|
+
appStoreUrl: string;
|
|
269
|
+
}): void
|
|
270
|
+
```
|
|
249
271
|
|
|
250
272
|
```javascript
|
|
251
|
-
|
|
252
|
-
|
|
273
|
+
datalyr.trackAppDownloadClick({
|
|
274
|
+
targetPlatform: 'ios',
|
|
275
|
+
appStoreUrl: 'https://apps.apple.com/app/your-app/id123456789',
|
|
276
|
+
});
|
|
253
277
|
```
|
|
254
278
|
|
|
255
|
-
|
|
256
|
-
- Persists across browser sessions
|
|
257
|
-
- Links events before and after user identification
|
|
258
|
-
- Can be passed to your backend for server-side attribution
|
|
259
|
-
|
|
260
|
-
### Identifying Users
|
|
279
|
+
For Android Play Store URLs, attribution parameters are automatically encoded into the `referrer` query parameter for deterministic install attribution.
|
|
261
280
|
|
|
262
|
-
|
|
281
|
+
---
|
|
263
282
|
|
|
264
|
-
|
|
265
|
-
datalyr.identify('user_123', {
|
|
266
|
-
email: 'user@example.com',
|
|
267
|
-
});
|
|
268
|
-
```
|
|
283
|
+
### User Identity
|
|
269
284
|
|
|
270
|
-
|
|
271
|
-
- All future events include `user_id`
|
|
272
|
-
- Historical anonymous events can be linked server-side
|
|
273
|
-
- Attribution data is preserved on the user
|
|
285
|
+
#### `identify(userId, traits?)`
|
|
274
286
|
|
|
275
|
-
|
|
287
|
+
Link the anonymous visitor to a known user. Rotates the session ID on call (prevents session fixation). User traits are encrypted at rest.
|
|
276
288
|
|
|
277
|
-
|
|
289
|
+
```typescript
|
|
290
|
+
identify(userId: string, traits?: UserTraits): void
|
|
291
|
+
```
|
|
278
292
|
|
|
279
293
|
```javascript
|
|
280
294
|
datalyr.identify('user_123', {
|
|
281
|
-
// Standard fields
|
|
282
295
|
email: 'user@example.com',
|
|
283
296
|
name: 'John Doe',
|
|
284
|
-
phone: '+1234567890',
|
|
285
|
-
|
|
286
|
-
// Custom fields
|
|
287
297
|
plan: 'premium',
|
|
288
298
|
company: 'Acme Inc',
|
|
289
|
-
signup_date: '2024-01-15',
|
|
290
299
|
});
|
|
291
300
|
```
|
|
292
301
|
|
|
293
|
-
|
|
302
|
+
#### `alias(userId, previousId?)`
|
|
294
303
|
|
|
295
|
-
|
|
304
|
+
Create an alias linking one user ID to another. If `previousId` is omitted, the current anonymous ID is used.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
alias(userId: string, previousId?: string): void
|
|
308
|
+
```
|
|
296
309
|
|
|
297
310
|
```javascript
|
|
298
|
-
datalyr.
|
|
311
|
+
datalyr.alias('user_123', 'temp_user_456');
|
|
299
312
|
```
|
|
300
313
|
|
|
301
|
-
|
|
302
|
-
- Clears the user ID
|
|
303
|
-
- Starts a new session
|
|
304
|
-
- Keeps the anonymous ID (same browser)
|
|
314
|
+
#### `group(groupId, traits?)`
|
|
305
315
|
|
|
306
|
-
|
|
316
|
+
Associate the current user with a group or account.
|
|
307
317
|
|
|
308
|
-
|
|
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' });
|
|
324
|
+
```
|
|
309
325
|
|
|
310
|
-
|
|
326
|
+
#### `reset()`
|
|
311
327
|
|
|
312
|
-
|
|
328
|
+
Clear user identity and start a new session. The anonymous ID is preserved.
|
|
313
329
|
|
|
314
330
|
```javascript
|
|
315
|
-
|
|
331
|
+
datalyr.reset();
|
|
316
332
|
```
|
|
317
333
|
|
|
318
|
-
|
|
334
|
+
#### `getAnonymousId()`
|
|
319
335
|
|
|
320
|
-
|
|
321
|
-
|------|------------|
|
|
322
|
-
| UTM | `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term` |
|
|
323
|
-
| Click IDs | `fbclid`, `gclid`, `ttclid`, `twclid`, `li_fat_id`, `msclkid` |
|
|
324
|
-
| Referrer | `referrer`, `landing_page` |
|
|
336
|
+
Returns the persistent anonymous ID assigned on first visit.
|
|
325
337
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
- Customer journey tracking (up to 30 touchpoints)
|
|
338
|
+
```typescript
|
|
339
|
+
getAnonymousId(): string
|
|
340
|
+
```
|
|
330
341
|
|
|
331
|
-
|
|
342
|
+
#### `getUserId()`
|
|
332
343
|
|
|
333
|
-
|
|
344
|
+
Returns the current user ID set by `identify()`, or `null` if not identified.
|
|
334
345
|
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
|
340
356
|
```
|
|
341
357
|
|
|
342
358
|
---
|
|
343
359
|
|
|
344
|
-
|
|
360
|
+
### Session
|
|
345
361
|
|
|
346
|
-
|
|
362
|
+
#### `getSessionId()`
|
|
347
363
|
|
|
348
|
-
|
|
364
|
+
Returns the current session ID.
|
|
349
365
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
4. First app open → mobile SDK recovers the web attribution:
|
|
354
|
-
- **Android**: Deterministic match via Play Store `referrer` URL parameter (~95% accuracy)
|
|
355
|
-
- **iOS**: IP-based match against recent web events within 24 hours (~90%+ accuracy)
|
|
366
|
+
```typescript
|
|
367
|
+
getSessionId(): string
|
|
368
|
+
```
|
|
356
369
|
|
|
357
|
-
|
|
370
|
+
#### `startNewSession()`
|
|
371
|
+
|
|
372
|
+
Force-start a new session. Returns the new session ID.
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
startNewSession(): string
|
|
376
|
+
```
|
|
358
377
|
|
|
359
378
|
```javascript
|
|
360
|
-
|
|
361
|
-
document.querySelector('#download-btn').addEventListener('click', () => {
|
|
362
|
-
datalyr.trackAppDownloadClick({
|
|
363
|
-
targetPlatform: 'ios', // or 'android'
|
|
364
|
-
appStoreUrl: 'https://apps.apple.com/app/your-app/id123456789',
|
|
365
|
-
});
|
|
366
|
-
});
|
|
379
|
+
const newSessionId = datalyr.startNewSession();
|
|
367
380
|
```
|
|
368
381
|
|
|
369
|
-
|
|
382
|
+
#### `getSessionData()`
|
|
370
383
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
});
|
|
384
|
+
Returns the current session metadata, or `null` if no active session.
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
getSessionData(): SessionData | null
|
|
376
388
|
```
|
|
377
389
|
|
|
378
|
-
|
|
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
|
+
```
|
|
379
401
|
|
|
380
|
-
|
|
402
|
+
#### `ready()`
|
|
381
403
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
+
```
|
|
385
415
|
|
|
386
416
|
---
|
|
387
417
|
|
|
388
|
-
|
|
418
|
+
### Attribution
|
|
389
419
|
|
|
390
|
-
|
|
420
|
+
#### `getAttribution()`
|
|
391
421
|
|
|
392
|
-
|
|
422
|
+
Returns the current captured attribution data.
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
getAttribution(): Attribution
|
|
426
|
+
```
|
|
393
427
|
|
|
394
428
|
```javascript
|
|
395
|
-
datalyr.
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
429
|
+
const attribution = datalyr.getAttribution();
|
|
430
|
+
console.log(attribution.source, attribution.medium, attribution.campaign);
|
|
431
|
+
```
|
|
432
|
+
|
|
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
|
+
}
|
|
400
449
|
```
|
|
401
450
|
|
|
402
|
-
|
|
451
|
+
Captured automatically from URLs:
|
|
452
|
+
|
|
453
|
+
| Type | Parameters |
|
|
454
|
+
|------|------------|
|
|
455
|
+
| UTM | `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`, `utm_term` |
|
|
456
|
+
| Click IDs | `fbclid`, `gclid`, `ttclid`, `twclid`, `li_fat_id`, `msclkid` |
|
|
457
|
+
| Referrer | `referrer`, `landing_page` |
|
|
458
|
+
|
|
459
|
+
Attribution supports first-touch (90-day window), last-touch, and journey tracking.
|
|
403
460
|
|
|
404
|
-
|
|
461
|
+
#### `setAttribution(attribution)`
|
|
462
|
+
|
|
463
|
+
Manually set or override attribution data.
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
setAttribution(attribution: Partial<Attribution>): void
|
|
467
|
+
```
|
|
405
468
|
|
|
406
469
|
```javascript
|
|
407
|
-
|
|
470
|
+
datalyr.setAttribution({
|
|
471
|
+
source: 'partner',
|
|
472
|
+
medium: 'referral',
|
|
473
|
+
campaign: 'spring_promo',
|
|
474
|
+
});
|
|
408
475
|
```
|
|
409
476
|
|
|
410
|
-
|
|
477
|
+
#### `getJourney()`
|
|
478
|
+
|
|
479
|
+
Returns the customer journey as an array of touchpoints (up to 30).
|
|
411
480
|
|
|
412
|
-
|
|
481
|
+
```typescript
|
|
482
|
+
getJourney(): TouchPoint[]
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
interface TouchPoint {
|
|
487
|
+
timestamp: number;
|
|
488
|
+
source?: string;
|
|
489
|
+
medium?: string;
|
|
490
|
+
campaign?: string;
|
|
491
|
+
sessionId: string;
|
|
492
|
+
}
|
|
493
|
+
```
|
|
413
494
|
|
|
414
495
|
---
|
|
415
496
|
|
|
416
|
-
|
|
497
|
+
### Super Properties
|
|
498
|
+
|
|
499
|
+
Super properties are included with every subsequent event.
|
|
500
|
+
|
|
501
|
+
#### `setSuperProperties(properties)`
|
|
417
502
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
503
|
+
Merge properties into the super properties store.
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
setSuperProperties(properties: Record<string, any>): void
|
|
507
|
+
```
|
|
422
508
|
|
|
423
509
|
```javascript
|
|
424
|
-
|
|
425
|
-
|
|
510
|
+
datalyr.setSuperProperties({ app_version: '2.1.0', environment: 'production' });
|
|
511
|
+
```
|
|
426
512
|
|
|
427
|
-
|
|
428
|
-
|
|
513
|
+
#### `unsetSuperProperty(propertyName)`
|
|
514
|
+
|
|
515
|
+
Remove a single super property by key.
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
unsetSuperProperty(propertyName: string): void
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
datalyr.unsetSuperProperty('environment');
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
#### `getSuperProperties()`
|
|
526
|
+
|
|
527
|
+
Returns a copy of the current super properties.
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
getSuperProperties(): Record<string, any>
|
|
429
531
|
```
|
|
430
532
|
|
|
431
533
|
---
|
|
432
534
|
|
|
433
|
-
|
|
535
|
+
### Privacy and Consent
|
|
434
536
|
|
|
435
|
-
|
|
537
|
+
#### `optOut()`
|
|
538
|
+
|
|
539
|
+
Opt the user out of all tracking. Clears the event queue and persists the preference in a cookie.
|
|
436
540
|
|
|
437
541
|
```javascript
|
|
438
|
-
// Opt user out of tracking
|
|
439
542
|
datalyr.optOut();
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
#### `optIn()`
|
|
440
546
|
|
|
441
|
-
|
|
547
|
+
Opt the user back in.
|
|
548
|
+
|
|
549
|
+
```javascript
|
|
442
550
|
datalyr.optIn();
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
#### `isOptedOut()`
|
|
554
|
+
|
|
555
|
+
Returns `true` if the user has opted out.
|
|
443
556
|
|
|
444
|
-
|
|
445
|
-
|
|
557
|
+
```typescript
|
|
558
|
+
isOptedOut(): boolean
|
|
446
559
|
```
|
|
447
560
|
|
|
448
|
-
|
|
561
|
+
#### `setConsent(consent)`
|
|
562
|
+
|
|
563
|
+
Set granular consent preferences.
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
setConsent(consent: ConsentConfig): void
|
|
567
|
+
```
|
|
449
568
|
|
|
450
569
|
```javascript
|
|
451
570
|
datalyr.setConsent({
|
|
452
571
|
analytics: true,
|
|
453
572
|
marketing: false,
|
|
454
573
|
preferences: true,
|
|
455
|
-
sale: false
|
|
574
|
+
sale: false // CCPA "Do Not Sell"
|
|
456
575
|
});
|
|
457
576
|
```
|
|
458
577
|
|
|
459
|
-
|
|
578
|
+
```typescript
|
|
579
|
+
interface ConsentConfig {
|
|
580
|
+
analytics?: boolean;
|
|
581
|
+
marketing?: boolean;
|
|
582
|
+
preferences?: boolean;
|
|
583
|
+
sale?: boolean;
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
#### Privacy Modes
|
|
460
588
|
|
|
461
589
|
```javascript
|
|
462
|
-
// Standard mode (default)
|
|
463
|
-
datalyr.init({
|
|
464
|
-
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
465
|
-
privacyMode: 'standard'
|
|
466
|
-
});
|
|
590
|
+
// Standard mode (default) - normal fingerprinting + tracking
|
|
591
|
+
datalyr.init({ workspaceId: '...', privacyMode: 'standard' });
|
|
467
592
|
|
|
468
|
-
// Strict mode - minimal data collection
|
|
469
|
-
datalyr.init({
|
|
470
|
-
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
471
|
-
privacyMode: 'strict'
|
|
472
|
-
});
|
|
593
|
+
// Strict mode - minimal data collection, no fingerprinting
|
|
594
|
+
datalyr.init({ workspaceId: '...', privacyMode: 'strict' });
|
|
473
595
|
```
|
|
474
596
|
|
|
597
|
+
The SDK also respects `respectDoNotTrack` and `respectGlobalPrivacyControl` config flags.
|
|
598
|
+
|
|
475
599
|
---
|
|
476
600
|
|
|
477
|
-
|
|
601
|
+
### Queue and Network
|
|
478
602
|
|
|
479
|
-
|
|
603
|
+
#### `flush()`
|
|
604
|
+
|
|
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
|
+
```
|
|
480
610
|
|
|
481
611
|
```javascript
|
|
482
|
-
datalyr.
|
|
483
|
-
|
|
484
|
-
trackSPA: true // Auto-track route changes (default: true)
|
|
485
|
-
});
|
|
612
|
+
await datalyr.flush();
|
|
613
|
+
```
|
|
486
614
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
615
|
+
#### `getNetworkStatus()`
|
|
616
|
+
|
|
617
|
+
Returns the current network status as tracked by the SDK.
|
|
618
|
+
|
|
619
|
+
```typescript
|
|
620
|
+
getNetworkStatus(): NetworkStatus
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
interface NetworkStatus {
|
|
625
|
+
isOnline: boolean;
|
|
626
|
+
lastOfflineAt: number | null;
|
|
627
|
+
lastOnlineAt: number | null;
|
|
628
|
+
}
|
|
491
629
|
```
|
|
492
630
|
|
|
631
|
+
Events are automatically stored when offline and sent when connectivity returns.
|
|
632
|
+
|
|
493
633
|
---
|
|
494
634
|
|
|
495
|
-
|
|
635
|
+
### Container Scripts
|
|
496
636
|
|
|
497
637
|
Container scripts manage third-party tracking pixels (Meta, Google, TikTok) configured in your Datalyr dashboard.
|
|
498
638
|
|
|
499
|
-
|
|
639
|
+
#### `loadScript(scriptId)`
|
|
640
|
+
|
|
641
|
+
Trigger a container script by ID.
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
loadScript(scriptId: string): void
|
|
645
|
+
```
|
|
500
646
|
|
|
501
|
-
|
|
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):
|
|
502
660
|
|
|
503
661
|
```html
|
|
504
662
|
<script defer src="https://track.datalyr.com/container.js"
|
|
505
663
|
data-workspace-id="YOUR_WORKSPACE_ID"></script>
|
|
506
664
|
```
|
|
507
665
|
|
|
508
|
-
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
### Debugging
|
|
509
669
|
|
|
510
|
-
|
|
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
|
+
```
|
|
511
687
|
|
|
512
688
|
```javascript
|
|
513
|
-
datalyr.
|
|
514
|
-
|
|
515
|
-
enableContainer: true // Default: true
|
|
516
|
-
});
|
|
689
|
+
console.log(datalyr.getErrors());
|
|
690
|
+
```
|
|
517
691
|
|
|
518
|
-
|
|
519
|
-
|
|
692
|
+
Enable `debug: true` in config to log all SDK activity to the console.
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
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
|
+
```
|
|
705
|
+
|
|
706
|
+
```javascript
|
|
707
|
+
datalyr.destroy();
|
|
708
|
+
```
|
|
709
|
+
|
|
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)
|
|
520
724
|
|
|
521
|
-
|
|
522
|
-
|
|
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
|
+
});
|
|
523
734
|
```
|
|
524
735
|
|
|
525
|
-
|
|
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
|
+
});
|
|
742
|
+
```
|
|
526
743
|
|
|
527
|
-
|
|
528
|
-
- Google Analytics / Google Ads
|
|
529
|
-
- TikTok Pixel
|
|
530
|
-
- Custom scripts and tracking pixels
|
|
744
|
+
### Requirements
|
|
531
745
|
|
|
532
|
-
|
|
533
|
-
-
|
|
534
|
-
-
|
|
535
|
-
|
|
536
|
-
|
|
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.
|
|
755
|
+
|
|
756
|
+
```javascript
|
|
757
|
+
datalyr.init({
|
|
758
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
759
|
+
trackSPA: true, // default
|
|
760
|
+
trackPageViews: true, // auto-track initial page view, default
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// Manual page tracking
|
|
764
|
+
datalyr.page({ title: 'Product Details', product_id: 'SKU-123' });
|
|
765
|
+
```
|
|
537
766
|
|
|
538
767
|
---
|
|
539
768
|
|
|
@@ -547,13 +776,11 @@ import datalyr from '@datalyr/web';
|
|
|
547
776
|
|
|
548
777
|
function App() {
|
|
549
778
|
useEffect(() => {
|
|
550
|
-
datalyr.init({
|
|
551
|
-
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
552
|
-
});
|
|
779
|
+
datalyr.init({ workspaceId: 'YOUR_WORKSPACE_ID' });
|
|
553
780
|
}, []);
|
|
554
781
|
|
|
555
782
|
const handleClick = () => {
|
|
556
|
-
datalyr.track('
|
|
783
|
+
datalyr.track('button_clicked', { button_name: 'CTA' });
|
|
557
784
|
};
|
|
558
785
|
|
|
559
786
|
return <button onClick={handleClick}>Click Me</button>;
|
|
@@ -568,13 +795,11 @@ import { onMounted } from 'vue';
|
|
|
568
795
|
import datalyr from '@datalyr/web';
|
|
569
796
|
|
|
570
797
|
onMounted(() => {
|
|
571
|
-
datalyr.init({
|
|
572
|
-
workspaceId: 'YOUR_WORKSPACE_ID'
|
|
573
|
-
});
|
|
798
|
+
datalyr.init({ workspaceId: 'YOUR_WORKSPACE_ID' });
|
|
574
799
|
});
|
|
575
800
|
|
|
576
801
|
const trackClick = () => {
|
|
577
|
-
datalyr.track('
|
|
802
|
+
datalyr.track('button_clicked');
|
|
578
803
|
};
|
|
579
804
|
</script>
|
|
580
805
|
|
|
@@ -585,34 +810,32 @@ const trackClick = () => {
|
|
|
585
810
|
|
|
586
811
|
### Next.js
|
|
587
812
|
|
|
588
|
-
```
|
|
813
|
+
```tsx
|
|
589
814
|
// app/providers.tsx
|
|
590
815
|
'use client';
|
|
591
816
|
|
|
592
817
|
import { useEffect } from 'react';
|
|
593
818
|
import datalyr from '@datalyr/web';
|
|
594
819
|
|
|
595
|
-
export function AnalyticsProvider({ children }) {
|
|
820
|
+
export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
|
|
596
821
|
useEffect(() => {
|
|
597
822
|
datalyr.init({
|
|
598
|
-
workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID
|
|
599
|
-
debug: process.env.NODE_ENV === 'development'
|
|
823
|
+
workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
|
|
824
|
+
debug: process.env.NODE_ENV === 'development',
|
|
600
825
|
});
|
|
601
826
|
}, []);
|
|
602
827
|
|
|
603
|
-
return children
|
|
828
|
+
return <>{children}</>;
|
|
604
829
|
}
|
|
605
830
|
|
|
606
831
|
// app/layout.tsx
|
|
607
832
|
import { AnalyticsProvider } from './providers';
|
|
608
833
|
|
|
609
|
-
export default function RootLayout({ children }) {
|
|
834
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
610
835
|
return (
|
|
611
836
|
<html>
|
|
612
837
|
<body>
|
|
613
|
-
<AnalyticsProvider>
|
|
614
|
-
{children}
|
|
615
|
-
</AnalyticsProvider>
|
|
838
|
+
<AnalyticsProvider>{children}</AnalyticsProvider>
|
|
616
839
|
</body>
|
|
617
840
|
</html>
|
|
618
841
|
);
|
|
@@ -623,77 +846,109 @@ export default function RootLayout({ children }) {
|
|
|
623
846
|
|
|
624
847
|
## TypeScript
|
|
625
848
|
|
|
849
|
+
All types are exported from the package:
|
|
850
|
+
|
|
626
851
|
```typescript
|
|
627
|
-
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
|
+
```
|
|
628
871
|
|
|
629
|
-
|
|
872
|
+
```typescript
|
|
630
873
|
const properties: EventProperties = {
|
|
631
874
|
product_id: 'SKU-123',
|
|
632
875
|
price: 99.99,
|
|
633
|
-
quantity: 2
|
|
876
|
+
quantity: 2,
|
|
634
877
|
};
|
|
878
|
+
datalyr.track('product_added', properties);
|
|
635
879
|
|
|
636
|
-
datalyr.track('Product Added', properties);
|
|
637
|
-
|
|
638
|
-
// Type-safe user traits
|
|
639
880
|
const traits: UserTraits = {
|
|
640
881
|
email: 'user@example.com',
|
|
641
882
|
name: 'John Doe',
|
|
642
|
-
plan: 'premium'
|
|
883
|
+
plan: 'premium',
|
|
643
884
|
};
|
|
644
|
-
|
|
645
885
|
datalyr.identify('user_123', traits);
|
|
646
886
|
```
|
|
647
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
|
+
|
|
648
901
|
---
|
|
649
902
|
|
|
650
903
|
## Troubleshooting
|
|
651
904
|
|
|
652
905
|
### Events not appearing
|
|
653
906
|
|
|
654
|
-
1.
|
|
655
|
-
2.
|
|
656
|
-
3.
|
|
657
|
-
4. Check Network tab for requests to `ingest.datalyr.com
|
|
658
|
-
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.
|
|
659
912
|
|
|
660
913
|
### SDK not initialized
|
|
661
914
|
|
|
662
915
|
```javascript
|
|
663
|
-
// Check initialization
|
|
664
916
|
console.log('Anonymous ID:', datalyr.getAnonymousId());
|
|
665
917
|
console.log('Session ID:', datalyr.getSessionId());
|
|
918
|
+
console.log('User ID:', datalyr.getUserId());
|
|
919
|
+
console.log('Network:', datalyr.getNetworkStatus());
|
|
666
920
|
console.log('Errors:', datalyr.getErrors());
|
|
667
921
|
```
|
|
668
922
|
|
|
669
|
-
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
|
+
```
|
|
670
934
|
|
|
671
|
-
### Next.js SSR
|
|
935
|
+
### Next.js SSR
|
|
672
936
|
|
|
673
|
-
|
|
937
|
+
SDK methods only work in the browser. Always call them inside `useEffect` or other client-side hooks:
|
|
674
938
|
|
|
675
939
|
```jsx
|
|
676
940
|
'use client';
|
|
677
|
-
|
|
678
941
|
import { useEffect } from 'react';
|
|
679
942
|
import datalyr from '@datalyr/web';
|
|
680
943
|
|
|
681
944
|
useEffect(() => {
|
|
682
|
-
// SDK methods only work in browser
|
|
683
945
|
datalyr.init({ workspaceId: '...' });
|
|
684
946
|
}, []);
|
|
685
947
|
```
|
|
686
948
|
|
|
687
949
|
### Script tag vs NPM
|
|
688
950
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
| Feature | Script Tag | NPM |
|
|
692
|
-
|---------|-----------|-----|
|
|
693
|
-
| Bundle Size | 0 (external) | ~15KB |
|
|
694
|
-
| TypeScript | No | Yes |
|
|
695
|
-
| Access | `window.datalyr` | `import datalyr` |
|
|
696
|
-
| Initialize | Automatic | `datalyr.init()` |
|
|
951
|
+
Use one installation method, not both. Using both creates duplicate instances.
|
|
697
952
|
|
|
698
953
|
---
|
|
699
954
|
|