@outlit/browser 0.2.2 → 0.3.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/dist/index.d.mts +10 -4
- package/dist/index.d.ts +10 -4
- package/dist/index.js +150 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -4
- package/dist/index.mjs.map +1 -1
- package/dist/outlit.global.js +1 -1
- package/dist/outlit.global.js.map +1 -1
- package/dist/react/index.d.mts +56 -4
- package/dist/react/index.d.ts +56 -4
- package/dist/react/index.js +186 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +188 -4
- package/dist/react/index.mjs.map +1 -1
- package/dist/{tracker-DFcTv3EM.d.mts → tracker-DK-2gYCi.d.mts} +91 -1
- package/dist/{tracker-DFcTv3EM.d.ts → tracker-DK-2gYCi.d.ts} +91 -1
- package/package.json +7 -2
package/dist/react/index.mjs
CHANGED
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
buildFormEvent,
|
|
10
10
|
buildIdentifyEvent,
|
|
11
11
|
buildIngestPayload,
|
|
12
|
-
buildPageviewEvent
|
|
12
|
+
buildPageviewEvent,
|
|
13
|
+
buildStageEvent
|
|
13
14
|
} from "@outlit/core";
|
|
14
15
|
|
|
15
16
|
// src/autocapture.ts
|
|
@@ -229,6 +230,7 @@ var DEFAULT_IDLE_TIMEOUT = 3e4;
|
|
|
229
230
|
var SESSION_TIMEOUT = 30 * 60 * 1e3;
|
|
230
231
|
var TIME_UPDATE_INTERVAL = 1e3;
|
|
231
232
|
var MIN_SPURIOUS_THRESHOLD = 50;
|
|
233
|
+
var MIN_PAGE_TIME_FOR_ENGAGEMENT = 500;
|
|
232
234
|
var SESSION_ID_KEY = "outlit_session_id";
|
|
233
235
|
var SESSION_LAST_ACTIVITY_KEY = "outlit_session_last_activity";
|
|
234
236
|
var SessionTracker = class {
|
|
@@ -273,7 +275,8 @@ var SessionTracker = class {
|
|
|
273
275
|
this.updateActiveTime();
|
|
274
276
|
const totalTimeMs = Date.now() - this.state.pageEntryTime;
|
|
275
277
|
const isSpuriousEvent = this.state.activeTimeMs < MIN_SPURIOUS_THRESHOLD && totalTimeMs < MIN_SPURIOUS_THRESHOLD;
|
|
276
|
-
|
|
278
|
+
const isTooSoonAfterNavigation = totalTimeMs < MIN_PAGE_TIME_FOR_ENGAGEMENT;
|
|
279
|
+
if (!isSpuriousEvent && !isTooSoonAfterNavigation) {
|
|
277
280
|
const event = buildEngagementEvent({
|
|
278
281
|
url: this.state.currentUrl,
|
|
279
282
|
referrer: document.referrer,
|
|
@@ -614,6 +617,9 @@ var Outlit = class {
|
|
|
614
617
|
options;
|
|
615
618
|
hasHandledExit = false;
|
|
616
619
|
sessionTracker = null;
|
|
620
|
+
// User identity state for stage events
|
|
621
|
+
currentUser = null;
|
|
622
|
+
pendingUser = null;
|
|
617
623
|
constructor(options) {
|
|
618
624
|
this.publicKey = options.publicKey;
|
|
619
625
|
this.apiHost = options.apiHost ?? DEFAULT_API_HOST;
|
|
@@ -672,6 +678,10 @@ var Outlit = class {
|
|
|
672
678
|
this.initCalendarTracking();
|
|
673
679
|
}
|
|
674
680
|
this.isTrackingEnabled = true;
|
|
681
|
+
if (this.pendingUser) {
|
|
682
|
+
this.applyUser(this.pendingUser);
|
|
683
|
+
this.pendingUser = null;
|
|
684
|
+
}
|
|
675
685
|
}
|
|
676
686
|
/**
|
|
677
687
|
* Check if tracking is currently enabled.
|
|
@@ -698,12 +708,21 @@ var Outlit = class {
|
|
|
698
708
|
/**
|
|
699
709
|
* Identify the current visitor.
|
|
700
710
|
* Links the anonymous visitor to a known user.
|
|
711
|
+
*
|
|
712
|
+
* When email or userId is provided, also sets the current user identity
|
|
713
|
+
* for stage events (activate, engaged, paid).
|
|
701
714
|
*/
|
|
702
715
|
identify(options) {
|
|
703
716
|
if (!this.isTrackingEnabled) {
|
|
704
717
|
console.warn("[Outlit] Tracking not enabled. Call enableTracking() first.");
|
|
705
718
|
return;
|
|
706
719
|
}
|
|
720
|
+
if (options.email || options.userId) {
|
|
721
|
+
this.currentUser = {
|
|
722
|
+
email: options.email,
|
|
723
|
+
userId: options.userId
|
|
724
|
+
};
|
|
725
|
+
}
|
|
707
726
|
const event = buildIdentifyEvent({
|
|
708
727
|
url: window.location.href,
|
|
709
728
|
referrer: document.referrer,
|
|
@@ -713,6 +732,98 @@ var Outlit = class {
|
|
|
713
732
|
});
|
|
714
733
|
this.enqueue(event);
|
|
715
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Set the current user identity.
|
|
737
|
+
* This is useful for SPA applications where you know the user's identity
|
|
738
|
+
* after authentication. Calls identify() under the hood.
|
|
739
|
+
*
|
|
740
|
+
* If called before tracking is enabled, the identity is stored as pending
|
|
741
|
+
* and applied automatically when enableTracking() is called.
|
|
742
|
+
*
|
|
743
|
+
* Note: Both setUser() and identify() enable stage events. The difference is
|
|
744
|
+
* setUser() can be called before tracking is enabled (identity is queued),
|
|
745
|
+
* while identify() requires tracking to be enabled first.
|
|
746
|
+
*/
|
|
747
|
+
setUser(identity) {
|
|
748
|
+
if (!identity.email && !identity.userId) {
|
|
749
|
+
console.warn("[Outlit] setUser requires at least email or userId");
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (!this.isTrackingEnabled) {
|
|
753
|
+
this.pendingUser = identity;
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
this.applyUser(identity);
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Clear the current user identity.
|
|
760
|
+
* Call this when the user logs out.
|
|
761
|
+
*/
|
|
762
|
+
clearUser() {
|
|
763
|
+
this.currentUser = null;
|
|
764
|
+
this.pendingUser = null;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Apply user identity and send identify event.
|
|
768
|
+
*/
|
|
769
|
+
applyUser(identity) {
|
|
770
|
+
this.currentUser = identity;
|
|
771
|
+
this.identify({ email: identity.email, userId: identity.userId, traits: identity.traits });
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Mark the current user as activated.
|
|
775
|
+
* This is typically called after a user completes onboarding or a key activation milestone.
|
|
776
|
+
* Requires the user to be identified (via setUser or identify with userId).
|
|
777
|
+
*/
|
|
778
|
+
activate(properties) {
|
|
779
|
+
this.sendStageEvent("activated", properties);
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Mark the current user as engaged.
|
|
783
|
+
* This is typically called when a user reaches a usage milestone.
|
|
784
|
+
* Can also be computed automatically by the engagement cron.
|
|
785
|
+
*/
|
|
786
|
+
engaged(properties) {
|
|
787
|
+
this.sendStageEvent("engaged", properties);
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Mark the current user as paid.
|
|
791
|
+
* This is typically called after a successful payment/subscription.
|
|
792
|
+
* Can also be triggered by Stripe integration.
|
|
793
|
+
*/
|
|
794
|
+
paid(properties) {
|
|
795
|
+
this.sendStageEvent("paid", properties);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Mark the current user as churned.
|
|
799
|
+
* This is typically called when a subscription is cancelled.
|
|
800
|
+
* Can also be triggered by Stripe integration.
|
|
801
|
+
*/
|
|
802
|
+
churned(properties) {
|
|
803
|
+
this.sendStageEvent("churned", properties);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Internal method to send a stage event.
|
|
807
|
+
*/
|
|
808
|
+
sendStageEvent(stage, properties) {
|
|
809
|
+
if (!this.isTrackingEnabled) {
|
|
810
|
+
console.warn("[Outlit] Tracking not enabled. Call enableTracking() first.");
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
if (!this.currentUser) {
|
|
814
|
+
console.warn(
|
|
815
|
+
`[Outlit] Cannot call ${stage}() without setting user identity. Call setUser() or identify() first.`
|
|
816
|
+
);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
const event = buildStageEvent({
|
|
820
|
+
url: window.location.href,
|
|
821
|
+
referrer: document.referrer,
|
|
822
|
+
stage,
|
|
823
|
+
properties
|
|
824
|
+
});
|
|
825
|
+
this.enqueue(event);
|
|
826
|
+
}
|
|
716
827
|
/**
|
|
717
828
|
* Get the current visitor ID.
|
|
718
829
|
* Returns null if tracking is not enabled.
|
|
@@ -820,7 +931,8 @@ var Outlit = class {
|
|
|
820
931
|
async sendEvents(events) {
|
|
821
932
|
if (events.length === 0) return;
|
|
822
933
|
if (!this.visitorId) return;
|
|
823
|
-
const
|
|
934
|
+
const userIdentity = this.currentUser ?? void 0;
|
|
935
|
+
const payload = buildIngestPayload(this.visitorId, "client", events, userIdentity);
|
|
824
936
|
const url = `${this.apiHost}/api/i/v1/${this.publicKey}/events`;
|
|
825
937
|
try {
|
|
826
938
|
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
@@ -860,7 +972,8 @@ function OutlitProvider({
|
|
|
860
972
|
formFieldDenylist,
|
|
861
973
|
flushInterval,
|
|
862
974
|
autoTrack = true,
|
|
863
|
-
autoIdentify = true
|
|
975
|
+
autoIdentify = true,
|
|
976
|
+
user
|
|
864
977
|
}) {
|
|
865
978
|
const outlitRef = useRef(null);
|
|
866
979
|
const initializedRef = useRef(false);
|
|
@@ -892,6 +1005,14 @@ function OutlitProvider({
|
|
|
892
1005
|
autoTrack,
|
|
893
1006
|
autoIdentify
|
|
894
1007
|
]);
|
|
1008
|
+
useEffect(() => {
|
|
1009
|
+
if (!outlitRef.current) return;
|
|
1010
|
+
if (user && (user.email || user.userId)) {
|
|
1011
|
+
outlitRef.current.setUser(user);
|
|
1012
|
+
} else {
|
|
1013
|
+
outlitRef.current.clearUser();
|
|
1014
|
+
}
|
|
1015
|
+
}, [user]);
|
|
895
1016
|
const enableTracking = useCallback(() => {
|
|
896
1017
|
if (outlitRef.current) {
|
|
897
1018
|
outlitRef.current.enableTracking();
|
|
@@ -940,10 +1061,73 @@ function useOutlit() {
|
|
|
940
1061
|
if (!outlit) return null;
|
|
941
1062
|
return outlit.getVisitorId();
|
|
942
1063
|
}, [outlit]);
|
|
1064
|
+
const setUser = useCallback2(
|
|
1065
|
+
(identity) => {
|
|
1066
|
+
if (!outlit) {
|
|
1067
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
outlit.setUser(identity);
|
|
1071
|
+
},
|
|
1072
|
+
[outlit]
|
|
1073
|
+
);
|
|
1074
|
+
const clearUser = useCallback2(() => {
|
|
1075
|
+
if (!outlit) {
|
|
1076
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
outlit.clearUser();
|
|
1080
|
+
}, [outlit]);
|
|
1081
|
+
const activate = useCallback2(
|
|
1082
|
+
(properties) => {
|
|
1083
|
+
if (!outlit) {
|
|
1084
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
outlit.activate(properties);
|
|
1088
|
+
},
|
|
1089
|
+
[outlit]
|
|
1090
|
+
);
|
|
1091
|
+
const engaged = useCallback2(
|
|
1092
|
+
(properties) => {
|
|
1093
|
+
if (!outlit) {
|
|
1094
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
outlit.engaged(properties);
|
|
1098
|
+
},
|
|
1099
|
+
[outlit]
|
|
1100
|
+
);
|
|
1101
|
+
const paid = useCallback2(
|
|
1102
|
+
(properties) => {
|
|
1103
|
+
if (!outlit) {
|
|
1104
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
outlit.paid(properties);
|
|
1108
|
+
},
|
|
1109
|
+
[outlit]
|
|
1110
|
+
);
|
|
1111
|
+
const churned = useCallback2(
|
|
1112
|
+
(properties) => {
|
|
1113
|
+
if (!outlit) {
|
|
1114
|
+
console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
outlit.churned(properties);
|
|
1118
|
+
},
|
|
1119
|
+
[outlit]
|
|
1120
|
+
);
|
|
943
1121
|
return {
|
|
944
1122
|
track,
|
|
945
1123
|
identify,
|
|
946
1124
|
getVisitorId,
|
|
1125
|
+
setUser,
|
|
1126
|
+
clearUser,
|
|
1127
|
+
activate,
|
|
1128
|
+
engaged,
|
|
1129
|
+
paid,
|
|
1130
|
+
churned,
|
|
947
1131
|
isInitialized,
|
|
948
1132
|
isTrackingEnabled,
|
|
949
1133
|
enableTracking
|