@treasuredata/web-sdk 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 +202 -0
- package/NOTICE +8 -0
- package/README.md +807 -0
- package/dist/browser.d.ts +9 -0
- package/dist/checksums.txt +8 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.template.d.ts +10 -0
- package/dist/core/configurator.d.ts +35 -0
- package/dist/core/sdk.d.ts +3 -0
- package/dist/index.d.ts +37 -0
- package/dist/init.d.ts +18 -0
- package/dist/loader.d.ts +59 -0
- package/dist/loader.js +1 -0
- package/dist/loader.min.js +1 -0
- package/dist/plugins/clicks.d.ts +21 -0
- package/dist/plugins/conversion-api.d.ts +23 -0
- package/dist/plugins/global-id.d.ts +17 -0
- package/dist/plugins/in-browser-message.d.ts +6 -0
- package/dist/plugins/page-personalize/bridge/constants.d.ts +9 -0
- package/dist/plugins/page-personalize/bridge/rpc.d.ts +15 -0
- package/dist/plugins/page-personalize/index.d.ts +34 -0
- package/dist/plugins/page-personalize/injection/inject.d.ts +17 -0
- package/dist/plugins/page-personalize/modes/preview.d.ts +3 -0
- package/dist/plugins/page-personalize/modes/spot-selection.d.ts +9 -0
- package/dist/plugins/page-personalize/offers.d.ts +72 -0
- package/dist/plugins/page-personalize/router.d.ts +17 -0
- package/dist/plugins/page-personalize/types.d.ts +27 -0
- package/dist/plugins/page-personalize/utils/selector-generator.d.ts +6 -0
- package/dist/plugins/personalization.d.ts +39 -0
- package/dist/plugins/record.d.ts +32 -0
- package/dist/plugins/server-cookie.d.ts +14 -0
- package/dist/plugins/session.d.ts +25 -0
- package/dist/plugins/track.d.ts +16 -0
- package/dist/plugins/utm.d.ts +16 -0
- package/dist/td-sdk.cjs +3263 -0
- package/dist/td-sdk.esm.js +3263 -0
- package/dist/td-sdk.esm.min.js +1 -0
- package/dist/td-sdk.js +3176 -0
- package/dist/td-sdk.min.cjs +1 -0
- package/dist/td-sdk.min.js +1 -0
- package/dist/treasure.d.ts +198 -0
- package/dist/types/index.d.ts +177 -0
- package/dist/utils/element.d.ts +20 -0
- package/dist/utils/lodash.d.ts +18 -0
- package/dist/utils/misc.d.ts +17 -0
- package/dist/utils/set-cookie.d.ts +14 -0
- package/dist/utils/uuid.d.ts +14 -0
- package/dist/utils/xhr.d.ts +58 -0
- package/dist/vendor/js-cookies.d.ts +19 -0
- package/package.json +90 -0
package/README.md
ADDED
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
# Treasure Data Web SDK
|
|
2
|
+
|
|
3
|
+
Modern, TypeScript-first analytics SDK for browser event tracking with comprehensive type safety and plugin architecture.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Install
|
|
8
|
+
|
|
9
|
+
**NPM (Recommended)**
|
|
10
|
+
```bash
|
|
11
|
+
npm install @treasuredata/web-sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**CDN Script**
|
|
15
|
+
```html
|
|
16
|
+
<script type="text/javascript">
|
|
17
|
+
!function(t,e){if(void 0===e[t]){e[t]=function(){e[t].clients.push(this),this._init=[Array.prototype.slice.call(arguments)]},e[t].clients=[];for(var r=function(t){return function(){return this["_"+t]=this["_"+t]||[],this["_"+t].push(Array.prototype.slice.call(arguments)),this}},s=["set","collectTags","blockEvents","unblockEvents","setSignedMode","setAnonymousMode","fetchServerCookie","fetchGlobalID","fetchUserSegments","fetchPersonalization","resetUUID","addRecord","trackEvent","trackPageview","trackClicks","ready"],c=0;c<s.length;c++){var o=s[c];e[t].prototype[o]=r(o)}var n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=("https:"===document.location.protocol?"https:":"http:")+"//cdn.treasuredata.com/sdk/web/1.0/td-sdk.min.js";var i=document.getElementsByTagName("script")[0];i.parentNode.insertBefore(n,i)}}("Treasure",this);
|
|
18
|
+
</script>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### First Event
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// TypeScript
|
|
25
|
+
import Treasure from '@treasuredata/web-sdk'
|
|
26
|
+
|
|
27
|
+
const td = new Treasure({
|
|
28
|
+
writeKey: 'your-write-key',
|
|
29
|
+
database: 'your-database'
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Track your first event
|
|
33
|
+
td.trackEvent('user_actions', {
|
|
34
|
+
action: 'click',
|
|
35
|
+
button: 'signup'
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
// JavaScript (Node.js/CommonJS)
|
|
41
|
+
const Treasure = require('@treasuredata/web-sdk').default
|
|
42
|
+
|
|
43
|
+
// Or ES modules
|
|
44
|
+
import Treasure from '@treasuredata/web-sdk'
|
|
45
|
+
|
|
46
|
+
const td = new Treasure({
|
|
47
|
+
writeKey: 'your-write-key',
|
|
48
|
+
database: 'your-database'
|
|
49
|
+
})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Key Features
|
|
53
|
+
|
|
54
|
+
- **TypeScript-first**: Full type safety and IntelliSense support
|
|
55
|
+
- **Modern Architecture**: Composable plugin-based system
|
|
56
|
+
- **Privacy Compliance**: GDPR-ready with privacy controls
|
|
57
|
+
- **Automatic UTM Collection**: UTM parameters captured on init
|
|
58
|
+
- **Cross-device**: Global ID and server-side cookies for ITP compliance
|
|
59
|
+
- **Zero Dependencies**: Lightweight, self-contained
|
|
60
|
+
|
|
61
|
+
## Common Use Cases
|
|
62
|
+
|
|
63
|
+
### Page View Tracking
|
|
64
|
+
```javascript
|
|
65
|
+
// Track page view
|
|
66
|
+
td.trackPageview('pageviews')
|
|
67
|
+
|
|
68
|
+
// With success/error callbacks
|
|
69
|
+
td.trackPageview('pageviews',
|
|
70
|
+
(response) => console.log('Pageview tracked!'),
|
|
71
|
+
(error) => console.error('Failed:', error)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// With personalization: configure it once on the constructor. When set, every
|
|
75
|
+
// trackEvent/trackPageview call fetches personalization INSTEAD of ingesting the
|
|
76
|
+
// event (the call no longer records to your database — see below)
|
|
77
|
+
const td = new Treasure({
|
|
78
|
+
writeKey: 'your-write-key',
|
|
79
|
+
database: 'your-database',
|
|
80
|
+
personalization: {
|
|
81
|
+
endpoint: 'personalization.example.com',
|
|
82
|
+
token: 'personalization_token',
|
|
83
|
+
database: 'personalization_db' // optional; defaults to the main `database`
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// The personalization table comes from the tracking call ('pageviews' here),
|
|
88
|
+
// and the request payload is the event data (track values + globals + record)
|
|
89
|
+
td.trackPageview('pageviews',
|
|
90
|
+
(response) => console.log('Personalization fetched!'),
|
|
91
|
+
(error) => console.error('Failed:', error)
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Event Tracking
|
|
96
|
+
```javascript
|
|
97
|
+
// Basic event
|
|
98
|
+
td.trackEvent('events', {
|
|
99
|
+
event_type: 'purchase',
|
|
100
|
+
item_id: 'SKU-123',
|
|
101
|
+
revenue: 29.99
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// With success/error callbacks
|
|
105
|
+
td.trackEvent('button_clicks', { button: 'header_cta' },
|
|
106
|
+
(response) => console.log('Tracked!'),
|
|
107
|
+
(error) => console.error('Failed:', error)
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Global Properties
|
|
112
|
+
```javascript
|
|
113
|
+
// Set user properties for all events
|
|
114
|
+
td.set('$global', 'user_id', '12345')
|
|
115
|
+
td.set('$global', 'plan', 'premium')
|
|
116
|
+
|
|
117
|
+
// Set table-specific defaults
|
|
118
|
+
td.set('purchases', 'currency', 'USD')
|
|
119
|
+
|
|
120
|
+
// Multiple properties at once
|
|
121
|
+
td.set('$global', {
|
|
122
|
+
user_id: '12345',
|
|
123
|
+
plan: 'premium',
|
|
124
|
+
signup_date: '2024-01-15'
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Automatic Click Tracking
|
|
129
|
+
```javascript
|
|
130
|
+
// Track all clicks on buttons and links
|
|
131
|
+
td.trackClicks()
|
|
132
|
+
|
|
133
|
+
// Custom configuration
|
|
134
|
+
td.trackClicks({
|
|
135
|
+
tableName: 'ui_interactions',
|
|
136
|
+
element: document.getElementById('main-content')
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### UTM Parameter Collection
|
|
141
|
+
```javascript
|
|
142
|
+
// Collect UTM parameters from URL
|
|
143
|
+
const utmParams = td.collectUTMParameters()
|
|
144
|
+
console.log(utmParams) // { utm_source: 'google', utm_campaign: 'summer2024' }
|
|
145
|
+
|
|
146
|
+
// Get previously collected UTMs
|
|
147
|
+
const storedUtms = td.getUTMParameters()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Privacy & Consent Management
|
|
151
|
+
|
|
152
|
+
### Signed vs Anonymous Mode
|
|
153
|
+
```javascript
|
|
154
|
+
const td = new Treasure({
|
|
155
|
+
writeKey: 'key',
|
|
156
|
+
database: 'db',
|
|
157
|
+
startInSignedMode: false // Default: anonymous mode
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
// Anonymous mode (default) - no PII collected
|
|
161
|
+
td.setAnonymousMode()
|
|
162
|
+
td.trackEvent('events', { action: 'view' })
|
|
163
|
+
// Sends: { action: 'view', td_version: '1.0.0' }
|
|
164
|
+
// Omits: td_client_id, td_ip, td_global_id
|
|
165
|
+
|
|
166
|
+
// Signed mode - PII collection enabled
|
|
167
|
+
td.setSignedMode()
|
|
168
|
+
td.trackEvent('events', { action: 'purchase' })
|
|
169
|
+
// Sends: { action: 'purchase', td_client_id: 'uuid', td_ip: '192.168.1.1' }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Event Blocking
|
|
173
|
+
```javascript
|
|
174
|
+
// Temporarily block all events
|
|
175
|
+
td.blockEvents()
|
|
176
|
+
td.trackEvent('blocked', {}) // Not sent
|
|
177
|
+
|
|
178
|
+
// Resume tracking
|
|
179
|
+
td.unblockEvents()
|
|
180
|
+
td.trackEvent('tracked', {}) // Sent normally
|
|
181
|
+
|
|
182
|
+
// Check status
|
|
183
|
+
if (td.areEventsBlocked()) {
|
|
184
|
+
console.log('Tracking is currently blocked')
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Privacy Control Example
|
|
189
|
+
```javascript
|
|
190
|
+
const td = new Treasure({ writeKey: 'key', database: 'db' })
|
|
191
|
+
|
|
192
|
+
// Programmatically manage privacy based on user preferences
|
|
193
|
+
function handleUserPrivacyChoice(privacyLevel) {
|
|
194
|
+
switch (privacyLevel) {
|
|
195
|
+
case 'full_tracking':
|
|
196
|
+
td.unblockEvents()
|
|
197
|
+
td.setSignedMode()
|
|
198
|
+
break
|
|
199
|
+
case 'anonymous_only':
|
|
200
|
+
td.unblockEvents()
|
|
201
|
+
td.setAnonymousMode()
|
|
202
|
+
break
|
|
203
|
+
case 'no_tracking':
|
|
204
|
+
td.blockEvents()
|
|
205
|
+
break
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Example: User clicks privacy preference buttons
|
|
210
|
+
document.getElementById('accept-all').onclick = () => handleUserPrivacyChoice('full_tracking')
|
|
211
|
+
document.getElementById('essential-only').onclick = () => handleUserPrivacyChoice('anonymous_only')
|
|
212
|
+
document.getElementById('reject-all').onclick = () => handleUserPrivacyChoice('no_tracking')
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Advanced Features
|
|
216
|
+
|
|
217
|
+
### Global ID (Cross-device Tracking)
|
|
218
|
+
```javascript
|
|
219
|
+
// 1. Enable Global ID collection
|
|
220
|
+
td.set('$global', 'td_global_id', 'td_global_id')
|
|
221
|
+
|
|
222
|
+
// 2. Switch to signed mode
|
|
223
|
+
td.setSignedMode()
|
|
224
|
+
|
|
225
|
+
// 3. Fetch Global ID
|
|
226
|
+
td.fetchGlobalID(
|
|
227
|
+
(globalId) => {
|
|
228
|
+
console.log('Global ID:', globalId)
|
|
229
|
+
// Use for cross-device analytics
|
|
230
|
+
},
|
|
231
|
+
(error) => console.error('Failed to get Global ID:', error),
|
|
232
|
+
false, // forceFetch
|
|
233
|
+
{
|
|
234
|
+
domain: '.yourdomain.com',
|
|
235
|
+
secure: true,
|
|
236
|
+
sameSite: 'None'
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Server-Side Cookies (ITP Compliance)
|
|
242
|
+
```javascript
|
|
243
|
+
const td = new Treasure({
|
|
244
|
+
writeKey: 'key',
|
|
245
|
+
database: 'db',
|
|
246
|
+
useServerSideCookie: true,
|
|
247
|
+
sscDomain: 'yourdomain.com'
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
td.fetchServerCookie(
|
|
251
|
+
(serverId) => console.log('Server ID:', serverId),
|
|
252
|
+
(error) => console.error('Server cookie failed:', error)
|
|
253
|
+
)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### User Segmentation
|
|
257
|
+
```javascript
|
|
258
|
+
// Fetch user segments for personalization
|
|
259
|
+
td.fetchUserSegments(
|
|
260
|
+
'audience_token_abc123',
|
|
261
|
+
(segments) => {
|
|
262
|
+
segments.forEach(segment => {
|
|
263
|
+
console.log('Segment:', segment.values)
|
|
264
|
+
console.log('Attributes:', segment.attributes)
|
|
265
|
+
})
|
|
266
|
+
},
|
|
267
|
+
(error) => console.error('Segmentation failed:', error)
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
// With custom keys
|
|
271
|
+
td.fetchUserSegments({
|
|
272
|
+
audienceToken: ['token1', 'token2'],
|
|
273
|
+
keys: { user_id: '12345', email: 'user@example.com' }
|
|
274
|
+
}, successCallback, errorCallback)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Personalization & In-Browser Messaging
|
|
278
|
+
```javascript
|
|
279
|
+
// Manual personalization fetch
|
|
280
|
+
td.fetchPersonalization({
|
|
281
|
+
endpoint: 'personalization.example.com',
|
|
282
|
+
database: 'recommendations_db',
|
|
283
|
+
table: 'user_offers',
|
|
284
|
+
token: 'p13n_token_123'
|
|
285
|
+
}, {
|
|
286
|
+
user_id: '12345',
|
|
287
|
+
page_type: 'product_detail',
|
|
288
|
+
product_category: 'electronics'
|
|
289
|
+
}, (response) => {
|
|
290
|
+
console.log('Personalization response:', response)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
// Personalization driven by tracking calls
|
|
294
|
+
// Configure personalization once on the constructor...
|
|
295
|
+
const td = new Treasure({
|
|
296
|
+
writeKey: 'your-write-key',
|
|
297
|
+
database: 'your-database',
|
|
298
|
+
personalization: {
|
|
299
|
+
endpoint: 'personalization.example.com',
|
|
300
|
+
token: 'p13n_token_123',
|
|
301
|
+
database: 'recommendations_db' // optional; defaults to the main `database`
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
// ...then trackEvent and trackPageview fetch personalization instead of
|
|
306
|
+
// ingesting the event. The personalization table is the tracking call's table,
|
|
307
|
+
// and the request payload is the event data ($global + table defaults + track
|
|
308
|
+
// values + record) — not recorded to your database.
|
|
309
|
+
td.trackEvent('events', { action: 'view' })
|
|
310
|
+
td.trackPageview('pageviews',
|
|
311
|
+
(response) => console.log('Personalization fetched'),
|
|
312
|
+
(error) => console.error('Personalization failed')
|
|
313
|
+
)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Plugin Architecture
|
|
317
|
+
|
|
318
|
+
For advanced users who need custom plugin combinations:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
import {
|
|
322
|
+
createSDK,
|
|
323
|
+
session,
|
|
324
|
+
record,
|
|
325
|
+
track,
|
|
326
|
+
clicks,
|
|
327
|
+
utm,
|
|
328
|
+
globalId
|
|
329
|
+
} from '@treasuredata/web-sdk'
|
|
330
|
+
|
|
331
|
+
// Build custom SDK with only needed plugins
|
|
332
|
+
const sdk = createSDK({
|
|
333
|
+
writeKey: 'your-key',
|
|
334
|
+
database: 'your-db'
|
|
335
|
+
})
|
|
336
|
+
.use(session()) // Identity & consent management
|
|
337
|
+
.use(record()) // Core event submission
|
|
338
|
+
.use(track()) // Auto-tracked properties
|
|
339
|
+
.use(clicks()) // Click tracking (optional)
|
|
340
|
+
.use(utm()) // UTM collection (optional)
|
|
341
|
+
.use(globalId()) // Global ID (optional)
|
|
342
|
+
|
|
343
|
+
// Same API as the full Treasure constructor
|
|
344
|
+
sdk.trackEvent('events', { custom: 'data' })
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Automatic Data Collection
|
|
348
|
+
|
|
349
|
+
When using `trackEvent()` or `trackPageview()`, these properties are automatically included:
|
|
350
|
+
|
|
351
|
+
| Property | Description | Example |
|
|
352
|
+
|----------|-------------|---------|
|
|
353
|
+
| `td_version` | SDK version | `"1.0.0"` |
|
|
354
|
+
| `td_client_id` | Client UUID* | `"abc-123-def"` |
|
|
355
|
+
| `td_charset` | Page character set | `"utf-8"` |
|
|
356
|
+
| `td_language` | Browser language | `"en-us"` |
|
|
357
|
+
| `td_color` | Screen color depth | `"24-bit"` |
|
|
358
|
+
| `td_screen` | Screen resolution | `"1920x1080"` |
|
|
359
|
+
| `td_viewport` | Viewport size | `"1200x800"` |
|
|
360
|
+
| `td_title` | Page title | `"Home Page"` |
|
|
361
|
+
| `td_description` | Meta description | `"Welcome to..."` |
|
|
362
|
+
| `td_url` | Page URL | `"https://example.com/page"` |
|
|
363
|
+
| `td_user_agent` | User agent + SDK info | `"Mozilla/5.0...;WEBSDK/1.0.0"` |
|
|
364
|
+
| `td_platform` | Platform | `"MacIntel"` |
|
|
365
|
+
| `td_host` | Hostname | `"example.com"` |
|
|
366
|
+
| `td_path` | URL path | `"/products/123"` |
|
|
367
|
+
| `td_referrer` | Referrer URL | `"https://google.com"` |
|
|
368
|
+
|
|
369
|
+
**Server-side properties** (populated by Treasure Data):
|
|
370
|
+
| Property | Description | Signed Mode Only |
|
|
371
|
+
|----------|-------------|------------------|
|
|
372
|
+
| `td_ip` | Request IP address | ✓ |
|
|
373
|
+
|
|
374
|
+
\* *Marked properties are considered PII and only sent in signed mode*
|
|
375
|
+
|
|
376
|
+
## Configuration Options
|
|
377
|
+
|
|
378
|
+
### Core Configuration
|
|
379
|
+
```javascript
|
|
380
|
+
const td = new Treasure({
|
|
381
|
+
// Required
|
|
382
|
+
writeKey: 'your-write-key', // Get from Treasure Data console
|
|
383
|
+
database: 'your-database', // Target database name
|
|
384
|
+
|
|
385
|
+
// Optional
|
|
386
|
+
host: 'us01.records.in.treasuredata.com', // API endpoint host
|
|
387
|
+
development: false, // Enable development mode (no events sent)
|
|
388
|
+
logging: true, // Enable console logging
|
|
389
|
+
startInSignedMode: false, // Default consent mode
|
|
390
|
+
jsonpTimeout: 10000, // Request timeout (ms)
|
|
391
|
+
})
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Personalization Configuration
|
|
395
|
+
When set, every `trackEvent` and `trackPageview` call fetches personalization and renders any in-browser messages **instead of** ingesting the event to your database. The personalization table is the table passed to the tracking call, and the request payload is the event data (`$global` + table defaults + track values + record).
|
|
396
|
+
```javascript
|
|
397
|
+
const td = new Treasure({
|
|
398
|
+
writeKey: 'key',
|
|
399
|
+
database: 'db',
|
|
400
|
+
personalization: {
|
|
401
|
+
endpoint: 'personalization.example.com', // Personalization API endpoint
|
|
402
|
+
token: 'p13n_token_123', // Personalization API token
|
|
403
|
+
database: 'recommendations_db' // Optional; defaults to the main `database`
|
|
404
|
+
}
|
|
405
|
+
})
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Storage Configuration
|
|
409
|
+
```javascript
|
|
410
|
+
const td = new Treasure({
|
|
411
|
+
writeKey: 'key',
|
|
412
|
+
database: 'db',
|
|
413
|
+
storage: {
|
|
414
|
+
name: '_td', // Cookie name
|
|
415
|
+
expires: 63072000, // Expiry (seconds, 2 years default)
|
|
416
|
+
domain: '.yourdomain.com', // Cookie domain
|
|
417
|
+
path: '/' // Cookie path
|
|
418
|
+
}
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
// Disable cookie storage
|
|
422
|
+
const td = new Treasure({
|
|
423
|
+
writeKey: 'key',
|
|
424
|
+
database: 'db',
|
|
425
|
+
storage: 'none'
|
|
426
|
+
})
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Server-Side Cookie Configuration
|
|
430
|
+
```javascript
|
|
431
|
+
const td = new Treasure({
|
|
432
|
+
writeKey: 'key',
|
|
433
|
+
database: 'db',
|
|
434
|
+
useServerSideCookie: true,
|
|
435
|
+
sscDomain: 'yourdomain.com', // Or function: () => window.location.hostname
|
|
436
|
+
sscServer: 'ssc.yourdomain.com' // Or function: (domain) => `ssc.${domain}`
|
|
437
|
+
})
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
## API Reference
|
|
442
|
+
|
|
443
|
+
### Constructor
|
|
444
|
+
```javascript
|
|
445
|
+
new Treasure(config: TDConfig): Treasure
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**Parameters:**
|
|
449
|
+
- `config` (Object, required): Configuration object
|
|
450
|
+
- `writeKey` (string, required): Write-only API key from Treasure Data console
|
|
451
|
+
- `database` (string, required): Target database name
|
|
452
|
+
- `host` (string, optional): API endpoint host. Default: `'us01.records.in.treasuredata.com'`
|
|
453
|
+
- `development` (boolean, optional): Development mode - logs events without sending. Default: `false`
|
|
454
|
+
- `logging` (boolean, optional): Enable console logging. Default: `true`
|
|
455
|
+
- `startInSignedMode` (boolean, optional): Start in signed mode. Default: `false`
|
|
456
|
+
- `jsonpTimeout` (number, optional): Request timeout in milliseconds. Default: `10000`
|
|
457
|
+
- `storage` (Object|string, optional): Cookie storage configuration or `'none'` to disable
|
|
458
|
+
- `useServerSideCookie` (boolean, optional): Enable server-side cookie support. Default: `false`
|
|
459
|
+
- `personalization` (Object, optional): Personalization config. When set, every `trackEvent`/`trackPageview` fetches personalization instead of ingesting the event
|
|
460
|
+
- `endpoint` (string, required): Personalization API endpoint
|
|
461
|
+
- `token` (string, required): Personalization API token
|
|
462
|
+
- `database` (string, optional): Personalization database name. Defaults to the main `database`
|
|
463
|
+
- The personalization **table** is the table passed to the tracking call (e.g. `'events'`, `'pageviews'`), not configured here
|
|
464
|
+
- The request **payload** is the event data (`$global` + table defaults + track values + the call's `record`), not configured here
|
|
465
|
+
|
|
466
|
+
### Core Methods
|
|
467
|
+
|
|
468
|
+
#### `addRecord(table, record, success?, error?)`
|
|
469
|
+
Manual event submission without automatic tracking data.
|
|
470
|
+
|
|
471
|
+
**Parameters:**
|
|
472
|
+
- `table` (string, required): Table name (3-255 chars, lowercase, numbers, underscore only)
|
|
473
|
+
- `record` (Object, required): Event data object to send
|
|
474
|
+
- `success` (Function, optional): Success callback `(response: TrackResponse) => void`
|
|
475
|
+
- `error` (Function, optional): Error callback `(error: TDError) => void`
|
|
476
|
+
|
|
477
|
+
#### `trackEvent(table?, record?, success?, error?)`
|
|
478
|
+
Event tracking with automatic browser/session properties included. When `personalization` is configured on the constructor, fetches personalization instead of ingesting the event (see Behavior below).
|
|
479
|
+
|
|
480
|
+
**Parameters:**
|
|
481
|
+
- `table` (string, optional): Table name. Default: `'events'`
|
|
482
|
+
- `record` (Object, optional): Additional event data. Default: `{}`
|
|
483
|
+
- `success` (Function, optional): Success callback `(response: TrackResponse) => void`
|
|
484
|
+
- `error` (Function, optional): Error callback `(error: TDError) => void`
|
|
485
|
+
|
|
486
|
+
**Behavior:**
|
|
487
|
+
- When `personalization` is **not** configured: records the event with automatic properties via `addRecord`, invoking the `success`/`error` callbacks.
|
|
488
|
+
- When `personalization` **is** configured (see Configuration Options): calls the personalization API **instead of** recording the event. The personalization table is `table`, and the request payload is the event data layered as `$global` → table defaults → automatic track values → `record`.
|
|
489
|
+
- Personalization responses trigger in-browser message rendering
|
|
490
|
+
- Personalization errors are logged
|
|
491
|
+
- The `success`/`error` callbacks are **not** invoked on this path
|
|
492
|
+
|
|
493
|
+
#### `trackPageview(table?, success?, error?, options?)`
|
|
494
|
+
Page view tracking with automatic browser/session properties. Delegates to `trackEvent`, so it shares the same personalization behavior.
|
|
495
|
+
|
|
496
|
+
**Parameters:**
|
|
497
|
+
- `table` (string, optional): Table name. Default: `'pageviews'`
|
|
498
|
+
- `success` (Function, optional): Success callback `(response: TrackResponse) => void`
|
|
499
|
+
- `error` (Function, optional): Error callback `(error: TDError) => void`
|
|
500
|
+
- `options` (Object, optional): Tracking options
|
|
501
|
+
- `payload` (Object, optional): Additional event data to merge into the tracking record
|
|
502
|
+
|
|
503
|
+
**Behavior:**
|
|
504
|
+
- Delegates to `trackEvent` with the resolved table name and `options.payload` as the record
|
|
505
|
+
- When `personalization` is **not** configured on the constructor: records the pageview with automatic properties via `addRecord`
|
|
506
|
+
- When `personalization` **is** configured: fetches personalization instead of ingesting (same XOR behavior as `trackEvent`). Personalization responses trigger in-browser message rendering and page personalization. Page personalization is suppressed while loaded in Personalization Studio
|
|
507
|
+
|
|
508
|
+
#### `set(table, key, value)` or `set(table, object)`
|
|
509
|
+
Set default properties for tables or globally.
|
|
510
|
+
|
|
511
|
+
**Parameters:**
|
|
512
|
+
- `table` (string, required): Table name or `'$global'` for all tables
|
|
513
|
+
- `key` (string, required): Property name (when using 3-parameter form)
|
|
514
|
+
- `value` (JSONValue, required): Property value (when using 3-parameter form)
|
|
515
|
+
- `object` (Object, required): Multiple properties object (when using 2-parameter form)
|
|
516
|
+
|
|
517
|
+
#### `get(table?, key?)`
|
|
518
|
+
Retrieve stored default properties.
|
|
519
|
+
|
|
520
|
+
**Parameters:**
|
|
521
|
+
- `table` (string, optional): Table name. Default: `'$global'`
|
|
522
|
+
- `key` (string, optional): Specific property name. If omitted, returns all properties for table
|
|
523
|
+
|
|
524
|
+
**Returns:** `JSONValue` - The property value or properties object
|
|
525
|
+
|
|
526
|
+
### Identity & Privacy Methods
|
|
527
|
+
|
|
528
|
+
#### `setSignedMode()`
|
|
529
|
+
Enable signed mode - allows collection of PII (td_client_id, td_ip, td_global_id).
|
|
530
|
+
|
|
531
|
+
#### `setAnonymousMode(keepIdentifier?)`
|
|
532
|
+
Enable anonymous mode - blocks PII collection.
|
|
533
|
+
|
|
534
|
+
**Parameters:**
|
|
535
|
+
- `keepIdentifier` (boolean, optional): Keep existing cookies/identifiers. Default: `false`
|
|
536
|
+
|
|
537
|
+
#### `inSignedMode()`
|
|
538
|
+
Check current privacy mode.
|
|
539
|
+
|
|
540
|
+
**Returns:** `boolean` - True if in signed mode, false if anonymous
|
|
541
|
+
|
|
542
|
+
#### `blockEvents()`
|
|
543
|
+
Block all event tracking. Events will not be sent or cached.
|
|
544
|
+
|
|
545
|
+
#### `unblockEvents()`
|
|
546
|
+
Resume event tracking.
|
|
547
|
+
|
|
548
|
+
#### `areEventsBlocked()`
|
|
549
|
+
Check if events are currently blocked.
|
|
550
|
+
|
|
551
|
+
**Returns:** `boolean` - True if events are blocked
|
|
552
|
+
|
|
553
|
+
#### `resetUUID(storage?, clientId?)`
|
|
554
|
+
Generate new client UUID and update cookie.
|
|
555
|
+
|
|
556
|
+
**Parameters:**
|
|
557
|
+
- `storage` (Object, optional): Custom storage configuration
|
|
558
|
+
- `clientId` (string, optional): Specific UUID to set. If omitted, generates random UUID
|
|
559
|
+
|
|
560
|
+
### Plugin Methods
|
|
561
|
+
|
|
562
|
+
#### `trackClicks(options?)`
|
|
563
|
+
Enable automatic click tracking for buttons and links.
|
|
564
|
+
|
|
565
|
+
**Parameters:**
|
|
566
|
+
- `options` (Object, optional): Click tracking configuration
|
|
567
|
+
- `tableName` (string, optional): Table name. Default: `'clicks'`
|
|
568
|
+
- `element` (string|HTMLElement, optional): Target element or selector. Default: `document`
|
|
569
|
+
|
|
570
|
+
#### `collectUTMParameters()`
|
|
571
|
+
Extract UTM parameters from current URL.
|
|
572
|
+
|
|
573
|
+
**Returns:** `Object` - UTM parameters object (utm_source, utm_campaign, etc.)
|
|
574
|
+
|
|
575
|
+
#### `getUTMParameters()`
|
|
576
|
+
Get previously collected UTM parameters.
|
|
577
|
+
|
|
578
|
+
**Returns:** `Object` - Stored UTM parameters
|
|
579
|
+
|
|
580
|
+
#### `fetchGlobalID(success?, error?, forceFetch?, options?)`
|
|
581
|
+
Fetch Treasure Data Global ID for cross-device tracking.
|
|
582
|
+
|
|
583
|
+
**Prerequisites:** Must call `setSignedMode()` and `set('$global', 'td_global_id', 'td_global_id')` first.
|
|
584
|
+
|
|
585
|
+
**Parameters:**
|
|
586
|
+
- `success` (Function, optional): Success callback `(globalId: string | null) => void`
|
|
587
|
+
- `error` (Function, optional): Error callback `(error: unknown) => void`
|
|
588
|
+
- `forceFetch` (boolean, optional): Skip cache and fetch fresh ID. Default: `false`
|
|
589
|
+
- `options` (Object, optional): Cookie options
|
|
590
|
+
- `path` (string, optional): Cookie path
|
|
591
|
+
- `domain` (string, optional): Cookie domain
|
|
592
|
+
- `secure` (boolean, optional): Secure flag
|
|
593
|
+
- `maxAge` (number|string|Date, optional): Cookie expiry. Default: `6000`
|
|
594
|
+
- `sameSite` (string, optional): SameSite attribute ('None'|'Lax'|'Strict'). Default: `'None'`
|
|
595
|
+
|
|
596
|
+
#### `fetchServerCookie(success?, error?, forceFetch?)`
|
|
597
|
+
Fetch server-side cookie for ITP compliance.
|
|
598
|
+
|
|
599
|
+
**Prerequisites:** Must enable with `useServerSideCookie: true` in config and call `setSignedMode()`.
|
|
600
|
+
|
|
601
|
+
**Parameters:**
|
|
602
|
+
- `success` (Function, optional): Success callback `(serverSideId: string) => void`
|
|
603
|
+
- `error` (Function, optional): Error callback `(error: string | Error) => void`
|
|
604
|
+
- `forceFetch` (boolean, optional): Skip cache and fetch fresh cookie. Default: `false`
|
|
605
|
+
|
|
606
|
+
#### `fetchUserSegments(audienceToken, success?, error?)` or `fetchUserSegments(options, success?, error?)`
|
|
607
|
+
Fetch user segments for personalization.
|
|
608
|
+
|
|
609
|
+
**Parameters (Form 1):**
|
|
610
|
+
- `audienceToken` (string|string[], required): Audience token(s)
|
|
611
|
+
- `success` (Function, optional): Success callback with segment data
|
|
612
|
+
- `error` (Function, optional): Error callback
|
|
613
|
+
|
|
614
|
+
**Parameters (Form 2):**
|
|
615
|
+
- `options` (Object, required): Segmentation options
|
|
616
|
+
- `audienceToken` (string|string[], required): Audience token(s)
|
|
617
|
+
- `keys` (Object, optional): Additional key-value data
|
|
618
|
+
- `success` (Function, optional): Success callback with segment data
|
|
619
|
+
- `error` (Function, optional): Error callback
|
|
620
|
+
|
|
621
|
+
#### `fetchPersonalization(config, data?, success?, error?)`
|
|
622
|
+
Fetch personalization data from CDP API.
|
|
623
|
+
|
|
624
|
+
**Parameters:**
|
|
625
|
+
- `config` (Object, required): Personalization configuration
|
|
626
|
+
- `endpoint` (string, required): API endpoint URL
|
|
627
|
+
- `database` (string, required): Database name
|
|
628
|
+
- `table` (string, required): Table name
|
|
629
|
+
- `token` (string, required): API token
|
|
630
|
+
- `data` (Object, optional): Additional request data
|
|
631
|
+
- `success` (Function, optional): Success callback `(response: Object) => void`
|
|
632
|
+
- `error` (Function, optional): Error callback `(error: Error) => void`
|
|
633
|
+
|
|
634
|
+
#### `collectTags(options?)`
|
|
635
|
+
Collect conversion tracking tags for ad platforms.
|
|
636
|
+
|
|
637
|
+
**Parameters:**
|
|
638
|
+
- `options` (Object, optional): Collection options
|
|
639
|
+
- `table` (string, optional): Table name for storing tags
|
|
640
|
+
- `success` (Function, optional): Success callback `(response: TrackResponse) => void`
|
|
641
|
+
- `error` (Function, optional): Error callback `(error: TDError) => void`
|
|
642
|
+
|
|
643
|
+
## Examples
|
|
644
|
+
|
|
645
|
+
### E-commerce Tracking
|
|
646
|
+
```javascript
|
|
647
|
+
const td = new Treasure({ writeKey: 'key', database: 'ecommerce' })
|
|
648
|
+
|
|
649
|
+
// Product view
|
|
650
|
+
td.trackEvent('product_views', {
|
|
651
|
+
product_id: 'SKU-123',
|
|
652
|
+
category: 'electronics',
|
|
653
|
+
price: 299.99,
|
|
654
|
+
currency: 'USD'
|
|
655
|
+
})
|
|
656
|
+
|
|
657
|
+
// Purchase
|
|
658
|
+
td.trackEvent('purchases', {
|
|
659
|
+
order_id: 'ORDER-456',
|
|
660
|
+
items: ['SKU-123', 'SKU-789'],
|
|
661
|
+
total: 349.98,
|
|
662
|
+
payment_method: 'credit_card'
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
// Set user context
|
|
666
|
+
td.set('$global', {
|
|
667
|
+
user_id: '12345',
|
|
668
|
+
customer_tier: 'gold',
|
|
669
|
+
signup_date: '2024-01-15'
|
|
670
|
+
})
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### SaaS Application Analytics
|
|
674
|
+
```javascript
|
|
675
|
+
const td = new Treasure({ writeKey: 'key', database: 'saas_analytics' })
|
|
676
|
+
|
|
677
|
+
// Feature usage
|
|
678
|
+
td.trackEvent('feature_usage', {
|
|
679
|
+
feature: 'dashboard_export',
|
|
680
|
+
plan: 'pro',
|
|
681
|
+
execution_time_ms: 1250
|
|
682
|
+
})
|
|
683
|
+
|
|
684
|
+
// User onboarding
|
|
685
|
+
td.trackEvent('onboarding_steps', {
|
|
686
|
+
step: 'profile_completed',
|
|
687
|
+
step_number: 3,
|
|
688
|
+
time_to_complete_sec: 45
|
|
689
|
+
})
|
|
690
|
+
|
|
691
|
+
// Error tracking
|
|
692
|
+
td.trackEvent('errors', {
|
|
693
|
+
error_type: 'validation_failed',
|
|
694
|
+
form: 'user_signup',
|
|
695
|
+
field: 'email'
|
|
696
|
+
})
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Content & Media Site
|
|
700
|
+
```javascript
|
|
701
|
+
const td = new Treasure({ writeKey: 'key', database: 'content_analytics' })
|
|
702
|
+
|
|
703
|
+
// Article engagement
|
|
704
|
+
td.trackEvent('content_engagement', {
|
|
705
|
+
article_id: 'post-123',
|
|
706
|
+
engagement_type: 'scroll_75_percent',
|
|
707
|
+
time_on_page_sec: 120,
|
|
708
|
+
reading_speed_wpm: 200
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
// Video tracking
|
|
712
|
+
td.trackEvent('video_events', {
|
|
713
|
+
video_id: 'vid-789',
|
|
714
|
+
event: 'play',
|
|
715
|
+
position_sec: 0,
|
|
716
|
+
duration_sec: 300
|
|
717
|
+
})
|
|
718
|
+
|
|
719
|
+
// Newsletter signup
|
|
720
|
+
td.trackEvent('conversions', {
|
|
721
|
+
type: 'newsletter_signup',
|
|
722
|
+
source: 'article_cta',
|
|
723
|
+
article_category: 'technology'
|
|
724
|
+
})
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
## Troubleshooting
|
|
728
|
+
|
|
729
|
+
### Common Issues
|
|
730
|
+
|
|
731
|
+
**Events not appearing in Treasure Data:**
|
|
732
|
+
- Check `development: false` in config
|
|
733
|
+
- Verify `writeKey` and `database` are correct
|
|
734
|
+
- Ensure events aren't blocked: `td.areEventsBlocked()`
|
|
735
|
+
- Check browser console for error messages
|
|
736
|
+
|
|
737
|
+
**TypeScript errors:**
|
|
738
|
+
```bash
|
|
739
|
+
npm install --save-dev @types/node # If using Node.js types
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
**Global ID not working:**
|
|
743
|
+
- Must call `td.setSignedMode()` first
|
|
744
|
+
- Must enable with `td.set('$global', 'td_global_id', 'td_global_id')`
|
|
745
|
+
- Check HTTPS requirement for secure cookies
|
|
746
|
+
|
|
747
|
+
**Server-side cookie fails:**
|
|
748
|
+
- Verify `useServerSideCookie: true` in config
|
|
749
|
+
- Check `sscDomain` configuration
|
|
750
|
+
- Ensure signed mode is enabled
|
|
751
|
+
|
|
752
|
+
### Debug Mode
|
|
753
|
+
```javascript
|
|
754
|
+
const td = new Treasure({
|
|
755
|
+
writeKey: 'key',
|
|
756
|
+
database: 'db',
|
|
757
|
+
development: true, // Events logged, not sent
|
|
758
|
+
logging: true // Enable debug logs
|
|
759
|
+
})
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
## Browser Support
|
|
763
|
+
|
|
764
|
+
- **Modern**: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
|
|
765
|
+
- **Baseline**: All browsers with ES2022 support
|
|
766
|
+
- **Polyfills**: None required for target browsers
|
|
767
|
+
|
|
768
|
+
## Security
|
|
769
|
+
|
|
770
|
+
- All requests use HTTPS
|
|
771
|
+
- Write-only API keys (no read access)
|
|
772
|
+
- Optional PII collection controls
|
|
773
|
+
- SameSite=None cookies for cross-site tracking
|
|
774
|
+
- No sensitive data in localStorage
|
|
775
|
+
|
|
776
|
+
## Development
|
|
777
|
+
|
|
778
|
+
### Code Quality
|
|
779
|
+
|
|
780
|
+
This project uses automated code quality checks that run before each commit:
|
|
781
|
+
|
|
782
|
+
- **Type checking** - TypeScript compilation validation
|
|
783
|
+
- **Linting** - ESLint rules enforcement
|
|
784
|
+
- **Formatting** - Prettier code formatting
|
|
785
|
+
|
|
786
|
+
#### Setting up pre-commit hooks
|
|
787
|
+
|
|
788
|
+
To enable automatic code quality checks on commit:
|
|
789
|
+
|
|
790
|
+
```bash
|
|
791
|
+
npm run hooks:install
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
This configures git to run type-check, linting, and formatting before each commit. If formatting changes are needed, the commit will be blocked and you'll need to review and stage the changes.
|
|
795
|
+
|
|
796
|
+
#### Manual code quality checks
|
|
797
|
+
|
|
798
|
+
You can also run these checks manually:
|
|
799
|
+
|
|
800
|
+
```bash
|
|
801
|
+
npm run type-check # TypeScript compilation check
|
|
802
|
+
npm run lint # ESLint linting
|
|
803
|
+
npm run lint:fix # Auto-fix linting issues
|
|
804
|
+
npm run format # Apply Prettier formatting
|
|
805
|
+
npm run format:check # Check formatting without applying changes
|
|
806
|
+
```
|
|
807
|
+
|