@arthurreira/analytics 0.7.0 → 0.9.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/client.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  interface AnalyticsProps {
2
2
  apiKey: string;
3
3
  apiUrl: string;
4
+ wsUrl?: string;
4
5
  }
5
- declare function Analytics({ apiKey, apiUrl }: AnalyticsProps): null;
6
+ declare function Analytics({ apiKey, apiUrl, wsUrl }: AnalyticsProps): null;
6
7
 
7
- declare function useAnalytics(apiUrl: string, apiKey: string): {
8
+ declare function useAnalytics(apiUrl: string, apiKey: string, options?: {
9
+ wsUrl?: string;
10
+ }): {
8
11
  trackPageview: (path: string) => void;
9
12
  trackClick: (e: MouseEvent, element: HTMLElement) => void;
10
13
  trackScroll: (depth: number) => void;
package/dist/client.js CHANGED
@@ -54,7 +54,7 @@ async function createSession(apiUrl, apiKey, visitorId) {
54
54
  const response = await fetch(`${apiUrl}/sessions`, {
55
55
  method: "POST",
56
56
  headers: {
57
- "Authorization": `Bearer ${apiKey}`,
57
+ "X-API-Key": apiKey,
58
58
  "Content-Type": "application/json"
59
59
  },
60
60
  body: JSON.stringify(sessionData)
@@ -66,7 +66,7 @@ async function sendEvent(apiUrl, apiKey, payload) {
66
66
  await fetch(`${apiUrl}/events`, {
67
67
  method: "POST",
68
68
  headers: {
69
- "Authorization": `Bearer ${apiKey}`,
69
+ "X-API-Key": apiKey,
70
70
  "Content-Type": "application/json"
71
71
  },
72
72
  body: JSON.stringify(payload)
@@ -124,6 +124,50 @@ async function trackCTA(apiUrl, apiKey, sessionId, path, ctaId, ctaVariant) {
124
124
  });
125
125
  }
126
126
 
127
+ // src/lib/presence.ts
128
+ var DEFAULT_WS_URL = "wss://edge.arthurreira.dev/realtime";
129
+ function connectPresence(apiKey, sessionId, wsUrl = DEFAULT_WS_URL) {
130
+ if (typeof WebSocket === "undefined") {
131
+ return { disconnect: () => {
132
+ } };
133
+ }
134
+ let ws = null;
135
+ let attempts = 0;
136
+ let intentionalClose = false;
137
+ let retryTimer = null;
138
+ function connect() {
139
+ try {
140
+ ws = new WebSocket(wsUrl);
141
+ } catch {
142
+ return;
143
+ }
144
+ ws.onopen = () => {
145
+ attempts = 0;
146
+ ws.send(JSON.stringify({ type: "join", api_key: apiKey, session_id: sessionId }));
147
+ };
148
+ ws.onclose = () => {
149
+ if (intentionalClose || attempts >= 3) return;
150
+ const delay = Math.pow(2, attempts) * 1e3;
151
+ attempts++;
152
+ retryTimer = setTimeout(connect, delay);
153
+ };
154
+ }
155
+ connect();
156
+ return {
157
+ disconnect: () => {
158
+ intentionalClose = true;
159
+ if (retryTimer !== null) {
160
+ clearTimeout(retryTimer);
161
+ retryTimer = null;
162
+ }
163
+ if (ws) {
164
+ ws.close();
165
+ ws = null;
166
+ }
167
+ }
168
+ };
169
+ }
170
+
127
171
  // src/hooks/useAnalytics.ts
128
172
  var SESSION_EXPIRY_MINUTES = 30;
129
173
  async function getOrCreateSession(apiUrl, apiKey, visitorId) {
@@ -142,16 +186,18 @@ async function getOrCreateSession(apiUrl, apiKey, visitorId) {
142
186
  localStorage.setItem("af_session_last_activity", String(now));
143
187
  return newSessionId;
144
188
  }
145
- function useAnalytics(apiUrl, apiKey) {
189
+ function useAnalytics(apiUrl, apiKey, options) {
146
190
  const sessionId = useRef(null);
147
191
  const pendingEvents = useRef([]);
148
192
  const pathname = useRef(typeof window !== "undefined" ? window?.location?.pathname ?? "" : "");
193
+ const presence = useRef(null);
149
194
  useEffect(() => {
150
195
  if (typeof window === "undefined") return;
151
196
  const visitor_id = localStorage.getItem("af_analytics_visitor_id") || crypto.randomUUID();
152
197
  localStorage.setItem("af_analytics_visitor_id", visitor_id);
153
198
  getOrCreateSession(apiUrl, apiKey, visitor_id).then((id) => {
154
199
  sessionId.current = id;
200
+ presence.current = connectPresence(apiKey, id, options?.wsUrl);
155
201
  pendingEvents.current.forEach((fn) => fn());
156
202
  pendingEvents.current = [];
157
203
  });
@@ -160,6 +206,8 @@ function useAnalytics(apiUrl, apiKey) {
160
206
  if (typeof window === "undefined") return;
161
207
  const sendEnd = () => {
162
208
  if (!sessionId.current) return;
209
+ presence.current?.disconnect();
210
+ presence.current = null;
163
211
  navigator.sendBeacon(`${apiUrl}/sessions/${sessionId.current}/end`);
164
212
  localStorage.removeItem("af_session_id");
165
213
  localStorage.removeItem("af_session_last_activity");
@@ -209,8 +257,8 @@ function useAnalytics(apiUrl, apiKey) {
209
257
  }
210
258
 
211
259
  // src/components/Analytics.tsx
212
- function Analytics({ apiKey, apiUrl }) {
213
- const { trackPageview: trackPageview2, trackClick: trackClick2, trackScroll: trackScroll2, trackCopy: trackCopy2, trackError: trackError2 } = useAnalytics(apiUrl, apiKey);
260
+ function Analytics({ apiKey, apiUrl, wsUrl }) {
261
+ const { trackPageview: trackPageview2, trackClick: trackClick2, trackScroll: trackScroll2, trackCopy: trackCopy2, trackError: trackError2 } = useAnalytics(apiUrl, apiKey, { wsUrl });
214
262
  const lastTracked = useRef2(null);
215
263
  const lastScrollDepth = useRef2(0);
216
264
  const pathname = typeof window !== "undefined" ? window.location.pathname : "";
package/dist/index.js CHANGED
@@ -45,7 +45,7 @@ async function createSession(apiUrl, apiKey, visitorId) {
45
45
  const response = await fetch(`${apiUrl}/sessions`, {
46
46
  method: "POST",
47
47
  headers: {
48
- "Authorization": `Bearer ${apiKey}`,
48
+ "X-API-Key": apiKey,
49
49
  "Content-Type": "application/json"
50
50
  },
51
51
  body: JSON.stringify(sessionData)
@@ -57,7 +57,7 @@ async function sendEvent(apiUrl, apiKey, payload) {
57
57
  await fetch(`${apiUrl}/events`, {
58
58
  method: "POST",
59
59
  headers: {
60
- "Authorization": `Bearer ${apiKey}`,
60
+ "X-API-Key": apiKey,
61
61
  "Content-Type": "application/json"
62
62
  },
63
63
  body: JSON.stringify(payload)
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  { "name": "@arthurreira/analytics",
2
- "version": "0.7.0",
2
+ "version": "0.9.0",
3
3
  "type": "module",
4
4
  "scripts": {
5
5
  "build": "tsup",