feat(frontend): تحلیل رفتار با OpenPanel بهجای اجرای نمونهٔ دوم Umami
نمونهٔ OpenPanel موجود (stats.*) با یک پروژهٔ دوم برای این سایت استفاده میشود؛ VITE_OPENPANEL_URL/VITE_OPENPANEL_CLIENT_ID در زمان بیلد تزریق میشوند و در نبودشان همهچیز بیاثر است. API عمومی track() تغییر نکرده و مسیر Umami هم برای عقبنشینی دستنخورده مانده.
This commit is contained in:
@@ -1,17 +1,65 @@
|
|||||||
// لایهٔ نازک تحلیل رفتار (Umami) — اگر اسکریپت ردیاب بارگیری نشده باشد
|
// لایهٔ نازک تحلیل رفتار — OpenPanel.
|
||||||
// (VITE_UMAMI_SRC خالی)، همهٔ فراخوانیها بیاثر و ارزاناند.
|
//
|
||||||
|
// نمونهٔ OpenPanel از قبل روی این سرور بالا است (stats.bennu-api-bahrestan.ir) و
|
||||||
|
// پروژهٔ ERP هم از همان استفاده میکند؛ بهجای اجرای یک ابزار تحلیل دوم (Umami)،
|
||||||
|
// همین یک نمونه با یک «پروژهٔ» دوم برای این سایت به کار میرود.
|
||||||
|
//
|
||||||
|
// اگر VITE_OPENPANEL_URL و VITE_OPENPANEL_CLIENT_ID در زمان بیلد تنظیم نشده باشند،
|
||||||
|
// همهٔ فراخوانیها بیاثر و ارزاناند (مثل حالت فعلی Umami).
|
||||||
|
//
|
||||||
|
// مسیر Umami دستنخورده مانده تا اگر اسکریپت قدیمی جایی فعال بود از کار نیفتد.
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
op?: (...args: unknown[]) => void
|
||||||
umami?: { track: (event?: string, data?: Record<string, unknown>) => void }
|
umami?: { track: (event?: string, data?: Record<string, unknown>) => void }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** رخداد سفارشی — نام رخداد در داشبورد Umami نمایش داده میشود. */
|
const OP_URL = (import.meta.env?.VITE_OPENPANEL_URL as string | undefined)?.trim()
|
||||||
export function track(event: string, data?: Record<string, unknown>) {
|
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 {
|
try {
|
||||||
window.umami?.track(event, data)
|
if (OP_SCRIPT_URL) loadOpenPanelScript(OP_SCRIPT_URL)
|
||||||
|
window.op?.('init', {
|
||||||
|
apiUrl: OP_URL,
|
||||||
|
clientId: OP_CLIENT_ID,
|
||||||
|
trackScreenViews: true, // بازدید صفحه → کدام صفحات دیده میشوند
|
||||||
|
})
|
||||||
} catch {
|
} 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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import "./index.css";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import { App } from "./App";
|
import { App } from "./App";
|
||||||
|
import { initAnalytics } from "./analytics";
|
||||||
|
|
||||||
|
initAnalytics();
|
||||||
|
|
||||||
const rootEl = document.getElementById("root");
|
const rootEl = document.getElementById("root");
|
||||||
if (rootEl) {
|
if (rootEl) {
|
||||||
|
|||||||
Reference in New Issue
Block a user