diff --git a/desk/src/pages/onboarding/OnboardingIntro.vue b/desk/src/pages/onboarding/OnboardingIntro.vue
index c46f3f0ab..14145fac9 100644
--- a/desk/src/pages/onboarding/OnboardingIntro.vue
+++ b/desk/src/pages/onboarding/OnboardingIntro.vue
@@ -10,10 +10,15 @@
diff --git a/desk/src/pages/onboarding/SetupFavicon.vue b/desk/src/pages/onboarding/SetupFavicon.vue
index dff1e4177..c3b930df8 100644
--- a/desk/src/pages/onboarding/SetupFavicon.vue
+++ b/desk/src/pages/onboarding/SetupFavicon.vue
@@ -21,8 +21,9 @@
diff --git a/desk/src/pages/onboarding/SetupLogo.vue b/desk/src/pages/onboarding/SetupLogo.vue
index cccf9a43f..c264c7db7 100644
--- a/desk/src/pages/onboarding/SetupLogo.vue
+++ b/desk/src/pages/onboarding/SetupLogo.vue
@@ -21,8 +21,9 @@
diff --git a/desk/src/pages/onboarding/SetupName.vue b/desk/src/pages/onboarding/SetupName.vue
index beac3f8e6..5dd02c1d6 100644
--- a/desk/src/pages/onboarding/SetupName.vue
+++ b/desk/src/pages/onboarding/SetupName.vue
@@ -20,8 +20,9 @@
diff --git a/desk/src/pages/onboarding/SetupSkipEmail.vue b/desk/src/pages/onboarding/SetupSkipEmail.vue
index 69a21cd27..1215fc5e1 100644
--- a/desk/src/pages/onboarding/SetupSkipEmail.vue
+++ b/desk/src/pages/onboarding/SetupSkipEmail.vue
@@ -10,8 +10,9 @@
diff --git a/desk/src/pages/onboarding/SuccessMessage.vue b/desk/src/pages/onboarding/SuccessMessage.vue
index 53294fa16..cd6b39544 100644
--- a/desk/src/pages/onboarding/SuccessMessage.vue
+++ b/desk/src/pages/onboarding/SuccessMessage.vue
@@ -32,8 +32,13 @@
diff --git a/desk/src/pages/onboarding/email/EmailCredentials.vue b/desk/src/pages/onboarding/email/EmailCredentials.vue
index 4c61e63f2..47b410d16 100644
--- a/desk/src/pages/onboarding/email/EmailCredentials.vue
+++ b/desk/src/pages/onboarding/email/EmailCredentials.vue
@@ -34,9 +34,10 @@
diff --git a/desk/src/pages/onboarding/email/SelectService.vue b/desk/src/pages/onboarding/email/SelectService.vue
index 1516a2615..9c409544f 100644
--- a/desk/src/pages/onboarding/email/SelectService.vue
+++ b/desk/src/pages/onboarding/email/SelectService.vue
@@ -38,10 +38,11 @@
diff --git a/desk/src/pages/onboarding/email/SetupEmail.vue b/desk/src/pages/onboarding/email/SetupEmail.vue
index eb61940db..8af36829a 100644
--- a/desk/src/pages/onboarding/email/SetupEmail.vue
+++ b/desk/src/pages/onboarding/email/SetupEmail.vue
@@ -5,7 +5,9 @@
diff --git a/desk/src/pages/onboarding/email/SuccessMessage.vue b/desk/src/pages/onboarding/email/SuccessMessage.vue
index 28fe72d4c..aff318395 100644
--- a/desk/src/pages/onboarding/email/SuccessMessage.vue
+++ b/desk/src/pages/onboarding/email/SuccessMessage.vue
@@ -10,8 +10,13 @@
diff --git a/desk/src/router.js b/desk/src/router.js
index 625d5b8e2..63ed1bdc5 100644
--- a/desk/src/router.js
+++ b/desk/src/router.js
@@ -1,6 +1,7 @@
import { createRouter, createWebHistory } from "vue-router";
import { call } from "frappe-ui";
import { useAuthStore } from "@/stores/auth";
+import { init as initTelemetry } from "./telemetry";
export const WEBSITE_ROOT = "Website Root";
@@ -393,6 +394,8 @@ router.beforeEach(async (to) => {
});
router.beforeEach(async (to) => {
+ await initTelemetry();
+
const isAuthRoute = AUTH_ROUTES.includes(to.name);
const authStore = useAuthStore();
diff --git a/desk/src/telemetry.ts b/desk/src/telemetry.ts
new file mode 100644
index 000000000..9a32f929b
--- /dev/null
+++ b/desk/src/telemetry.ts
@@ -0,0 +1,57 @@
+import { useStorage } from "@vueuse/core";
+import { call } from "frappe-ui";
+import "../../../frappe/frappe/public/js/lib/posthog.js";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+declare const posthog: any;
+
+const APP = "helpdesk";
+const SITENAME = window.location.hostname;
+
+const telemetry = useStorage("telemetry", {
+ enabled: false,
+ project_id: "",
+ host: "",
+});
+
+export async function init() {
+ await set_enabled();
+ if (!telemetry.value.enabled) return;
+ try {
+ await set_credentials();
+ posthog.init(telemetry.value.project_id, {
+ api_host: telemetry.value.host,
+ autocapture: false,
+ capture_pageview: false,
+ capture_pageleave: false,
+ advanced_disable_decide: true,
+ });
+ posthog.identify(SITENAME);
+ } catch (e) {
+ console.trace("Failed to initialize telemetry", e);
+ telemetry.value.enabled = false;
+ }
+}
+
+async function set_enabled() {
+ if (telemetry.value.enabled) return;
+
+ await call("helpdesk.api.telemetry.is_enabled").then((res) => {
+ telemetry.value.enabled = res;
+ });
+}
+
+async function set_credentials() {
+ if (!telemetry.value.enabled) return;
+ if (telemetry.value.project_id && telemetry.value.host) return;
+
+ await call("helpdesk.api.telemetry.get_credentials").then((res) => {
+ telemetry.value.project_id = res.project_id;
+ telemetry.value.host = res.telemetry_host;
+ });
+}
+
+export function capture(event: string) {
+ if (!telemetry.value.enabled) return;
+ posthog.capture(`${APP}_${event}`);
+}
diff --git a/helpdesk/api/telemetry.py b/helpdesk/api/telemetry.py
new file mode 100644
index 000000000..7fd31a3e0
--- /dev/null
+++ b/helpdesk/api/telemetry.py
@@ -0,0 +1,18 @@
+import frappe
+
+
+@frappe.whitelist()
+def is_enabled():
+ return bool(
+ frappe.get_system_settings("enable_telemetry")
+ and frappe.conf.get("posthog_host")
+ and frappe.conf.get("posthog_project_id")
+ )
+
+
+@frappe.whitelist()
+def get_credentials():
+ return {
+ "project_id": frappe.conf.get("posthog_project_id"),
+ "telemetry_host": frappe.conf.get("posthog_host"),
+ }
diff --git a/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py b/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py
index 690887ae2..4df90fe27 100644
--- a/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py
+++ b/helpdesk/helpdesk/doctype/hd_ticket/hd_ticket.py
@@ -16,7 +16,6 @@
from frappe.model.mapper import get_mapped_doc
from frappe.query_builder import Case, DocType, Order
from frappe.query_builder.functions import Count
-from frappe.realtime import get_website_room
from frappe.utils import date_diff, get_datetime, now_datetime, time_diff_in_seconds
from frappe.utils.user import is_website_user
@@ -27,8 +26,7 @@
default_outgoing_email_account,
default_ticket_outgoing_email_account,
)
-
-from helpdesk.utils import publish_event
+from helpdesk.utils import publish_event, capture_event
class HDTicket(Document):
@@ -439,6 +437,8 @@ def reply_via_agent(
self.status = "Replied"
self.save()
+ capture_event("agent_replied")
+
if skip_email_workflow:
return
diff --git a/helpdesk/utils.py b/helpdesk/utils.py
index 14cb992b9..d6ffd57f9 100644
--- a/helpdesk/utils.py
+++ b/helpdesk/utils.py
@@ -3,6 +3,7 @@
import frappe
from bs4 import BeautifulSoup
from frappe.realtime import get_website_room
+from frappe.utils.telemetry import capture as _capture
def publish_event(event: str, data: dict):
@@ -10,6 +11,10 @@ def publish_event(event: str, data: dict):
frappe.publish_realtime(event, message=data, room=room, after_commit=True)
+def capture_event(event: str):
+ return _capture(event, "helpdesk")
+
+
def extract_mentions(html):
if not html:
return []