@outlit/browser 0.4.0 → 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.
@@ -4,6 +4,7 @@ import { createContext, useCallback, useEffect, useRef, useState } from "react";
4
4
  // src/tracker.ts
5
5
  import {
6
6
  DEFAULT_API_HOST,
7
+ buildBillingEvent,
7
8
  buildCalendarEvent,
8
9
  buildCustomEvent,
9
10
  buildFormEvent,
@@ -709,7 +710,7 @@ var Outlit = class {
709
710
  * Links the anonymous visitor to a known user.
710
711
  *
711
712
  * When email or userId is provided, also sets the current user identity
712
- * for stage events (activate, engaged, paid).
713
+ * for stage events (activate, engaged, inactive).
713
714
  */
714
715
  identify(options) {
715
716
  if (!this.isTrackingEnabled) {
@@ -770,37 +771,22 @@ var Outlit = class {
770
771
  this.identify({ email: identity.email, userId: identity.userId, traits: identity.traits });
771
772
  }
772
773
  /**
773
- * Mark the current user as activated.
774
- * This is typically called after a user completes onboarding or a key activation milestone.
775
- * Requires the user to be identified (via setUser or identify with userId).
774
+ * User namespace methods for contact journey stages.
776
775
  */
777
- activate(properties) {
778
- this.sendStageEvent("activated", properties);
779
- }
780
- /**
781
- * Mark the current user as engaged.
782
- * This is typically called when a user reaches a usage milestone.
783
- * Can also be computed automatically by the engagement cron.
784
- */
785
- engaged(properties) {
786
- this.sendStageEvent("engaged", properties);
787
- }
788
- /**
789
- * Mark the current user as paid.
790
- * This is typically called after a successful payment/subscription.
791
- * Can also be triggered by Stripe integration.
792
- */
793
- paid(properties) {
794
- this.sendStageEvent("paid", properties);
795
- }
776
+ user = {
777
+ identify: (options) => this.identify(options),
778
+ activate: (properties) => this.sendStageEvent("activated", properties),
779
+ engaged: (properties) => this.sendStageEvent("engaged", properties),
780
+ inactive: (properties) => this.sendStageEvent("inactive", properties)
781
+ };
796
782
  /**
797
- * Mark the current user as churned.
798
- * This is typically called when a subscription is cancelled.
799
- * Can also be triggered by Stripe integration.
783
+ * Customer namespace methods for billing status.
800
784
  */
801
- churned(properties) {
802
- this.sendStageEvent("churned", properties);
803
- }
785
+ customer = {
786
+ trialing: (options) => this.sendBillingEvent("trialing", options),
787
+ paid: (options) => this.sendBillingEvent("paid", options),
788
+ churned: (options) => this.sendBillingEvent("churned", options)
789
+ };
804
790
  /**
805
791
  * Internal method to send a stage event.
806
792
  */
@@ -823,6 +809,26 @@ var Outlit = class {
823
809
  });
824
810
  this.enqueue(event);
825
811
  }
812
+ sendBillingEvent(status, options) {
813
+ if (!this.isTrackingEnabled) {
814
+ console.warn("[Outlit] Tracking not enabled. Call enableTracking() first.");
815
+ return;
816
+ }
817
+ if (!options.customerId && !options.stripeCustomerId && !options.domain) {
818
+ console.warn("[Outlit] customer.* requires customerId, stripeCustomerId, or domain");
819
+ return;
820
+ }
821
+ const event = buildBillingEvent({
822
+ url: window.location.href,
823
+ referrer: document.referrer,
824
+ status,
825
+ customerId: options.customerId,
826
+ stripeCustomerId: options.stripeCustomerId,
827
+ domain: options.domain,
828
+ properties: options.properties
829
+ });
830
+ this.enqueue(event);
831
+ }
826
832
  /**
827
833
  * Get the current visitor ID.
828
834
  * Returns null if tracking is not enabled.
@@ -939,8 +945,11 @@ var Outlit = class {
939
945
  const blob = new Blob([JSON.stringify(payload)], { type: "application/json" });
940
946
  const sent = navigator.sendBeacon(url, blob);
941
947
  if (sent) return;
948
+ console.warn(
949
+ `[Outlit] sendBeacon failed for ${events.length} events, falling back to fetch`
950
+ );
942
951
  }
943
- await fetch(url, {
952
+ const response = await fetch(url, {
944
953
  method: "POST",
945
954
  headers: {
946
955
  "Content-Type": "application/json"
@@ -948,8 +957,13 @@ var Outlit = class {
948
957
  body: JSON.stringify(payload),
949
958
  keepalive: true
950
959
  });
960
+ if (!response.ok) {
961
+ console.warn(
962
+ `[Outlit] Server returned ${response.status} when sending ${events.length} events`
963
+ );
964
+ }
951
965
  } catch (error) {
952
- console.warn("[Outlit] Failed to send events:", error);
966
+ console.warn(`[Outlit] Failed to send ${events.length} events:`, error);
953
967
  }
954
968
  }
955
969
  };
@@ -1057,6 +1071,16 @@ function useOutlit() {
1057
1071
  },
1058
1072
  [outlit]
1059
1073
  );
1074
+ const userIdentify = useCallback2(
1075
+ (options) => {
1076
+ if (!outlit) {
1077
+ console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1078
+ return;
1079
+ }
1080
+ outlit.user.identify(options);
1081
+ },
1082
+ [outlit]
1083
+ );
1060
1084
  const getVisitorId = useCallback2(() => {
1061
1085
  if (!outlit) return null;
1062
1086
  return outlit.getVisitorId();
@@ -1084,7 +1108,7 @@ function useOutlit() {
1084
1108
  console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1085
1109
  return;
1086
1110
  }
1087
- outlit.activate(properties);
1111
+ outlit.user.activate(properties);
1088
1112
  },
1089
1113
  [outlit]
1090
1114
  );
@@ -1094,27 +1118,47 @@ function useOutlit() {
1094
1118
  console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1095
1119
  return;
1096
1120
  }
1097
- outlit.engaged(properties);
1121
+ outlit.user.engaged(properties);
1098
1122
  },
1099
1123
  [outlit]
1100
1124
  );
1101
- const paid = useCallback2(
1125
+ const inactive = useCallback2(
1102
1126
  (properties) => {
1103
1127
  if (!outlit) {
1104
1128
  console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1105
1129
  return;
1106
1130
  }
1107
- outlit.paid(properties);
1131
+ outlit.user.inactive(properties);
1132
+ },
1133
+ [outlit]
1134
+ );
1135
+ const trialing = useCallback2(
1136
+ (options) => {
1137
+ if (!outlit) {
1138
+ console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1139
+ return;
1140
+ }
1141
+ outlit.customer.trialing(options);
1142
+ },
1143
+ [outlit]
1144
+ );
1145
+ const paid = useCallback2(
1146
+ (options) => {
1147
+ if (!outlit) {
1148
+ console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1149
+ return;
1150
+ }
1151
+ outlit.customer.paid(options);
1108
1152
  },
1109
1153
  [outlit]
1110
1154
  );
1111
1155
  const churned = useCallback2(
1112
- (properties) => {
1156
+ (options) => {
1113
1157
  if (!outlit) {
1114
1158
  console.warn("[Outlit] Not initialized. Make sure OutlitProvider is mounted.");
1115
1159
  return;
1116
1160
  }
1117
- outlit.churned(properties);
1161
+ outlit.customer.churned(options);
1118
1162
  },
1119
1163
  [outlit]
1120
1164
  );
@@ -1124,10 +1168,17 @@ function useOutlit() {
1124
1168
  getVisitorId,
1125
1169
  setUser,
1126
1170
  clearUser,
1127
- activate,
1128
- engaged,
1129
- paid,
1130
- churned,
1171
+ user: {
1172
+ identify: userIdentify,
1173
+ activate,
1174
+ engaged,
1175
+ inactive
1176
+ },
1177
+ customer: {
1178
+ trialing,
1179
+ paid,
1180
+ churned
1181
+ },
1131
1182
  isInitialized,
1132
1183
  isTrackingEnabled,
1133
1184
  enableTracking