Spaces:
Running
Running
visilog
Browse files
client/src/utils/visitorTracking.js
CHANGED
|
@@ -30,10 +30,44 @@ function getOrCreateVisitorId() {
|
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
/**
|
| 34 |
* Records a single page visit per session to the server.
|
| 35 |
-
* This
|
| 36 |
-
* and sends it to the correct `/api/track-visit` endpoint.
|
| 37 |
*/
|
| 38 |
export async function recordVisit() {
|
| 39 |
if (typeof window === "undefined") return;
|
|
@@ -48,30 +82,14 @@ export async function recordVisit() {
|
|
| 48 |
// If sessionStorage fails, proceed anyway but might record multiple visits.
|
| 49 |
}
|
| 50 |
|
| 51 |
-
|
| 52 |
-
if (!visitorId) return;
|
| 53 |
-
|
| 54 |
-
// Asynchronously get location but don't block the main tracking event.
|
| 55 |
const location = await getCoarseLocation();
|
| 56 |
|
| 57 |
-
|
| 58 |
-
visitorId: visitorId,
|
| 59 |
path: `${window.location.pathname}${window.location.search}${window.location.hash}`,
|
| 60 |
-
|
| 61 |
location: location,
|
| 62 |
-
|
| 63 |
-
};
|
| 64 |
-
|
| 65 |
-
try {
|
| 66 |
-
fetch(getApiUrl("/api/track-visit"), {
|
| 67 |
-
method: "POST",
|
| 68 |
-
headers: { "Content-Type": "application/json" },
|
| 69 |
-
body: JSON.stringify(payload),
|
| 70 |
-
keepalive: true, // Good for fire-and-forget
|
| 71 |
-
});
|
| 72 |
-
} catch (error) {
|
| 73 |
-
console.warn("Could not send visit data to server:", error);
|
| 74 |
-
}
|
| 75 |
}
|
| 76 |
|
| 77 |
/**
|
|
|
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
| 33 |
+
/**
|
| 34 |
+
* A generic function to send any tracking event to the server.
|
| 35 |
+
* This aligns with the server's `/api/track` endpoint and Pydantic model.
|
| 36 |
+
* @param {string} eventType - The type of event (e.g., 'page_view', 'file_upload_start').
|
| 37 |
+
* @param {object} eventData - A dictionary of additional data related to the event.
|
| 38 |
+
*/
|
| 39 |
+
export async function trackEvent(eventType, eventData = {}) {
|
| 40 |
+
if (typeof window === "undefined") return;
|
| 41 |
+
|
| 42 |
+
const clientId = getOrCreateVisitorId();
|
| 43 |
+
if (!clientId) return;
|
| 44 |
+
|
| 45 |
+
const payload = {
|
| 46 |
+
client_id: clientId,
|
| 47 |
+
event_type: eventType,
|
| 48 |
+
event_data: eventData,
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
// This is a "fire-and-forget" request. We don't wait for the response,
|
| 52 |
+
// and we use `keepalive` to ensure the request is sent even if the user
|
| 53 |
+
// is navigating away from the page.
|
| 54 |
+
try {
|
| 55 |
+
fetch(getApiUrl("/api/track"), {
|
| 56 |
+
method: "POST",
|
| 57 |
+
headers: {
|
| 58 |
+
"Content-Type": "application/json",
|
| 59 |
+
},
|
| 60 |
+
body: JSON.stringify(payload),
|
| 61 |
+
keepalive: true,
|
| 62 |
+
});
|
| 63 |
+
} catch (error) {
|
| 64 |
+
console.warn("Could not send tracking event to server:", error);
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
/**
|
| 69 |
* Records a single page visit per session to the server.
|
| 70 |
+
* This now uses the generic `trackEvent` function.
|
|
|
|
| 71 |
*/
|
| 72 |
export async function recordVisit() {
|
| 73 |
if (typeof window === "undefined") return;
|
|
|
|
| 82 |
// If sessionStorage fails, proceed anyway but might record multiple visits.
|
| 83 |
}
|
| 84 |
|
| 85 |
+
// Get location data to include in the event
|
|
|
|
|
|
|
|
|
|
| 86 |
const location = await getCoarseLocation();
|
| 87 |
|
| 88 |
+
trackEvent('page_view', {
|
|
|
|
| 89 |
path: `${window.location.pathname}${window.location.search}${window.location.hash}`,
|
| 90 |
+
referrer: document.referrer,
|
| 91 |
location: location,
|
| 92 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
}
|
| 94 |
|
| 95 |
/**
|