Files
aramesh-backend/frontend/src/analytics.ts
T
aramesh-site deploy 9d0015808c feat(frontend): تحلیل رفتار با OpenPanel به‌جای اجرای نمونهٔ دوم Umami
نمونهٔ OpenPanel موجود (stats.*) با یک پروژهٔ دوم برای این سایت استفاده می‌شود؛
VITE_OPENPANEL_URL/VITE_OPENPANEL_CLIENT_ID در زمان بیلد تزریق می‌شوند و در
نبودشان همه‌چیز بی‌اثر است. API عمومی track() تغییر نکرده و مسیر Umami هم
برای عقب‌نشینی دست‌نخورده مانده.
2026-09-26 21:43:59 +00:00

66 lines
2.9 KiB
TypeScript

// لایهٔ نازک تحلیل رفتار — OpenPanel.
//
// نمونهٔ OpenPanel از قبل روی این سرور بالا است (stats.bennu-api-bahrestan.ir) و
// پروژهٔ ERP هم از همان استفاده می‌کند؛ به‌جای اجرای یک ابزار تحلیل دوم (Umami)،
// همین یک نمونه با یک «پروژهٔ» دوم برای این سایت به کار می‌رود.
//
// اگر VITE_OPENPANEL_URL و VITE_OPENPANEL_CLIENT_ID در زمان بیلد تنظیم نشده باشند،
// همهٔ فراخوانی‌ها بی‌اثر و ارزان‌اند (مثل حالت فعلی Umami).
//
// مسیر Umami دست‌نخورده مانده تا اگر اسکریپت قدیمی جایی فعال بود از کار نیفتد.
declare global {
interface Window {
op?: (...args: unknown[]) => void
umami?: { track: (event?: string, data?: Record<string, unknown>) => void }
}
}
const OP_URL = (import.meta.env?.VITE_OPENPANEL_URL as string | undefined)?.trim()
const OP_CLIENT_ID = (import.meta.env?.VITE_OPENPANEL_CLIENT_ID as string | undefined)?.trim()
const OP_SCRIPT_URL = (import.meta.env?.VITE_OPENPANEL_SCRIPT_URL as string | undefined)?.trim()
// شیم صف OpenPanel — تا رسیدن op1.js، فراخوانی‌ها در صف می‌مانند و بعد تخلیه می‌شوند.
function loadOpenPanelScript(src: string): void {
if (document.querySelector('script[data-openpanel]')) return
const shim = document.createElement('script')
shim.textContent =
'window.op=window.op||function(){var n=[];return new Proxy(function(){arguments.length&&n.push([].slice.call(arguments))},{get:function(t,r){return"q"===r?n:function(){n.push([r].concat([].slice.call(arguments)))}},has:function(t,r){return"q"===r}}) }();'
document.head.appendChild(shim)
const script = document.createElement('script')
script.src = src
script.async = true
script.defer = true
script.dataset.openpanel = '1'
document.head.appendChild(script)
}
/** یک‌بار در شروع اپ صدا زده می‌شود؛ بدون تنظیمات، هیچ کاری نمی‌کند. */
export function initAnalytics(): void {
if (!OP_URL || !OP_CLIENT_ID) return
try {
if (OP_SCRIPT_URL) loadOpenPanelScript(OP_SCRIPT_URL)
window.op?.('init', {
apiUrl: OP_URL,
clientId: OP_CLIENT_ID,
trackScreenViews: true, // بازدید صفحه → کدام صفحات دیده می‌شوند
})
} catch {
// تحلیل رفتار هرگز نباید مسیر اصلی را بشکند
}
}
/** رخداد سفارشی — در داشبورد OpenPanel نمایش داده می‌شود. */
export function track(event: string, data?: Record<string, unknown>) {
try {
window.op?.('track', event, data ?? {})
} catch {
/* ignore */
}
try {
window.umami?.track(event, data)
} catch {
/* ignore */
}
}