saasco-sdk 0.1.22 → 0.1.24
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 +71 -34
- package/index.cjs.js +37 -28
- package/index.esm.js +37 -28
- package/package.json +1 -1
- package/src/lib/analytics.d.ts +19 -9
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
- [Privacy](#privacy)
|
|
6
|
-
- [Getting Started](#
|
|
7
|
-
- [
|
|
6
|
+
- [Getting Started](#getting-started)
|
|
7
|
+
- [Automatic Page View Tracking](#automatic-page-view-tracking)
|
|
8
8
|
- [Tracking Events](#tracking-events)
|
|
9
9
|
- [Identifying Users](#identifying-users)
|
|
10
10
|
- [Debugging and Dev](#debugging-and-dev)
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<br />
|
|
14
14
|
|
|
15
|
-
## 🔒
|
|
15
|
+
## 🔒 Privacy
|
|
16
16
|
|
|
17
17
|
By default Saasco is privacy friendly, using no cookies and obscuring all activity behind Anonymous IDs. However if you want to power more complex user tracking you can identify users and then all events they do will be attributed to them in your CRM. This can assist with customer support but also for things like drip campaigns and other marketing activities.
|
|
18
18
|
|
|
@@ -22,9 +22,9 @@ Install by running:
|
|
|
22
22
|
`npm install saasco-sdk`
|
|
23
23
|
|
|
24
24
|
Copy your Project ID from the project settings page in Saasco:
|
|
25
|
-
[https://saasco.com/your-project/settings/project](https://saasco.com/your-
|
|
25
|
+
[https://www.saasco.com/projects/your-project/apps/dashboard/settings/project](https://www.saasco.com/projects/your-project/apps/dashboard/settings/project)
|
|
26
26
|
|
|
27
|
-
Then import Saasco and
|
|
27
|
+
Then import Saasco and initialize the lib with your Project ID.
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
30
|
// lib/saasco.ts
|
|
@@ -35,7 +35,7 @@ export const saasco = new Saasco({ projectId: 'YOUR-PROJECT-ID' });
|
|
|
35
35
|
|
|
36
36
|
## Automatic Page View Tracking
|
|
37
37
|
|
|
38
|
-
When you
|
|
38
|
+
When you initialize the lib Saasco will automatically start tracking all page views in your app. By default, it tracks all URL changes, including query parameters and hash changes. You can customize this behavior using the `autoPageTracking` configuration object:
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
const analytics = new Saasco({
|
|
@@ -54,18 +54,23 @@ You can also [manually track pages](https://www.notion.so/Manual-Page-Tracking-i
|
|
|
54
54
|
|
|
55
55
|
## Tracking Events
|
|
56
56
|
|
|
57
|
-
With events you can track custom actions users are taking on your site with event properties.
|
|
57
|
+
With events you can track custom actions users are taking on your site with event properties. The track method supports both client-side (parameter-style) and server-side (object-style) usage patterns.
|
|
58
58
|
|
|
59
59
|
Each event has 2 components:
|
|
60
60
|
|
|
61
61
|
**Name** - this is the name of the action that was taken.
|
|
62
62
|
|
|
63
|
-
_We like to follow
|
|
63
|
+
_We like to follow Segment's [Object Action Framework](https://segment.com/academy/collecting-data/naming-conventions-for-clean-data/) for naming events._
|
|
64
64
|
|
|
65
|
-
**Properties** - This is an object with the values of the event. Such as
|
|
65
|
+
**Properties** - This is an object with the values of the event. Such as the value, currency, or query.
|
|
66
66
|
|
|
67
67
|
We currently have limited support for properties, but in the future we will support complex querying and actions based on event properties.
|
|
68
68
|
|
|
69
|
+
### Client Usage
|
|
70
|
+
|
|
71
|
+
For client-side tracking, use the Segment-compatible syntax.
|
|
72
|
+
This will automatically assign userId based on identify calls during the session
|
|
73
|
+
|
|
69
74
|
```tsx
|
|
70
75
|
// Import saasco
|
|
71
76
|
import { saasco } from '../lib/saasco.ts';
|
|
@@ -80,6 +85,25 @@ saasco.track("Searched Movies", {
|
|
|
80
85
|
});
|
|
81
86
|
```
|
|
82
87
|
|
|
88
|
+
### Server Usage (Object Style)
|
|
89
|
+
|
|
90
|
+
For server-side tracking, use the object-style syntax.
|
|
91
|
+
You must provide a userId for server side tracking events so there is a contact to connect the events to.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// Import saasco
|
|
95
|
+
import { saasco } from '../lib/saasco.ts';
|
|
96
|
+
|
|
97
|
+
// Track an event and associate it with a user
|
|
98
|
+
saasco.track({
|
|
99
|
+
event: "Signed Up",
|
|
100
|
+
userId: "user_123",
|
|
101
|
+
properties: {
|
|
102
|
+
provider: 'email',
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
83
107
|
## Identifying Users
|
|
84
108
|
|
|
85
109
|
By default Saasco does not track any identifiable data about users, just anonymous user ids and session ids. However if you want to tie events to users you can identify users which will connect events to users in your CRM and power tools like drip campaigns and customer support.
|
|
@@ -110,7 +134,7 @@ function signedOut(){
|
|
|
110
134
|
|
|
111
135
|
### Identifying users who don't have an ID
|
|
112
136
|
|
|
113
|
-
Often times you have a
|
|
137
|
+
Often times you have a user's contact details before they sign up for your site. This could be part of the signup flow, or if they were to subscribe to marketing emails before they sign up as a customer
|
|
114
138
|
|
|
115
139
|
Saasco allows identifying users without an id by simply skipping the `ID` part of the identify call. This will add contacts to the CRM for email marketing and other tools before users register.
|
|
116
140
|
|
|
@@ -129,7 +153,7 @@ By doing this users will get tracked and added to your contacts, and as soon as
|
|
|
129
153
|
|
|
130
154
|
### Soft vs Full identify
|
|
131
155
|
|
|
132
|
-
When users are identified without
|
|
156
|
+
When users are identified without an `ID` we call this a "Soft Identify". Users who are soft identified can also be called "Leads".
|
|
133
157
|
Once a user signs up and you identify them with an `ID` they will be fully registered and can be called "Customers"
|
|
134
158
|
|
|
135
159
|
In the CRM when you identify a user, either soft or full, they become a contact.
|
|
@@ -152,43 +176,50 @@ export const saasco = new Saasco({
|
|
|
152
176
|
|
|
153
177
|
#### Debugging
|
|
154
178
|
|
|
155
|
-
You can turn on debugging when you
|
|
179
|
+
You can turn on debugging when you initialize the repo or by running `saasco.enableDebug()` in your code or the browser.
|
|
156
180
|
|
|
157
181
|
```tsx
|
|
158
182
|
export const saasco = new Saasco({
|
|
159
183
|
projectId: 'YOUR-PROJECT-ID',
|
|
160
184
|
enabled: process.env['NODE_ENV'] === 'production',
|
|
161
185
|
// Set to true to console log analytics events.
|
|
162
|
-
// This works even when enabled is false - it just
|
|
186
|
+
// This works even when enabled is false - it just won't send the data
|
|
163
187
|
debug: true,
|
|
164
188
|
});
|
|
165
189
|
```
|
|
166
190
|
|
|
167
|
-
You can also enable debug mode by calling `saasco.
|
|
191
|
+
You can also enable debug mode by calling `saasco.enableDebug()` anywhere in your code.
|
|
168
192
|
|
|
169
193
|
```tsx
|
|
170
|
-
saasco.
|
|
194
|
+
saasco.enableDebug();
|
|
171
195
|
// will console log "debug mode activated"
|
|
172
196
|
```
|
|
173
197
|
|
|
198
|
+
You can disable debug mode by calling `saasco.disableDebug()`.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
saasco.disableDebug();
|
|
202
|
+
// will console log "debug mode deactivated"
|
|
203
|
+
```
|
|
204
|
+
|
|
174
205
|
## Reserved Properties
|
|
175
206
|
|
|
176
|
-
Saasco has reserved some properties that have semantic meanings for contacts and
|
|
207
|
+
Saasco has reserved some properties that have semantic meanings for contacts and will handle them in special ways.
|
|
177
208
|
For example, Saasco always expects email to be a string of the user's email address, this is important for when sending emails using the marketing app.
|
|
178
209
|
The SDK will do its best to match these properties, eg (created_at will be mapped to createdAt), but if possible you should use the reserved properties.
|
|
179
210
|
|
|
180
211
|
### Reserved Contact Properties
|
|
181
212
|
|
|
182
|
-
|
|
|
213
|
+
| PROPERTY | TYPE | DESCRIPTION |
|
|
183
214
|
| ----------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
|
|
184
215
|
| age | Number | Age of a user |
|
|
185
216
|
| avatar | String | URL to an avatar image for the user |
|
|
186
217
|
| birthday | Date | User's birthday |
|
|
187
|
-
| createdAt | Date | Date the user's account was first created. We
|
|
218
|
+
| createdAt | Date | Date the user's account was first created. We recommend using ISO-8601 date strings. |
|
|
188
219
|
| description | String | Description of the user |
|
|
189
220
|
| email | String | Email address of a user |
|
|
190
221
|
| firstName | String | First name of a user |
|
|
191
|
-
| displayName | String | The
|
|
222
|
+
| displayName | String | The preferred user's display name, will default to "firstName lastName" |
|
|
192
223
|
| gender | String | Gender of a user |
|
|
193
224
|
| lastName | String | Last name of a user |
|
|
194
225
|
| name | String | Full name of a user. If you only pass a first and last name Segment automatically fills in the full name for you. |
|
|
@@ -213,11 +244,11 @@ Any property that starts with `$` is a property that has been generated by the S
|
|
|
213
244
|
| $locale | Locale | The most recent preferred language of the user. |
|
|
214
245
|
| $screenHeight | Screen Height | The most recent height of the device screen in pixels |
|
|
215
246
|
| $screenWidth | Screen Width | The most recent width of the device screen in pixels |
|
|
216
|
-
| $screenDpi | Screen DPI | The most recent
|
|
247
|
+
| $screenDpi | Screen DPI | The most recent pixel density of the device screen. |
|
|
217
248
|
| $lastSeen | Last Seen | The last time a user was identified while active was not false in the context |
|
|
218
249
|
| $os | Operating System | The most recent OS of the user. |
|
|
219
250
|
| $browser | Browser | The most recent browser of the user. |
|
|
220
|
-
| $browserVersion | Browser Version | The most recent
|
|
251
|
+
| $browserVersion | Browser Version | The most recent browser version of the user. |
|
|
221
252
|
| $initialReferrer | Initial Referrer | Referring URL when the user first arrived on your site. Defaults to "direct" |
|
|
222
253
|
| $referrer | Last Touch Referrer | Referring URL when the user last interacted with your site. Defaults to "direct" |
|
|
223
254
|
| $initialReferringDomain | Initial Referring Domain | Referring domain at first arrival. Defaults to "direct" |
|
|
@@ -249,11 +280,11 @@ Properties used to calculate revenue for different traffic sources and LTV for u
|
|
|
249
280
|
| -------- | ------ | ----------------------------------------------------------------------------------------- |
|
|
250
281
|
| revenue | Number | Amount of revenue an event resulted in. This should be a decimal value |
|
|
251
282
|
| currency | String | Currency of the revenue an event resulted in. This should be sent in the ISO 4127 format. |
|
|
252
|
-
| value | Number | An abstract numerical value used internally to score
|
|
283
|
+
| value | Number | An abstract numerical value used internally to score events, such as lead scoring. |
|
|
253
284
|
|
|
254
285
|
### Default Event Properties
|
|
255
286
|
|
|
256
|
-
Our SDKs automatically collect certain properties on every event or user profile. The default properties begin with a `$` and can be overwritten with your own identify calls, so we
|
|
287
|
+
Our SDKs automatically collect certain properties on every event or user profile. The default properties begin with a `$` and can be overwritten with your own identify calls, so we recommend avoiding leading `$` in your identify call properties to avoid conflicts.
|
|
257
288
|
|
|
258
289
|
| Property | Display Name | Description |
|
|
259
290
|
| ---------------- | --------------------------- | -------------------------------------------------------------------------------- |
|
|
@@ -320,16 +351,19 @@ saasco.track('Signed Up', {
|
|
|
320
351
|
Event triggered when a user signs in.
|
|
321
352
|
| Property | Description |
|
|
322
353
|
|----------|--------------------------------------------------|
|
|
323
|
-
| `
|
|
354
|
+
| `provider` | The provider used for signing in (e.g., email, github, google). |
|
|
324
355
|
|
|
325
356
|
Example:
|
|
326
357
|
|
|
327
358
|
```jsx
|
|
328
359
|
saasco.track('Signed In', {
|
|
329
|
-
|
|
360
|
+
provider: 'email',
|
|
330
361
|
});
|
|
331
362
|
```
|
|
332
363
|
|
|
364
|
+
Note:
|
|
365
|
+
When tracking Signed In events call identify('user_id', {email: '...'}) before the event to connect to the user.
|
|
366
|
+
|
|
333
367
|
#### Signed Out
|
|
334
368
|
|
|
335
369
|
Event triggered when a user signs out.
|
|
@@ -341,13 +375,16 @@ Example:
|
|
|
341
375
|
saasco.track('Signed Out');
|
|
342
376
|
```
|
|
343
377
|
|
|
378
|
+
Note:
|
|
379
|
+
When tracking Signed Out events call identify(null) _after_ tracking the event to reset the session.
|
|
380
|
+
|
|
344
381
|
#### Trial Started
|
|
345
382
|
|
|
346
383
|
Event triggered when a user starts a trial.
|
|
347
384
|
| Property | Description |
|
|
348
385
|
|-------------------|---------------------------------------------------------------------|
|
|
349
386
|
| `duration` | The duration of the trial in days |
|
|
350
|
-
| `type`| Values can be `optIn` for
|
|
387
|
+
| `type`| Values can be `optIn` for when the user didn't provide a cc or `optOut` when the user provided a cc and it will automatically start at the end of the trial period|
|
|
351
388
|
|
|
352
389
|
Example:
|
|
353
390
|
|
|
@@ -357,10 +394,10 @@ saasco.track('Trial Started', { duration: 14, type: 'optOut' });
|
|
|
357
394
|
|
|
358
395
|
#### Trial Ended
|
|
359
396
|
|
|
360
|
-
Event triggered when a
|
|
397
|
+
Event triggered when a user's trial ends.
|
|
361
398
|
| Property | Description |
|
|
362
399
|
|-------------------|---------------------------------------------------------------------|
|
|
363
|
-
| `daysLeftInTrial`| If a user
|
|
400
|
+
| `daysLeftInTrial`| If a user manually upgrades before the end of the trial you can record this here|
|
|
364
401
|
|
|
365
402
|
Example:
|
|
366
403
|
|
|
@@ -368,10 +405,10 @@ Example:
|
|
|
368
405
|
saasco.track('Trial Ended', { daysLeftInTrial: 4 });
|
|
369
406
|
```
|
|
370
407
|
|
|
371
|
-
#### Payment
|
|
408
|
+
#### Payment Completed
|
|
372
409
|
|
|
373
410
|
Event triggered when a payment is completed.
|
|
374
|
-
This
|
|
411
|
+
This may be called on the server side after a confirmation webhook.
|
|
375
412
|
This is helpful for recording ongoing subscription payments.
|
|
376
413
|
|
|
377
414
|
| Property | Description |
|
|
@@ -435,7 +472,7 @@ Event triggered when a subscription is upgraded.
|
|
|
435
472
|
Example:
|
|
436
473
|
|
|
437
474
|
```jsx
|
|
438
|
-
saasco.track('Subscription
|
|
475
|
+
saasco.track('Subscription Upgraded', {
|
|
439
476
|
fromPlan: 'Monthly',
|
|
440
477
|
toPlan: 'Annual',
|
|
441
478
|
previousRevenue: 29,
|
|
@@ -452,13 +489,13 @@ Event triggered when a subscription is downgraded.
|
|
|
452
489
|
| `toPlan` | The new plan. |
|
|
453
490
|
| `previousRevenue` | The revenue from the previous plan. |
|
|
454
491
|
| `newRevenue` | The revenue from the new plan. |
|
|
455
|
-
| `revenue` | If the customer is refunded immediately then include a revenue number here, in the case of a downgrade this will be a
|
|
492
|
+
| `revenue` | If the customer is refunded immediately then include a revenue number here, in the case of a downgrade this will be a negative value. Only include the revenue here if it's not tracked on your backend or with a webhook |
|
|
456
493
|
| `currency` | The currency of the payment, assumed to be USD unless otherwise specified. |
|
|
457
494
|
|
|
458
495
|
Example:
|
|
459
496
|
|
|
460
497
|
```jsx
|
|
461
|
-
saasco.track('Subscription
|
|
498
|
+
saasco.track('Subscription Downgraded', {
|
|
462
499
|
fromPlan: 'Annual',
|
|
463
500
|
toPlan: 'Monthly',
|
|
464
501
|
previousRevenue: 129,
|
|
@@ -480,7 +517,7 @@ All properties should be added as data attributes in the format data-[prop name]
|
|
|
480
517
|
></script>
|
|
481
518
|
```
|
|
482
519
|
|
|
483
|
-
All the properties for
|
|
520
|
+
All the properties for initializing the sdk can be passed in like this:
|
|
484
521
|
|
|
485
522
|
```jsx
|
|
486
523
|
<script
|
package/index.cjs.js
CHANGED
|
@@ -6,7 +6,7 @@ var tslib = require('tslib');
|
|
|
6
6
|
var uuid = require('@lukeed/uuid');
|
|
7
7
|
var zod = require('zod');
|
|
8
8
|
|
|
9
|
-
var version = "0.1.
|
|
9
|
+
var version = "0.1.24";
|
|
10
10
|
|
|
11
11
|
const timezones = {
|
|
12
12
|
'Asia/Barnaul': 'RU',
|
|
@@ -469,6 +469,7 @@ function getBrowserContext() {
|
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
const isBrowser = typeof window !== 'undefined';
|
|
472
|
+
const isServer = !isBrowser;
|
|
472
473
|
const PREF = 'saasco-sdk';
|
|
473
474
|
const data = {};
|
|
474
475
|
function storeData(key, value, ttl) {
|
|
@@ -476,7 +477,7 @@ function storeData(key, value, ttl) {
|
|
|
476
477
|
value,
|
|
477
478
|
expiry: new Date().getTime() + ttl
|
|
478
479
|
};
|
|
479
|
-
if (
|
|
480
|
+
if (isServer) {
|
|
480
481
|
if (value === undefined) {
|
|
481
482
|
delete data[key];
|
|
482
483
|
return;
|
|
@@ -489,7 +490,7 @@ function storeData(key, value, ttl) {
|
|
|
489
490
|
localStorage.setItem(fullKey, JSON.stringify(item));
|
|
490
491
|
}
|
|
491
492
|
function retrieveData(key) {
|
|
492
|
-
if (
|
|
493
|
+
if (isServer) {
|
|
493
494
|
const item = data[key];
|
|
494
495
|
if (!item) return null;
|
|
495
496
|
if (Date.now() > item.expiry) {
|
|
@@ -525,7 +526,7 @@ function setSessionId({
|
|
|
525
526
|
function getAnonymousId() {
|
|
526
527
|
return retrieveData(`anonymous-id`);
|
|
527
528
|
}
|
|
528
|
-
function
|
|
529
|
+
function setAnonymousId({
|
|
529
530
|
reset
|
|
530
531
|
} = {
|
|
531
532
|
reset: false
|
|
@@ -581,7 +582,7 @@ class Saasco {
|
|
|
581
582
|
this.log('Saasco initialized', this.config);
|
|
582
583
|
if (this.config.debug) this.log('Debug mode active. This will log all events to the console.');
|
|
583
584
|
if (!this.config.enabled) this.log('Analytics is disabled. No requests will be sent to the server.');
|
|
584
|
-
this.
|
|
585
|
+
this.initAutoPageTracking();
|
|
585
586
|
this.isInitialized = true;
|
|
586
587
|
}
|
|
587
588
|
disableDebug() {
|
|
@@ -592,35 +593,43 @@ class Saasco {
|
|
|
592
593
|
this.config.debug = true;
|
|
593
594
|
this.log('Debug mode activated.');
|
|
594
595
|
}
|
|
595
|
-
|
|
596
|
-
* The track method lets you record the actions your users perform.
|
|
597
|
-
* Its good to keep a conistent naming convention for your events.
|
|
598
|
-
* We like the Object Action Framework from segment:
|
|
599
|
-
* https://segment.com/academy/collecting-data/naming-conventions-for-clean-data/
|
|
600
|
-
*
|
|
601
|
-
* @param name The name of the event eg "Song Played"
|
|
602
|
-
* @param properties The properties of the event eg { genre: "Classics", song: "Never Gonna Give You Up" }
|
|
603
|
-
*/
|
|
604
|
-
track(name,
|
|
605
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
606
|
-
properties, context) {
|
|
596
|
+
track(actionOrPayload, propertiesOrNothing, contextOrNothing) {
|
|
607
597
|
if (!this.config.projectId) {
|
|
608
598
|
const response = this.error("Unable to track event. Project ID is required but has not been provided. If you are using an env variable make sure it's set correctly.");
|
|
609
599
|
return Promise.resolve(response);
|
|
610
600
|
}
|
|
611
601
|
setSessionId();
|
|
612
|
-
|
|
613
|
-
const
|
|
602
|
+
setAnonymousId();
|
|
603
|
+
const hasAction = typeof actionOrPayload === 'string';
|
|
604
|
+
const hasPayload = typeof actionOrPayload === 'object';
|
|
605
|
+
// Must do payload on the server
|
|
606
|
+
if (isServer && hasAction) {
|
|
607
|
+
const response = this.error('When calling track from the server you must pass a payload object with a userId in order to track events. For example: track({ event: "Song Played", userId: "user_123", properties: { song: "Song Name" } })');
|
|
608
|
+
return Promise.resolve(response);
|
|
609
|
+
}
|
|
610
|
+
// On server events we require a userId or an anonymousId
|
|
611
|
+
if (isServer && hasPayload && !actionOrPayload.userId && !actionOrPayload.anonymousId) {
|
|
612
|
+
const response = this.error('When calling track from the server you must pass a payload object with either a userId or an anonymousId in order to track events. For example:\n\ntrack({ event: "Song Played", userId: "user_123", properties: { song: "Song Name" } }). \n\nIf providing an anonymousId this must be provided from the client side otherwise we will not have a user to connect the event to.');
|
|
613
|
+
return Promise.resolve(response);
|
|
614
|
+
}
|
|
615
|
+
const action = hasAction ? actionOrPayload : actionOrPayload.event;
|
|
616
|
+
const properties = hasAction ? propertiesOrNothing : actionOrPayload.properties;
|
|
617
|
+
const context = hasAction ? contextOrNothing : actionOrPayload.context;
|
|
618
|
+
const sessionId = (hasAction ? undefined : actionOrPayload.sessionId) || getSessionId();
|
|
619
|
+
const anonymousId = (hasAction ? undefined : actionOrPayload.anonymousId) || getAnonymousId();
|
|
620
|
+
const distinctId = (hasAction ? undefined : actionOrPayload.userId) || getUserId();
|
|
621
|
+
// Only gets browser context if in the browser
|
|
622
|
+
const browserContext = isBrowser ? getBrowserContext() || {} : {};
|
|
614
623
|
const data = {
|
|
615
624
|
id: uuid.v4(),
|
|
616
625
|
timestamp: new Date().toISOString(),
|
|
617
|
-
action
|
|
626
|
+
action,
|
|
618
627
|
version,
|
|
619
|
-
sessionId
|
|
620
|
-
anonymousId
|
|
621
|
-
distinctId
|
|
628
|
+
sessionId,
|
|
629
|
+
anonymousId,
|
|
630
|
+
distinctId,
|
|
622
631
|
projectId: this.config.projectId,
|
|
623
|
-
payload: JSON.stringify(Object.assign(Object.assign({}, browserContext
|
|
632
|
+
payload: JSON.stringify(Object.assign(Object.assign({}, browserContext), {
|
|
624
633
|
properties: properties || {}
|
|
625
634
|
})),
|
|
626
635
|
source: isBrowser ? 'client' : 'server',
|
|
@@ -636,7 +645,7 @@ class Saasco {
|
|
|
636
645
|
*/
|
|
637
646
|
page() {
|
|
638
647
|
var _a, _b;
|
|
639
|
-
if (
|
|
648
|
+
if (isServer) {
|
|
640
649
|
console.warn('Saasco page tracking is only available in the browser');
|
|
641
650
|
return;
|
|
642
651
|
}
|
|
@@ -673,7 +682,7 @@ class Saasco {
|
|
|
673
682
|
setSessionId({
|
|
674
683
|
reset
|
|
675
684
|
});
|
|
676
|
-
const anonymousId =
|
|
685
|
+
const anonymousId = setAnonymousId({
|
|
677
686
|
reset
|
|
678
687
|
});
|
|
679
688
|
// set the distinct Id to the userId
|
|
@@ -778,12 +787,12 @@ class Saasco {
|
|
|
778
787
|
* It listens to url changes to track new pages every time the url changes
|
|
779
788
|
* @returns
|
|
780
789
|
*/
|
|
781
|
-
|
|
790
|
+
initAutoPageTracking() {
|
|
782
791
|
var _a, _b;
|
|
783
792
|
// Disable auto page tracking if the config is set to false
|
|
784
793
|
if (!((_a = this.config.autoPageTracking) === null || _a === void 0 ? void 0 : _a.enabled)) return;
|
|
785
794
|
// Prevent running on the server
|
|
786
|
-
if (
|
|
795
|
+
if (isServer) return console.warn('Saasco auto page tracking is only available in the browser');
|
|
787
796
|
// Prevent intitializing auto page tracking more than once
|
|
788
797
|
if (window.saascoAutoPageTrackingActive) {
|
|
789
798
|
this.log('Auto Page Tracking already enabled');
|
package/index.esm.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __awaiter } from 'tslib';
|
|
|
2
2
|
import { v4 } from '@lukeed/uuid';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
-
var version = "0.1.
|
|
5
|
+
var version = "0.1.24";
|
|
6
6
|
|
|
7
7
|
const timezones = {
|
|
8
8
|
'Asia/Barnaul': 'RU',
|
|
@@ -465,6 +465,7 @@ function getBrowserContext() {
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
const isBrowser = typeof window !== 'undefined';
|
|
468
|
+
const isServer = !isBrowser;
|
|
468
469
|
const PREF = 'saasco-sdk';
|
|
469
470
|
const data = {};
|
|
470
471
|
function storeData(key, value, ttl) {
|
|
@@ -472,7 +473,7 @@ function storeData(key, value, ttl) {
|
|
|
472
473
|
value,
|
|
473
474
|
expiry: new Date().getTime() + ttl
|
|
474
475
|
};
|
|
475
|
-
if (
|
|
476
|
+
if (isServer) {
|
|
476
477
|
if (value === undefined) {
|
|
477
478
|
delete data[key];
|
|
478
479
|
return;
|
|
@@ -485,7 +486,7 @@ function storeData(key, value, ttl) {
|
|
|
485
486
|
localStorage.setItem(fullKey, JSON.stringify(item));
|
|
486
487
|
}
|
|
487
488
|
function retrieveData(key) {
|
|
488
|
-
if (
|
|
489
|
+
if (isServer) {
|
|
489
490
|
const item = data[key];
|
|
490
491
|
if (!item) return null;
|
|
491
492
|
if (Date.now() > item.expiry) {
|
|
@@ -521,7 +522,7 @@ function setSessionId({
|
|
|
521
522
|
function getAnonymousId() {
|
|
522
523
|
return retrieveData(`anonymous-id`);
|
|
523
524
|
}
|
|
524
|
-
function
|
|
525
|
+
function setAnonymousId({
|
|
525
526
|
reset
|
|
526
527
|
} = {
|
|
527
528
|
reset: false
|
|
@@ -577,7 +578,7 @@ class Saasco {
|
|
|
577
578
|
this.log('Saasco initialized', this.config);
|
|
578
579
|
if (this.config.debug) this.log('Debug mode active. This will log all events to the console.');
|
|
579
580
|
if (!this.config.enabled) this.log('Analytics is disabled. No requests will be sent to the server.');
|
|
580
|
-
this.
|
|
581
|
+
this.initAutoPageTracking();
|
|
581
582
|
this.isInitialized = true;
|
|
582
583
|
}
|
|
583
584
|
disableDebug() {
|
|
@@ -588,35 +589,43 @@ class Saasco {
|
|
|
588
589
|
this.config.debug = true;
|
|
589
590
|
this.log('Debug mode activated.');
|
|
590
591
|
}
|
|
591
|
-
|
|
592
|
-
* The track method lets you record the actions your users perform.
|
|
593
|
-
* Its good to keep a conistent naming convention for your events.
|
|
594
|
-
* We like the Object Action Framework from segment:
|
|
595
|
-
* https://segment.com/academy/collecting-data/naming-conventions-for-clean-data/
|
|
596
|
-
*
|
|
597
|
-
* @param name The name of the event eg "Song Played"
|
|
598
|
-
* @param properties The properties of the event eg { genre: "Classics", song: "Never Gonna Give You Up" }
|
|
599
|
-
*/
|
|
600
|
-
track(name,
|
|
601
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
602
|
-
properties, context) {
|
|
592
|
+
track(actionOrPayload, propertiesOrNothing, contextOrNothing) {
|
|
603
593
|
if (!this.config.projectId) {
|
|
604
594
|
const response = this.error("Unable to track event. Project ID is required but has not been provided. If you are using an env variable make sure it's set correctly.");
|
|
605
595
|
return Promise.resolve(response);
|
|
606
596
|
}
|
|
607
597
|
setSessionId();
|
|
608
|
-
|
|
609
|
-
const
|
|
598
|
+
setAnonymousId();
|
|
599
|
+
const hasAction = typeof actionOrPayload === 'string';
|
|
600
|
+
const hasPayload = typeof actionOrPayload === 'object';
|
|
601
|
+
// Must do payload on the server
|
|
602
|
+
if (isServer && hasAction) {
|
|
603
|
+
const response = this.error('When calling track from the server you must pass a payload object with a userId in order to track events. For example: track({ event: "Song Played", userId: "user_123", properties: { song: "Song Name" } })');
|
|
604
|
+
return Promise.resolve(response);
|
|
605
|
+
}
|
|
606
|
+
// On server events we require a userId or an anonymousId
|
|
607
|
+
if (isServer && hasPayload && !actionOrPayload.userId && !actionOrPayload.anonymousId) {
|
|
608
|
+
const response = this.error('When calling track from the server you must pass a payload object with either a userId or an anonymousId in order to track events. For example:\n\ntrack({ event: "Song Played", userId: "user_123", properties: { song: "Song Name" } }). \n\nIf providing an anonymousId this must be provided from the client side otherwise we will not have a user to connect the event to.');
|
|
609
|
+
return Promise.resolve(response);
|
|
610
|
+
}
|
|
611
|
+
const action = hasAction ? actionOrPayload : actionOrPayload.event;
|
|
612
|
+
const properties = hasAction ? propertiesOrNothing : actionOrPayload.properties;
|
|
613
|
+
const context = hasAction ? contextOrNothing : actionOrPayload.context;
|
|
614
|
+
const sessionId = (hasAction ? undefined : actionOrPayload.sessionId) || getSessionId();
|
|
615
|
+
const anonymousId = (hasAction ? undefined : actionOrPayload.anonymousId) || getAnonymousId();
|
|
616
|
+
const distinctId = (hasAction ? undefined : actionOrPayload.userId) || getUserId();
|
|
617
|
+
// Only gets browser context if in the browser
|
|
618
|
+
const browserContext = isBrowser ? getBrowserContext() || {} : {};
|
|
610
619
|
const data = {
|
|
611
620
|
id: v4(),
|
|
612
621
|
timestamp: new Date().toISOString(),
|
|
613
|
-
action
|
|
622
|
+
action,
|
|
614
623
|
version,
|
|
615
|
-
sessionId
|
|
616
|
-
anonymousId
|
|
617
|
-
distinctId
|
|
624
|
+
sessionId,
|
|
625
|
+
anonymousId,
|
|
626
|
+
distinctId,
|
|
618
627
|
projectId: this.config.projectId,
|
|
619
|
-
payload: JSON.stringify(Object.assign(Object.assign({}, browserContext
|
|
628
|
+
payload: JSON.stringify(Object.assign(Object.assign({}, browserContext), {
|
|
620
629
|
properties: properties || {}
|
|
621
630
|
})),
|
|
622
631
|
source: isBrowser ? 'client' : 'server',
|
|
@@ -632,7 +641,7 @@ class Saasco {
|
|
|
632
641
|
*/
|
|
633
642
|
page() {
|
|
634
643
|
var _a, _b;
|
|
635
|
-
if (
|
|
644
|
+
if (isServer) {
|
|
636
645
|
console.warn('Saasco page tracking is only available in the browser');
|
|
637
646
|
return;
|
|
638
647
|
}
|
|
@@ -669,7 +678,7 @@ class Saasco {
|
|
|
669
678
|
setSessionId({
|
|
670
679
|
reset
|
|
671
680
|
});
|
|
672
|
-
const anonymousId =
|
|
681
|
+
const anonymousId = setAnonymousId({
|
|
673
682
|
reset
|
|
674
683
|
});
|
|
675
684
|
// set the distinct Id to the userId
|
|
@@ -774,12 +783,12 @@ class Saasco {
|
|
|
774
783
|
* It listens to url changes to track new pages every time the url changes
|
|
775
784
|
* @returns
|
|
776
785
|
*/
|
|
777
|
-
|
|
786
|
+
initAutoPageTracking() {
|
|
778
787
|
var _a, _b;
|
|
779
788
|
// Disable auto page tracking if the config is set to false
|
|
780
789
|
if (!((_a = this.config.autoPageTracking) === null || _a === void 0 ? void 0 : _a.enabled)) return;
|
|
781
790
|
// Prevent running on the server
|
|
782
|
-
if (
|
|
791
|
+
if (isServer) return console.warn('Saasco auto page tracking is only available in the browser');
|
|
783
792
|
// Prevent intitializing auto page tracking more than once
|
|
784
793
|
if (window.saascoAutoPageTrackingActive) {
|
|
785
794
|
this.log('Auto Page Tracking already enabled');
|
package/package.json
CHANGED
package/src/lib/analytics.d.ts
CHANGED
|
@@ -4,6 +4,19 @@ declare global {
|
|
|
4
4
|
saasco: Saasco;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
+
type Identity = {
|
|
8
|
+
userId: string | number;
|
|
9
|
+
anonymousId?: string | number;
|
|
10
|
+
} | {
|
|
11
|
+
anonymousId: string | number;
|
|
12
|
+
userId?: string | number;
|
|
13
|
+
};
|
|
14
|
+
type TrackPayload = Identity & {
|
|
15
|
+
event: string;
|
|
16
|
+
sessionId?: string;
|
|
17
|
+
properties?: Record<string, any>;
|
|
18
|
+
context?: Record<string, any>;
|
|
19
|
+
};
|
|
7
20
|
type DoRequestResponse = {
|
|
8
21
|
success: boolean;
|
|
9
22
|
message: string;
|
|
@@ -38,17 +51,14 @@ export declare class Saasco {
|
|
|
38
51
|
disableDebug(): void;
|
|
39
52
|
enableDebug(): void;
|
|
40
53
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* https://segment.com/academy/collecting-data/naming-conventions-for-clean-data/
|
|
45
|
-
*
|
|
46
|
-
* @param name The name of the event eg "Song Played"
|
|
47
|
-
* @param properties The properties of the event eg { genre: "Classics", song: "Never Gonna Give You Up" }
|
|
54
|
+
* Track events with support for both client (Segment-style) and server (object-style) usage
|
|
55
|
+
* Client: track('User Signed Up', { plan: 'Pro' }, { source: 'client' })
|
|
56
|
+
* Server: track({ event: 'User Signed Up', userId: 'user_123', properties: { plan: 'Pro' } })
|
|
48
57
|
*/
|
|
49
|
-
track(
|
|
58
|
+
track(action: string, properties?: Record<string, any>, context?: {
|
|
50
59
|
active?: boolean;
|
|
51
60
|
}): Promise<DoRequestResponse>;
|
|
61
|
+
track(payload: TrackPayload): Promise<DoRequestResponse>;
|
|
52
62
|
/**
|
|
53
63
|
* The page method lets you record page views on your website
|
|
54
64
|
* This records the page title and path and names the event useing the reserved property "Page Viewed"
|
|
@@ -99,6 +109,6 @@ export declare class Saasco {
|
|
|
99
109
|
* It listens to url changes to track new pages every time the url changes
|
|
100
110
|
* @returns
|
|
101
111
|
*/
|
|
102
|
-
private
|
|
112
|
+
private initAutoPageTracking;
|
|
103
113
|
}
|
|
104
114
|
export {};
|