Track Plausible analytics events for the goals feature.
Log goal creation, group management, tab usage, deletions, and goals reached on import to measure feature adoption and completion. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+30
-2
@@ -136,6 +136,7 @@ function setupNav() {
|
||||
btn.classList.add("active");
|
||||
document.getElementById(`tab-${btn.dataset.tab}`).classList.add("active");
|
||||
if (btn.dataset.tab === "history") loadHistoryTab();
|
||||
if (btn.dataset.tab === "goals") trackEvent("Goals Tab");
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -773,7 +774,10 @@ function bindGoalActions(panel) {
|
||||
btn.addEventListener("click", async () => {
|
||||
if (!confirm(t("goals.deleteConfirm"))) return;
|
||||
const res = await fetch(`${apiBase()}/goals/${btn.dataset.goalId}`, { method: "DELETE" });
|
||||
if (res.ok) await loadGoals();
|
||||
if (res.ok) {
|
||||
trackEvent("Goal Delete");
|
||||
await loadGoals();
|
||||
}
|
||||
renderGoals();
|
||||
});
|
||||
});
|
||||
@@ -783,7 +787,10 @@ function bindGoalActions(panel) {
|
||||
const name = btn.dataset.groupName;
|
||||
if (!confirm(t("goals.deleteGroupConfirm", { name }))) return;
|
||||
const res = await fetch(`${apiBase()}/goal-groups/${btn.dataset.groupId}`, { method: "DELETE" });
|
||||
if (res.ok) await loadGoals();
|
||||
if (res.ok) {
|
||||
trackEvent("Goal Group Delete");
|
||||
await loadGoals();
|
||||
}
|
||||
renderGoals();
|
||||
});
|
||||
});
|
||||
@@ -794,6 +801,9 @@ function bindGoalActions(panel) {
|
||||
for (const id of ids) {
|
||||
await fetch(`${apiBase()}/goals/${id}`, { method: "DELETE" });
|
||||
}
|
||||
if (ids.length) {
|
||||
trackEvent("Goals Clear Completed", { count: String(ids.length) });
|
||||
}
|
||||
await loadGoals();
|
||||
renderGoals();
|
||||
});
|
||||
@@ -903,6 +913,7 @@ function renderGoals() {
|
||||
alert(t("goals.groupCreateFailed"));
|
||||
return;
|
||||
}
|
||||
trackEvent("Goal Group Create", { source: "goals_tab" });
|
||||
await loadGoals();
|
||||
renderGoals();
|
||||
});
|
||||
@@ -954,6 +965,7 @@ async function openGoalModal(item) {
|
||||
<option value="new">${esc(t("goals.newGroup"))}</option>`;
|
||||
|
||||
modal.hidden = false;
|
||||
trackEvent("Goal Modal Open");
|
||||
}
|
||||
|
||||
function closeGoalModal() {
|
||||
@@ -975,6 +987,7 @@ async function submitGoalModal() {
|
||||
}
|
||||
|
||||
let groupId = null;
|
||||
let newGroupFromModal = false;
|
||||
const groupVal = document.getElementById("goal-modal-group").value;
|
||||
if (groupVal === "new") {
|
||||
const name = document.getElementById("goal-modal-new-group").value.trim();
|
||||
@@ -995,6 +1008,7 @@ async function submitGoalModal() {
|
||||
}
|
||||
const gData = await gRes.json();
|
||||
groupId = gData.id;
|
||||
newGroupFromModal = true;
|
||||
} else if (groupVal) {
|
||||
groupId = parseInt(groupVal, 10);
|
||||
}
|
||||
@@ -1011,6 +1025,15 @@ async function submitGoalModal() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newGroupFromModal) {
|
||||
trackEvent("Goal Group Create", { source: "modal" });
|
||||
}
|
||||
trackEvent("Goal Create", {
|
||||
source: "inventory",
|
||||
group: newGroupFromModal ? "new" : groupId ? "existing" : "none",
|
||||
immediate: result.completed_at ? "true" : "false",
|
||||
});
|
||||
|
||||
closeGoalModal();
|
||||
await loadGoals();
|
||||
renderGoals();
|
||||
@@ -1026,6 +1049,11 @@ function showGoalsCompletedBanner(result) {
|
||||
return;
|
||||
}
|
||||
|
||||
trackEvent("Goals Reached", {
|
||||
goals: String(completed.length),
|
||||
groups: String(groupsDone.length),
|
||||
});
|
||||
|
||||
const items = completed.map((goal) => {
|
||||
const groupPrefix = goal.group_name
|
||||
? t("goals.completedItemGroup", { name: goal.group_name })
|
||||
|
||||
Reference in New Issue
Block a user