@arthurreira/analytics 0.3.0 → 0.5.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.js CHANGED
@@ -15,13 +15,31 @@ var BASE_FIELDS = (sessionId, eventType, path) => ({
15
15
  page_url: typeof window !== "undefined" ? window.location.href : ""
16
16
  });
17
17
  async function createSession(apiUrl, apiKey, visitorId) {
18
+ const sessionData = { visitor_id: visitorId };
19
+ if (typeof window !== "undefined") {
20
+ const nav = navigator;
21
+ sessionData.language = navigator.language || null;
22
+ sessionData.screen_width = screen.width || null;
23
+ sessionData.screen_height = screen.height || null;
24
+ sessionData.viewport_width = window.innerWidth || null;
25
+ sessionData.viewport_height = window.innerHeight || null;
26
+ sessionData.referrer = document.referrer || null;
27
+ sessionData.landing_page = window.location.pathname || null;
28
+ sessionData.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || null;
29
+ const params = new URLSearchParams(window.location.search);
30
+ sessionData.utm_source = params.get("utm_source");
31
+ sessionData.utm_medium = params.get("utm_medium");
32
+ sessionData.utm_campaign = params.get("utm_campaign");
33
+ sessionData.utm_term = params.get("utm_term");
34
+ sessionData.utm_content = params.get("utm_content");
35
+ }
18
36
  const response = await fetch(`${apiUrl}/sessions`, {
19
37
  method: "POST",
20
38
  headers: {
21
39
  "Authorization": `Bearer ${apiKey}`,
22
40
  "Content-Type": "application/json"
23
41
  },
24
- body: JSON.stringify({ visitor_id: visitorId })
42
+ body: JSON.stringify(sessionData)
25
43
  });
26
44
  const data = await response.json();
27
45
  return data.id;
@@ -88,6 +106,23 @@ async function trackCTA(apiUrl, apiKey, sessionId, path, ctaId, ctaVariant) {
88
106
  }
89
107
 
90
108
  // src/hooks/useAnalytics.ts
109
+ var SESSION_EXPIRY_MINUTES = 30;
110
+ async function getOrCreateSession(apiUrl, apiKey, visitorId) {
111
+ const storedSessionId = localStorage.getItem("af_session_id");
112
+ const lastActivity = localStorage.getItem("af_session_last_activity");
113
+ const now = Date.now();
114
+ if (storedSessionId && lastActivity) {
115
+ const minutesSinceActivity = (now - parseInt(lastActivity)) / 1e3 / 60;
116
+ if (minutesSinceActivity < SESSION_EXPIRY_MINUTES) {
117
+ localStorage.setItem("af_session_last_activity", String(now));
118
+ return storedSessionId;
119
+ }
120
+ }
121
+ const newSessionId = await createSession(apiUrl, apiKey, visitorId);
122
+ localStorage.setItem("af_session_id", newSessionId);
123
+ localStorage.setItem("af_session_last_activity", String(now));
124
+ return newSessionId;
125
+ }
91
126
  function useAnalytics(apiUrl, apiKey) {
92
127
  const sessionId = useRef(null);
93
128
  const pendingEvents = useRef([]);
@@ -96,14 +131,34 @@ function useAnalytics(apiUrl, apiKey) {
96
131
  if (typeof window === "undefined") return;
97
132
  const visitor_id = localStorage.getItem("af_analytics_visitor_id") || crypto.randomUUID();
98
133
  localStorage.setItem("af_analytics_visitor_id", visitor_id);
99
- createSession(apiUrl, apiKey, visitor_id).then((id) => {
134
+ getOrCreateSession(apiUrl, apiKey, visitor_id).then((id) => {
100
135
  sessionId.current = id;
101
136
  pendingEvents.current.forEach((fn) => fn());
102
137
  pendingEvents.current = [];
103
138
  });
104
139
  }, []);
140
+ useEffect(() => {
141
+ if (typeof window === "undefined") return;
142
+ const sendEnd = () => {
143
+ if (!sessionId.current) return;
144
+ navigator.sendBeacon(`${apiUrl}/sessions/${sessionId.current}/end`);
145
+ localStorage.removeItem("af_session_id");
146
+ localStorage.removeItem("af_session_last_activity");
147
+ };
148
+ const handleVisibility = () => {
149
+ if (document.visibilityState === "hidden") sendEnd();
150
+ };
151
+ const handleUnload = () => sendEnd();
152
+ document.addEventListener("visibilitychange", handleVisibility);
153
+ window.addEventListener("beforeunload", handleUnload);
154
+ return () => {
155
+ document.removeEventListener("visibilitychange", handleVisibility);
156
+ window.removeEventListener("beforeunload", handleUnload);
157
+ };
158
+ }, [apiUrl]);
105
159
  function enqueueOrRun(fn) {
106
160
  if (sessionId.current) {
161
+ localStorage.setItem("af_session_last_activity", String(Date.now()));
107
162
  fn();
108
163
  } else {
109
164
  pendingEvents.current.push(fn);
package/dist/index.js CHANGED
@@ -6,13 +6,31 @@ var BASE_FIELDS = (sessionId, eventType, path) => ({
6
6
  page_url: typeof window !== "undefined" ? window.location.href : ""
7
7
  });
8
8
  async function createSession(apiUrl, apiKey, visitorId) {
9
+ const sessionData = { visitor_id: visitorId };
10
+ if (typeof window !== "undefined") {
11
+ const nav = navigator;
12
+ sessionData.language = navigator.language || null;
13
+ sessionData.screen_width = screen.width || null;
14
+ sessionData.screen_height = screen.height || null;
15
+ sessionData.viewport_width = window.innerWidth || null;
16
+ sessionData.viewport_height = window.innerHeight || null;
17
+ sessionData.referrer = document.referrer || null;
18
+ sessionData.landing_page = window.location.pathname || null;
19
+ sessionData.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || null;
20
+ const params = new URLSearchParams(window.location.search);
21
+ sessionData.utm_source = params.get("utm_source");
22
+ sessionData.utm_medium = params.get("utm_medium");
23
+ sessionData.utm_campaign = params.get("utm_campaign");
24
+ sessionData.utm_term = params.get("utm_term");
25
+ sessionData.utm_content = params.get("utm_content");
26
+ }
9
27
  const response = await fetch(`${apiUrl}/sessions`, {
10
28
  method: "POST",
11
29
  headers: {
12
30
  "Authorization": `Bearer ${apiKey}`,
13
31
  "Content-Type": "application/json"
14
32
  },
15
- body: JSON.stringify({ visitor_id: visitorId })
33
+ body: JSON.stringify(sessionData)
16
34
  });
17
35
  const data = await response.json();
18
36
  return data.id;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  { "name": "@arthurreira/analytics",
2
- "version": "0.3.0",
2
+ "version": "0.5.0",
3
3
  "type": "module",
4
4
  "scripts": {
5
5
  "build": "tsup",