saasco-sdk 0.1.21 → 0.1.23
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 +24 -1
- package/index.cjs.js +33 -23
- package/index.esm.js +33 -23
- package/package.json +1 -1
- package/src/lib/analytics.d.ts +18 -8
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ 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 (oarameter-style) and server-side (object-style) usage patterns.
|
|
58
58
|
|
|
59
59
|
Each event has 2 components:
|
|
60
60
|
|
|
@@ -66,6 +66,11 @@ _We like to follow segments [Object Action Framework](https://segment.com/academ
|
|
|
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,24 @@ 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.
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// Import saasco
|
|
95
|
+
import { saasco } from '../lib/saasco.ts';
|
|
96
|
+
|
|
97
|
+
// Track an event with full control
|
|
98
|
+
saasco.track({
|
|
99
|
+
event: "User Signed Up",
|
|
100
|
+
userId: "user_123",
|
|
101
|
+
properties: { plan: "Pro" },
|
|
102
|
+
context: { source: "server" },
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
83
106
|
## Identifying Users
|
|
84
107
|
|
|
85
108
|
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.
|
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.23";
|
|
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) {
|
|
@@ -592,37 +593,46 @@ 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
602
|
setAnonmousId();
|
|
613
|
-
const
|
|
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
|
})),
|
|
635
|
+
source: isBrowser ? 'client' : 'server',
|
|
626
636
|
context: JSON.stringify(context || {})
|
|
627
637
|
};
|
|
628
638
|
return this.doRequest('events', data);
|
|
@@ -635,7 +645,7 @@ class Saasco {
|
|
|
635
645
|
*/
|
|
636
646
|
page() {
|
|
637
647
|
var _a, _b;
|
|
638
|
-
if (
|
|
648
|
+
if (isServer) {
|
|
639
649
|
console.warn('Saasco page tracking is only available in the browser');
|
|
640
650
|
return;
|
|
641
651
|
}
|
|
@@ -782,7 +792,7 @@ class Saasco {
|
|
|
782
792
|
// Disable auto page tracking if the config is set to false
|
|
783
793
|
if (!((_a = this.config.autoPageTracking) === null || _a === void 0 ? void 0 : _a.enabled)) return;
|
|
784
794
|
// Prevent running on the server
|
|
785
|
-
if (
|
|
795
|
+
if (isServer) return console.warn('Saasco auto page tracking is only available in the browser');
|
|
786
796
|
// Prevent intitializing auto page tracking more than once
|
|
787
797
|
if (window.saascoAutoPageTrackingActive) {
|
|
788
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.23";
|
|
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) {
|
|
@@ -588,37 +589,46 @@ 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
598
|
setAnonmousId();
|
|
609
|
-
const
|
|
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
|
})),
|
|
631
|
+
source: isBrowser ? 'client' : 'server',
|
|
622
632
|
context: JSON.stringify(context || {})
|
|
623
633
|
};
|
|
624
634
|
return this.doRequest('events', data);
|
|
@@ -631,7 +641,7 @@ class Saasco {
|
|
|
631
641
|
*/
|
|
632
642
|
page() {
|
|
633
643
|
var _a, _b;
|
|
634
|
-
if (
|
|
644
|
+
if (isServer) {
|
|
635
645
|
console.warn('Saasco page tracking is only available in the browser');
|
|
636
646
|
return;
|
|
637
647
|
}
|
|
@@ -778,7 +788,7 @@ class Saasco {
|
|
|
778
788
|
// Disable auto page tracking if the config is set to false
|
|
779
789
|
if (!((_a = this.config.autoPageTracking) === null || _a === void 0 ? void 0 : _a.enabled)) return;
|
|
780
790
|
// Prevent running on the server
|
|
781
|
-
if (
|
|
791
|
+
if (isServer) return console.warn('Saasco auto page tracking is only available in the browser');
|
|
782
792
|
// Prevent intitializing auto page tracking more than once
|
|
783
793
|
if (window.saascoAutoPageTrackingActive) {
|
|
784
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"
|