راهنمای نصب و API آلفانا
نصب SDK، پیکربندی، React Hooks، Tracker API، فیچر فلگ، A/B تست و راهنمای رشد و رفتار — به ترتیب فهرست کنار صفحه.
معرفی
آلفانا یک SDK رهگیری رفتار برای React، Next.js، Vanilla JS و وردپرس است. ناوبری SPA، زمان حضور، heatmap (با فیلتر مسیر اختیاری)، لاگهای زمان اجرا، ضربان نشست، فیچر فلگ، A/B تست و سیگنالهایی مثل rage click و U-turn — بدون اسکریپت شخص ثالث.
پکیج npm: alphana-sdk — ورودیها alphana-sdk و alphana-sdk/react.
کلیک، موس و اسکرول با نمونهبرداری؛ burst کلیک (rage) برای نقاط گیر.
جمع زمان به میلیثانیه به ازای هر مسیر.
pushState / replaceState / popstate و تشخیص ترک سریع صفحه (U-turn).
ارزیابی سمت سرور با هدفگیری روی ویژگیهای کاربر پس از identify().
console و خطاهای سراسری با ارسال به /logs/ingest.
بدون کوکی تحلیلگر شخص ثالث؛ شناسه بازدیدکننده در مرورگر.
نصب
آخرین نسخه روی npm (alphana-sdk) منتشر میشود. با هر package manager نصب کنید:
# npm
npm install alphana-sdk
# pnpm
pnpm add alphana-sdk
# yarn
yarn add alphana-sdk
# bun
bun add alphana-sdkنصب با Script / Google Tag Manager
اگر نمیخواهید پکیج npm نصب کنید، نسخه CDN را با یک تگ script در head یا GTM Custom HTML قرار دهید. SDK از روی data-app-id و data-secret-key خودش را مقداردهی و شروع میکند.
<script
async
src="https://storage.alphana.ir/cdn/alphana-sdk/latest/alphana-sdk.js"
data-app-id="YOUR_APP_ID"
data-secret-key="YOUR_SECRET_KEY"
></script>برای GTM یک Custom HTML Tag بسازید، همین کد را قرار دهید و Trigger را روی All Pages بگذارید.
React / Vite
UserTrackerProvider را یک بار دور کل اپ بپیچید، معمولاً در main.tsx.
// main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { UserTrackerProvider } from 'alphana-sdk/react';
import App from './App';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<UserTrackerProvider
config={{
appId: import.meta.env.VITE_TRACKER_APP_ID,
secretKey: import.meta.env.VITE_TRACKER_SECRET,
}}
>
<App />
</UserTrackerProvider>
</StrictMode>
);# .env.local
VITE_TRACKER_APP_ID=your_app_id_here
VITE_TRACKER_SECRET=your_secret_key_hereNext.js App Router
چون UserTrackerProvider از hooks استفاده میکند، باید در یک Client Component باشد.
گام ۱ — ساخت Providers component
// app/providers.tsx
'use client';
import { UserTrackerProvider } from 'alphana-sdk/react';
import type { ReactNode } from 'react';
export function Providers({ children }: { children: ReactNode }) {
return (
<UserTrackerProvider
config={{
appId: process.env.NEXT_PUBLIC_TRACKER_APP_ID!,
secretKey: process.env.NEXT_PUBLIC_TRACKER_SECRET!,
}}
>
{children}
</UserTrackerProvider>
);
}گام ۲ — استفاده در layout.tsx
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="fa" dir="rtl">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}گام ۳ — متغیرهای محیطی
# .env.local
NEXT_PUBLIC_TRACKER_APP_ID=your_app_id_here
NEXT_PUBLIC_TRACKER_SECRET=your_secret_key_hereگام ۴ — ردیابی مسیر در App Router
برای ثبت هر تغییر مسیر، usePageView(usePathname()) را در یک Client Component صدا بزنید (مثلاً داخل همان Providers یا layout).
// app/navigation-tracker.tsx
'use client';
import { usePathname } from 'next/navigation';
import { usePageView } from 'alphana-sdk/react';
export function NavigationTracker() {
usePageView(usePathname());
return null;
}// در layout یا providers، بعد از UserTrackerProvider:
import { NavigationTracker } from './navigation-tracker';
// ...
<Providers>
<NavigationTracker />
{children}
</Providers>Vanilla JS / TS
بدون هیچ فریموری — فقط یک instance از UserTracker بسازید و init() صدا بزنید.
import { UserTracker } from 'alphana-sdk';
const tracker = new UserTracker({
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
});
// یک بار در شروع برنامه فراخوانی کنید
tracker.init();
// هنگام logout یا unmount
tracker.destroy();وردپرس
برای سایتهای وردپرس از افزونه Alphana Tracker استفاده کنید — بدون npm، فقط فایل ZIP و پنل مدیریت.
مراحل نصب
- در پیشخوان وردپرس: افزونهها → افزودن → بارگذاری افزونه و فایل ZIP را انتخاب کنید؛ یا محتوای ZIP را در
wp-content/plugins/alphana-tracker/قرار دهید. - افزونه را فعال کنید.
- به تنظیمات → Alphana Tracker بروید، App ID و Secret Key را از داشبورد آلفانا وارد کنید.
- گزینه فعالسازی رهگیری را علامت بزنید و ذخیره کنید. اسکریپت روی تمام صفحات عمومی سایت تزریق میشود.
- برای ثبت هدف یا درآمد بدون کدنویسی، به دکمه/لینک در صفحه یک
idبدهید؛ سپس همان شناسه را در داشبورد در صفحه Goals یا Revenue با تریگر «کلیک روی المنت» تنظیم کنید.
<button id="signup-btn">ثبتنام</button>
<button id="checkout-btn" data-alphana-amount="1490000" data-alphana-currency="IRR">
خرید
</button>تنظیمات کامل
تمام گزینههای قابل پاس دادن به TrackerConfig:
| نام | نوع | توضیح |
|---|---|---|
appIdاجباری | string | شناسه اپ از داشبورد آلفانا؛ برای کلود اجباری است. |
secretKeyاجباری | string | کلید SDK برای Bearer token. در مرورگر با appId و دامنه ثبتشده اعتبارسنجی میشود. |
endpoint | string | آدرس رویدادها؛ پیشفرض https://api.alphana.ir/api/events. ارسال دستهای: …/batch، ضربان: …/heartbeat. |
sessionId | string | شناسه نشست ثابت؛ در غیر این صورت UUID خودکار. |
trackNavigation | boolean | ردیابی pushState/replaceState/popstate و U-turn. پیشفرض: true |
trackHeatmap | boolean | heatmap + rage click. پیشفرض: true |
trackTime | boolean | زمان تجمعی به ازای هر مسیر. پیشفرض: true |
heatmapPages | string[] | منسوخ — ثبت صفحات فقط از پنل Heatmap Pages انجام میشود. سرور خودش مسیرهای مجاز را فیلتر میکند. |
trackLogs | boolean | console.info/warn/error، onerror، unhandledrejection → /logs/ingest. پیشفرض: true |
mouseSampleRate | number (0–1) | درصد نمونهبرداری رویداد موس/اسکرول. پیشفرض: 0.3 |
maxHeatmapPoints | number | حداکثر نقاط heatmap در حافظه به ازای هر مسیر. پیشفرض: 2000 |
batchSize | number | اندازه صف قبل از flush خودکار. پیشفرض: 20 |
flushInterval | number (ms) | فاصله flush خودکار. پیشفرض: 5000 |
onEvent | (event) => void | callback همزمان برای هر رویداد emitشده. |
consentMode | "auto" | "disabled" | auto (پیشفرض): اگر ویجت رضایت کوکی در داشبورد فعال باشد، تا پذیرش کاربر ردیابی شروع نمیشود. disabled: بنر نشان داده نمیشود و ردیابی فوری است. |
رضایت کوکی / ویجتها
از SDK نسخه 2.0.5، میتوانید ویجتهای داخلسایت را از داشبورد → Widgets فعال کنید. ابتدا رضایت کوکی: محتوا و تم قابل سفارشیسازی است. اگر فعال باشد:
- تا پذیرش کاربر، هیچ ردیابیای (pageview، heatmap، replay، goal، revenue، لاگ) انجام نمیشود.
- در صورت رد، ردیابی برای آن بازدیدکننده خاموش میماند.
- انتخاب در مرورگر ذخیره میشود؛ با افزایش
versionدر تنظیمات ویجت، بنر دوباره نمایش داده میشود. - اگر ویجت غیرفعال باشد، رفتار قبلی حفظ میشود و ردیابی فوری شروع میشود.
new UserTracker({
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
// اختیاری: بنر را در کلاینت نادیده بگیرید حتی اگر در داشبورد فعال باشد
consentMode: 'auto', // یا 'disabled'
}).init();ویجت بازخورد
ویجت بازخورد امتیاز ۱ تا ۵ بههمراه نظر اختیاری را جمعآوری میکند. از داشبورد → Widgets → Feedback فعال کنید.
- پس از
delaySecondsبهصورت خودکار نمایش داده میشود. - برای هر
versionفقط یکبار (ارسال یا بستن) در localStorage ذخیره میشود. - برخلاف رضایت کوکی، این ویجت ردیابی را مسدود نمیکند.
- پاسخها در داشبورد → Widgets → Responses قابل مشاهدهاند.
ویجت نظرسنجی
ویجت نظرسنجی سؤالات مرتبشده از نوع متن، امتیاز، تکانتخابی و چندانتخابی را نمایش میدهد. از داشبورد → Widgets → Survey پیکربندی کنید.
- همان قوانین تأخیر (
delaySeconds) و یکبار در هرversionاعمال میشود. - ردیابی را مسدود نمیکند.
- پاسخها از طریق
POST /api/sdk/widget-responsesذخیره میشوند و در داشبورد لیست میشوند.
ساخت API Key
API Key آلفانا برای اتصال سرور به سرور به Public Analytics API است. این کلید با Secret Key هر اپ که SDK برای ثبت رویداد استفاده میکند تفاوت دارد و نباید در JavaScript مرورگر، اپ موبایل یا مخزن عمومی قرار بگیرد.
به اپهای متعلق به حساب و اپهای shareشده با همان کاربر دسترسی دارد.
مقدار کامل کلید فقط هنگام ساخت یا rotate نمایش داده میشود؛ آلفانا آن را بازیابی نمیکند.
با rotate، کلید قبلی بلافاصله نامعتبر و یک کلید جدید صادر میشود.
مراحل تولید کلید
- وارد داشبورد آلفانا شوید و از منوی حساب به API Keys بروید.
- روی ساخت API Key کلیک کنید. هر حساب در حال حاضر یک API Key فعال دارد.
- مقدار با پیشوند
alphana_api_را همان لحظه کپی و در Secret Manager یا متغیر محیطی سمت سرور ذخیره کنید. - اگر کلید افشا شد، از همان صفحه گزینه Rotate را بزنید و مقدار جدید را در سرویسهای مصرفکننده جایگزین کنید.
# .env — فقط سمت سرور
ALPHANA_API_KEY=alphana_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxalphana_api_… برای خواندن Public API و مدیریت اپها در backend شماست. SDK Secret هر اپ برای ingestion داده همان اپ است؛ این دو قابل جایگزینی نیستند.احراز هویت Public API
Base URL برابر https://api.alphana.ir است. در همه درخواستها API Key را در هدر Bearer بفرستید. برای پیدا کردن appId ابتدا لیست اپها را دریافت کنید.
curl --request GET \
--url https://api.alphana.ir/api/v1/apps \
--header "Authorization: Bearer $ALPHANA_API_KEY" \
--header "Accept: application/json"[
{
"id": "11111111-1111-4111-8111-111111111111",
"name": "Storefront",
"domain": "https://example.com",
"active": true,
"createdAt": "2026-07-01T10:00:00.000Z",
"updatedAt": "2026-07-20T09:15:00.000Z"
}
]بازه زمانی
endpointهای تحلیلی به appIdنیاز دارند. پارامترهای اختیاری from و to باید ISO 8601 باشند؛ مقدار date-only از ساعت ۰۰:۰۰ UTC محاسبه میشود.
curl --get \
--url https://api.alphana.ir/api/v1/sessions/overview/kpis \
--header "Authorization: Bearer $ALPHANA_API_KEY" \
--data-urlencode "appId=11111111-1111-4111-8111-111111111111" \
--data-urlencode "from=2026-07-14T00:00:00.000Z" \
--data-urlencode "to=2026-07-21T23:59:59.999Z"Rate limit و خطاها
مقدار پیشفرض ۱۲۰ درخواست در دقیقه برای هر API Key است. وضعیت مصرف در هدرهای X-RateLimit-Limit، X-RateLimit-Remaining و X-RateLimit-Reset برمیگردد. پاسخ ۴۲۹ علاوه بر Retry-After، فیلد retryAfterSeconds دارد.
Endpointها و خروجیها
Public API نسخه ۱ شامل عملیات Apps، Sessions و Growth است. تمام endpointهای زیر JSON برمیگردانند و به Bearer API Key نیاز دارند.
| متد و مسیر | ورودی | خروجی |
|---|---|---|
GET/api/v1/apps | — | آرایه اپهای قابل دسترس: id، name، domain، active، createdAt و updatedAt. |
POST/api/v1/apps | Body: name و domain | اپ ساختهشده بههمراه _id، مشخصات اپ و SDK ingestion secret یکباره. |
GET/api/v1/sessions/data-bounds | appId | firstDataAt و lastDataAt؛ اگر دادهای نباشد هر دو null هستند. |
GET/api/v1/sessions/overview/extended | appId، from؟، to؟ | KPI نشست، دکمهها و صفحات برتر، rage click، U-turn، صفحات مسئلهدار، فناوریها، کشورها، خطاها و منابع ترافیک. |
GET/api/v1/sessions/overview/kpis | appId، from؟، to؟ | current، previous و changePct برای visitors، views، visits، bounceRate و visitDurationMs. |
GET/api/v1/sessions/pageviews | appId، from؟، to؟ | آرایه path، views و uniqueVisitors مرتبشده بر اساس بازدید. |
GET/api/v1/sessions/timespent | appId، from؟، to؟ | آرایه path، totalMs، avgMs و sessions. |
GET/api/v1/sessions/user-growth | appId، from؟، to؟ | روند روزانه date، sessions، users، views و clicks بر مبنای UTC. |
GET/api/v1/sessions/traffic-heatmap | appId | هفت روز اخیر تهران: days با ۲۴ مقدار ساعتی و maxCount برای مقیاس نمودار. |
GET/api/v1/sessions/traffic-audience-activity | appId | میانگین فعالیت ۲۸ روزه در byWeekday و byHour همراه lookbackDays. |
GET/api/v1/sessions/locations/all | appId، from؟، to؟ | آرایه country، countryName، city، latitude، longitude و count. |
GET/api/v1/growth/utm | appId، from؟، to؟ | حداکثر ۱۰۰ ترکیب source، medium، campaign، term، content با sessions و visitors. |
نمونه خروجی KPI
{
"period": "lastWeek",
"compareEnabled": true,
"current": {
"visitors": 1240,
"views": 3980,
"visits": 1520,
"bounceRate": 41.7,
"visitDurationMs": 86342.5
},
"previous": {
"visitors": 1103,
"views": 3682,
"visits": 1374,
"bounceRate": 43.1,
"visitDurationMs": 81687.3
},
"changePct": {
"visitors": 12.4,
"views": 8.1,
"visits": 10.6,
"bounceRate": -3.2,
"visitDurationMs": 5.7
}
}ساخت اپ از API
curl --request POST \
--url https://api.alphana.ir/api/v1/apps \
--header "Authorization: Bearer $ALPHANA_API_KEY" \
--header "Content-Type: application/json" \
--data '{"name":"Storefront","domain":"https://example.com"}'React Hooks
وقتی از alphana-sdk/react استفاده میکنید این hooks در دسترس هستند:
| Hook | خروجی | توضیح |
|---|---|---|
useTracker() | UserTracker | null | instance tracker از context؛ بیرون از Provider برابر null است. |
usePageView(path?) | void | با تغییر path، trackPageView را صدا میزند؛ بدون path کاری نمیکند (مثلاً فقط برای App Router). |
usePageViews() | PageView[] | تمام pageview های session جاری. |
useHeatmapData(path?, refreshMs?) | HeatmapPoint[] | نقاط heatmap برای مسیر؛ بهروزرسانی با debounce (پیشفرض ۵۰۰ms). |
useTimeSpent() | Record<string, number> | زمان تجمعی به میلیثانیه به ازای هر مسیر. |
useTrackRevenue() | (payload) => void | تابع آماده برای ارسال purchase، subscription، renewal، upgrade یا refund از داخل React. |
useTrackGoal() | (payload) => void | تابع آماده برای ثبت هدفهای تبدیل مثل signup_completed یا demo_requested. |
useTrackJourneyStep() | (payload) => void | تابع آماده برای ثبت milestoneهای محصول مثل onboarding_done یا plan_selected. |
useFeatureFlags() | Record<string, boolean> | تمام فلگهای ارزیابیشده برای کاربر جاری. با هر بار identify() بهروز میشود. |
useFeatureFlagEnabled(key) | boolean | true اگر فلگ مشخصشده برای کاربر جاری فعال باشد، در غیر اینصورت false. |
مثال
import { useTracker, useTimeSpent, useHeatmapData } from 'alphana-sdk/react';
export function DebugPanel() {
const tracker = useTracker();
const timeByPath = useTimeSpent(); // Record<path, ms>
const points = useHeatmapData();
if (!tracker) return null;
return (
<div>
<p>مسیرهای با زمان ثبتشده: {Object.keys(timeByPath).length}</p>
<p>نقاط heatmap (این صفحه): {points.length}</p>
<button type="button" onClick={() => tracker.flush()}>ارسال فوری</button>
</div>
);
}Tracker API
متدهای عمومی روی instance UserTracker:
| متد | توضیح |
|---|---|
init() | شروع ردیابی. ممکن است ابتدا runtime-config و رضایت کوکی را بررسی کند؛ در SSR no-op است. مقدار this را برمیگرداند. |
destroy() | توقف listenerها و تایمرها؛ ارسال بهترین تلاش برای صف باقیمانده. |
flush() | ارسال فوری صف رویدادها به /batch (بدون await). |
trackPageView(path?) | ثبت دستی pageview برای مسیر دادهشده یا مسیر جاری. |
identify(props) | ادغام ویژگیهای کاربر برای هدفگیری فلگ؛ دوباره fetchFlags. |
trackRevenue(payload) | ثبت خرید، اشتراک، تمدید، ارتقا یا refund همراه با attribution فعلی. |
trackGoal(payload) | ثبت هدف تبدیل مثل signup_completed، lead یا trial_started. |
trackJourneyStep(payload) | ثبت milestone سفارشی در مسیر کاربر مثل onboarding_done. |
getFlags() / isFeatureEnabled(key) | خواندن فلگهای ارزیابیشده. |
onFlagsChange(fn) / fetchFlags() | اشتراک در تغییر فلگ یا درخواست مجدد ارزیابی. |
subscribe(fn) | subscriber رویداد؛ تابع unsubscribe برمیگرداند. |
getSession() | snapshot نشست (شامل visitorId). |
getPageViews() | تمام pageviewهای نشست جاری. |
getTimeSpent() | Record مسیر → میلیثانیه تجمعی. |
getHeatmapData(path?) | با path: آرایه نقاط؛ بدون آرگومان: Record همه مسیرها. |
import { UserTracker } from 'alphana-sdk';
const tracker = new UserTracker({ appId: 'id', secretKey: 'key' });
const unsubscribe = tracker.subscribe((event) => {
console.log(event.type, event);
});
tracker.init();
tracker.flush(); // اختیاری — خالی کردن صف
// unsubscribe();فیچر فلگ — معرفی
فیچر فلگ (Feature Flag) به شما امکان میدهد بدون دیپلوی مجدد، قابلیتهای مختلف را برای کاربران مختلف فعال یا غیرفعال کنید. SDK آلفانا این قابلیت را به صورت built-in ارائه میدهد.
فلگ را از داشبورد تغییر دهید — تغییر بلافاصله برای کاربران اعمال میشود.
فلگ را بر اساس email، plan، country یا هر property دیگری هدفگیری کنید.
بعد از identify() فلگها بلافاصله دوباره ارزیابی میشوند.
یک قابلیت مشکلدار را فوری غیرفعال کنید بدون نیاز به rollback.
ساخت فلگ در داشبورد
در داشبورد به بخش فیچر فلگها بروید و روی فلگ جدید کلیک کنید.
| فیلد | توضیح |
|---|---|
key | شناسه ماشینی فلگ — فقط حروف کوچک انگلیسی، اعداد، خطتیره یا زیرخط. مثال: new-checkout |
description | توضیح اختیاری برای یادآوری هدف فلگ. |
فعال/غیرفعال | وضعیت کلی فلگ. اگر غیرفعال باشد برای هیچ کاربری true نمیشود. |
شرطهای هدفگیری | اختیاری. اگر تعریف شود، همه شرطها باید برقرار باشند (AND). بدون شرط یعنی برای همه فعال است. |
استفاده در SDK
React Hooks
سادهترین روش — از hooks اختصاصی استفاده کنید:
import {
useFeatureFlagEnabled,
useFeatureFlags,
} from 'alphana-sdk/react';
// بررسی یک فلگ خاص
function CheckoutButton() {
const showNewCheckout = useFeatureFlagEnabled('new-checkout');
if (showNewCheckout) {
return <NewCheckout />;
}
return <OldCheckout />;
}
// دریافت همه فلگها
function DebugFlags() {
const flags = useFeatureFlags();
// { 'new-checkout': true, 'promo-banner': false, ... }
return <pre>{JSON.stringify(flags, null, 2)}</pre>;
}شناسایی کاربر
برای استفاده از شرطهای هدفگیری (مثل email یا plan)، ابتدا کاربر را شناسایی کنید:
import { useTracker } from 'alphana-sdk/react';
function AuthWrapper({ user }) {
const tracker = useTracker();
useEffect(() => {
if (user && tracker) {
// properties به عنوان شرطهای هدفگیری استفاده میشوند
tracker.identify({
email: user.email,
plan: user.plan, // 'trial' | 'pro' | ...
country: user.country, // 'IR' | 'US' | ...
});
}
}, [user, tracker]);
return <>{children}</>;
}Vanilla JS
const tracker = new UserTracker({
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
}).init();
// شناسایی کاربر
tracker.identify({ email: 'user@example.com', plan: 'pro' });
// بررسی فلگ
if (tracker.isFeatureEnabled('new-checkout')) {
showNewCheckout();
}
// گوش دادن به تغییرات فلگ
const unsub = tracker.onFlagsChange((flags) => {
console.log('flags updated:', flags);
});
// دریافت همه فلگها
const allFlags = tracker.getFlags();
// { 'new-checkout': true, 'promo-banner': false }شرطهای هدفگیری
هر فلگ میتواند یک یا چند شرط داشته باشد. تمام شرطها باید برقرار باشند (AND). اگر شرطی تعریف نشود، فلگ برای همه فعال است.
| operator | توضیح | مثال |
|---|---|---|
equals | مقدار دقیقاً برابر باشد (case-insensitive) | email equals user@example.com |
contains | مقدار شامل رشته مشخصشده باشد | email contains @mycompany.com |
is_in | مقدار در لیست جداشده با کاما باشد | plan is_in pro,economy,special |
userProperties که از طریق tracker.identify({...}) ارسال میکنید ارزیابی میشوند. اگر identify() فراخوانی نشده باشد، تمام شرطها به عنوان عدم تطابق در نظر گرفته میشوند.A/B تست — معرفی
A/B تست به شما امکان میدهد چند نسخه از UI یا جریان کاربر (واریانت) را همزمان اجرا کنید و نرخ تبدیل هر نسخه را با یک هدف تبدیل (Goal) مقایسه کنید. تخصیص واریانت از طریق API انجام میشود؛ رهگیری رفتار و محاسبه تبدیل با همان SDK آلفانا (pageview و کلیک) انجام میگیرد.
هر visitorId همیشه همان واریانت را میگیرد (hash قطعی).
مثلاً ۵۰٪ کنترل و ۵۰٪ واریانت B — مجموع وزنها باید ۱۰۰ باشد.
بازدید صفحه یا کلیک روی المنت — مثل قیف تبدیل.
شرکتکننده، تبدیل، نرخ و Uplift نسبت به واریانت کنترل.
running کنید — (۲) SDK را با secretKey نصب و init() کنید — (۳) با useAbVariant / tracker.getAbVariant() UI را عوض کنید — (۴) رویدادهای کاربر برای محاسبه Goal ثبت میشوند.Endpoint ارزیابی
POST https://api.alphana.ir/api/ab-tests/evaluate
Authorization: Bearer <APP_SECRET_KEY>
Origin: https://your-registered-domain.com
Content-Type: application/jsonاگر endpoint ترکر را https://api.alphana.ir/api/events گذاشتهاید، آدرس evaluate برابر است با: https://api.alphana.ir/api/ab-tests/evaluate
در مرورگر، backend علاوه بر Bearer token، دامنه Origin / Referer را با دامنه ثبتشده اپ تطبیق میدهد.
ساخت آزمایش در داشبورد
در داشبورد به A/B تست بروید و آزمایش جدید را بزنید.
| فیلد | توضیح |
|---|---|
key | شناسه SDK — فقط a-z، 0-9، خطتیره و زیرخط. مثال: checkout-cta-test |
variants | ۲ تا ۸ واریانت؛ هر کدام key، نام و weight (٪). مجموع weight = 100 |
goal | رویداد تبدیل: بازدید صفحه یا کلیک |
status | draft (پیشنویس) | running (فعال برای SDK) | paused |
conversionWindowHours | پنجره زمانی پس از اولین رویداد کاربر برای شمارش تبدیل (پیشفرض ۱۶۸ ساعت) |
countBy | visitor (یکتا) یا session |
running نباشد، endpoint evaluate واریانت برنمیگرداند. اولین واریانت در لیست بهعنوان کنترل برای محاسبه Uplift استفاده میشود.A/B تست — Vanilla JS / TS
با secretKey در کانفیگ ترکر، SDK پس از init() بهصورت خودکار واریانتها را از /ab-tests/evaluate میگیرد.
import { UserTracker } from 'alphana-sdk';
const tracker = new UserTracker({
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
endpoint: 'https://api.alphana.ir/api/events',
}).init();
tracker.onAbTestsChange((variants) => {
const variant = variants['checkout-cta-test'];
const cta = document.getElementById('cta')!;
if (variant === 'variant-b') {
cta.className = 'btn-blue';
cta.textContent = 'خرید الان';
} else {
cta.className = 'btn-green';
cta.textContent = 'ادامه خرید';
}
});
async function runCheckoutExperiment() {
await tracker.fetchAbTests(['checkout-cta-test']);
if (tracker.isAbVariant('checkout-cta-test', 'variant-b')) {
document.getElementById('cta')!.className = 'btn-blue';
} else {
document.getElementById('cta')!.className = 'btn-green';
}
}
void runCheckoutExperiment();visitorId نشست ثابت میماند. درخواستهای مرورگر با secret، appId و دامنه ثبتشده اپ کنترل میشوند؛ با این حال اگر کلید را جایی عمومی paste کردهاید، آن را rotate کنید.A/B تست — React / Vite
مثل Feature Flagها از hookهای آماده SDK استفاده کنید — نیازی به fetch دستی نیست.
// main.tsx — Provider مثل بخش Feature Flag
import { UserTrackerProvider } from 'alphana-sdk/react';
<UserTrackerProvider
config={{
appId: import.meta.env.VITE_TRACKER_APP_ID,
secretKey: import.meta.env.VITE_TRACKER_SECRET,
endpoint: 'https://api.alphana.ir/api/events',
}}
>
<App />
</UserTrackerProvider>// components/CheckoutCta.tsx
import {
useAbVariant,
useIsAbVariant,
useAbTests,
} from 'alphana-sdk/react';
export function CheckoutCta() {
const variant = useAbVariant('checkout-cta-test');
const isVariantB = useIsAbVariant('checkout-cta-test', 'variant-b');
// variant === null تا زمان بارگذاری اول evaluate
if (variant == null) {
return <button className="btn-skeleton">...</button>;
}
if (isVariantB) {
return <button className="btn-blue">خرید الان</button>;
}
return <button className="btn-green">ادامه خرید</button>;
}
// همه واریانتها:
function DebugPanel() {
const variants = useAbTests();
return <pre>{JSON.stringify(variants, null, 2)}</pre>;
}# .env.local (فقط برای توسعه — secret را در کلاینت production نگذارید)
VITE_TRACKER_APP_ID=your_app_id
VITE_TRACKER_SECRET=your_secret_key_hereA/B تست — Next.js App Router
در Client Component از همان hookهای React SDK استفاده کنید.UserTrackerProvider را در layout قرار دهید.
گام ۱ — Provider در layout
// app/providers.tsx
'use client';
import { UserTrackerProvider } from 'alphana-sdk/react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<UserTrackerProvider
config={{
appId: process.env.NEXT_PUBLIC_TRACKER_APP_ID!,
secretKey: process.env.NEXT_PUBLIC_TRACKER_SECRET!,
endpoint: 'https://api.alphana.ir/api/events',
}}
>
{children}
</UserTrackerProvider>
);
}گام ۲ — Client Component
'use client';
import { useAbVariant, useIsAbVariant } from 'alphana-sdk/react';
export function CheckoutCta() {
const variant = useAbVariant('checkout-cta-test');
const isVariantB = useIsAbVariant('checkout-cta-test', 'variant-b');
if (variant == null) {
return <button className="btn-skeleton">...</button>;
}
if (isVariantB) {
return <button className="btn-blue">خرید الان</button>;
}
return <button className="btn-green">ادامه خرید</button>;
}# .env.local
NEXT_PUBLIC_TRACKER_APP_ID=your_app_id
NEXT_PUBLIC_TRACKER_SECRET=your_secret_keypageview و کلیکها برای Goal از همان ترکر ثبت میشوند — آزمایش را در داشبورد با Goal رویداد (مثلاً click روی دکمه CTA) تعریف کنید.
هدف تبدیل (Goal)
تبدیل از روی دادههای نشست (همان رویدادهای SDK) محاسبه میشود؛ نیازی به فراخوانی جداگانه «conversion» نیست. Goal باید با رفتار واقعی کاربران همخوان باشد.
| نوع Goal | فیلدها | مثال |
|---|---|---|
page_view | path + pathMatch | مسیر /order/complete با contains |
click | elementLabel + labelMatch (+ path اختیاری) | کلیک روی دکمه با label «پرداخت» |
pathMatch
| مقدار | معنی |
|---|---|
contains | مسیر شامل رشته باشد |
exact | مسیر دقیقاً برابر |
starts_with | مسیر با پیشوند شروع شود |
regex | تطابق عبارت منظم |
usePageView در SPA/Next استفاده کنید تا مسیرها درست ثبت شوند. برای click، label المنت (مثلاً متن دکمه یا data-attribute) باید با elementLabel در Goal همخوان باشد.Growth Analytics — معرفی
قابلیتهای رشد آلفانا روی همان نصب SDK ساخته میشوند. SDK به صورت خودکار pageview، referrer، UTM و click idها را ثبت میکند؛ تیم شما فقط باید کاربران را با identify() شناسایی کند و رویدادهای درآمدی را با trackRevenue() ارسال کند.
تحلیل source، medium، campaign، term، content و click idها برای هر نشست.
نگهداری first-touch و last-touch برای نسبت دادن تبدیل و درآمد به کانالها.
ثبت خرید، اشتراک، تمدید، ارتقا و refund کنار رفتار کاربر.
ساخت گروههای پویا از کاربران بر اساس رفتار، کمپین، کشور، پلن یا ویژگیها.
دیدن عملکرد گروههای زمانی کاربران و مقایسه رشد، بازگشت یا ریزش.
UTM و Attribution
وقتی کاربر با لینک کمپین وارد سایت میشود، SDK پارامترهای UTM و click idها را از URL میخواند و به عنوان touchpoint ذخیره میکند. اولین touchpoint برای first-touch نگه داشته میشود و آخرین touchpoint برای last-touch بهروزرسانی میشود.
لینک استاندارد کمپین
https://example.com/pricing?utm_source=google&utm_medium=cpc&utm_campaign=spring_sale&utm_content=hero_cta&utm_term=analyticsتیم مارکتینگ باید این پارامترها را در تمام لینکهای تبلیغاتی، ایمیلها، شبکههای اجتماعی و همکاریهای affiliate استفاده کند:
| پارامتر | کاربرد |
|---|---|
utm_source | منبع ترافیک مثل google، instagram، newsletter |
utm_medium | نوع کانال مثل cpc، organic، email، referral |
utm_campaign | نام کمپین یا launch |
utm_term | کلمه کلیدی یا audience هدف |
utm_content | نسخه خلاقه، جایگاه لینک یا CTA |
gclid / fbclid / ttclid / msclkid | شناسه کلیک پلتفرمهای تبلیغاتی |
کاری که تیم فنی باید انجام دهد
برای UTM و Attribution، نصب معمول SDK کافی است. اگر از Next.js App Router استفاده میکنید، حتماً usePageView() را طبق بخش Next.js فعال کنید تا تغییر مسیرهای SPA هم ثبت شوند.
Revenue — ثبت درآمد و تبدیل
گزارش Revenue زمانی دقیق میشود که بعد از پرداخت موفق، تمدید، ارتقای پلن یا refund، یک رویداد درآمدی ارسال کنید. این رویداد به first-touch و last-touch کاربر وصل میشود تا درآمد هر کمپین مشخص شود.
Vanilla JS / TS
import { UserTracker } from 'alphana-sdk';
const tracker = new UserTracker({
appId: 'YOUR_APP_ID',
secretKey: 'YOUR_SECRET_KEY',
}).init();
// بعد از پرداخت موفق در checkout یا callback سمت کلاینت
tracker.trackRevenue({
eventName: 'purchase',
transactionId: 'order_12345',
orderId: 'order_12345',
amount: 1490000,
currency: 'IRR',
productId: 'pro-plan',
planId: 'pro',
coupon: 'SPRING20',
status: 'paid',
items: [
{ id: 'pro-plan', name: 'Pro Plan', quantity: 1, price: 1490000 },
],
metadata: {
billingPeriod: 'monthly',
},
});React
import { useTrackRevenue } from 'alphana-sdk/react';
export function PaymentSuccess({ order }: { order: Order }) {
const trackRevenue = useTrackRevenue();
useEffect(() => {
trackRevenue({
eventName: 'subscription',
transactionId: order.id,
amount: order.amount,
currency: order.currency,
planId: order.planSlug,
status: 'paid',
});
}, [order, trackRevenue]);
return <p>پرداخت با موفقیت انجام شد.</p>;
}تریگر کلیک روی المنت (بدون کد)
در داشبورد → Revenue یک تریگر با نوع «کلیک روی المنت» بسازید، مبلغ و ارز پیشفرض را وارد کنید و elementId را با id دکمه سایت یکی کنید. در صورت نیاز میتوانید مبلغ را با data-attribute روی المنت override کنید:
<button
id="checkout-btn"
data-alphana-amount="1490000"
data-alphana-currency="IRR"
data-alphana-event-name="purchase"
>
تکمیل خرید
</button>Segments و Cohorts
سگمنتها و کوهورتها در داشبورد از دادههایی ساخته میشوند که SDK جمعآوری میکند: نشستها، UTM، کشور، دستگاه، صفحات دیدهشده، درآمد و ویژگیهای کاربر. برای اینکه این بخشها واقعاً مفید شوند، باید بعد از login یا signup کاربر را شناسایی کنید.
شناسایی کاربر و ویژگیهای هدفگیری
tracker.identify({
id: user.id,
email: user.email,
plan: user.plan, // trial | pro | enterprise
role: user.role, // admin | member
country: user.country, // IR | DE | ...
companySize: user.companySize,
});بعد از این مرحله میتوانید در داشبورد سگمنتهایی مثل «کاربران پلن pro از Google Ads»، «کاربران ایران»، «کاربران newsletter که خرید نکردهاند» یا «کاربران دارای revenue» بسازید.
کوهورتها چطور کار میکنند؟
کوهورتها کاربران را بر اساس زمان اولین مشاهده، signup یا purchase گروهبندی میکنند. سپس میتوانید ببینید هر گروه در هفتهها یا ماههای بعد چه تعداد نشست، بازگشت یا درآمد ایجاد کرده است.
چکلیست استفاده برای تیمها
| تیم | کار لازم |
|---|---|
| Engineering | SDK را نصب کند، appId/secretKey را تنظیم کند، identify و trackRevenue را در نقاط درست صدا بزند. |
| Marketing | برای همه کمپینها UTM استاندارد و نامگذاری ثابت تعریف کند. |
| Product | سگمنتها، کوهورتها و conversionهای مهم را مشخص کند. |
| Data / Growth | مدل attribution، بازه گزارشگیری و تعریف revenue/refund را با تیمها هماهنگ کند. |
| QA | با یک لینک UTM تستی وارد شود، login کند، پرداخت تستی بزند و داشبورد UTM/Revenue/Attribution را بررسی کند. |
QA flow:
1. Open /?utm_source=qa&utm_medium=test&utm_campaign=growth_docs
2. Sign up or log in
3. Call tracker.identify({...})
4. Complete a test purchase
5. Verify Dashboard → UTM, Revenue, Attribution, Segments, CohortsBehavior Analytics — معرفی
بخش Behavior برای پاسخ به سه سؤال اصلی ساخته شده است: کاربران چه هدفهایی را کامل میکنند، از چه مسیرهایی عبور میکنند و آیا دوباره برمیگردند یا نه. Pageview و visitorId به صورت خودکار ثبت میشوند؛ تیم فنی فقط باید هدفها و milestoneهای مهم را نامگذاری و ارسال کند.
رویدادهای تبدیل مثل signup، lead، trial_start یا activation.
صفحات ورود، انتقال بین صفحات و milestoneهای سفارشی محصول.
بازگشت کاربران در نشستهای بعدی بر اساس visitorId و identify.
Goals — ثبت هدفهای تبدیل
Goal یعنی یک نتیجه مهم برای کسبوکار یا محصول؛ مثل ثبتنام کامل، ارسال فرم دمو، شروع trial، افزودن به سبد یا تکمیل onboarding. تیم محصول ابتدا goal key را در داشبورد، صفحه Goals تعریف میکند؛ سپس تیم فنی همان key را در SDK ارسال میکند.
tracker.trackGoal({
key: 'signup_completed',
name: 'Signup completed',
value: 1,
metadata: {
source: 'pricing_page',
},
});import { useTrackGoal } from 'alphana-sdk/react';
export function SignupSuccess() {
const trackGoal = useTrackGoal();
useEffect(() => {
trackGoal({ key: 'signup_completed', name: 'Signup completed' });
}, [trackGoal]);
return <p>ثبتنام کامل شد.</p>;
}demo_requested یا trial_started.تریگر کلیک روی المنت (بدون کد)
در داشبورد → Goals تریگر را روی «کلیک روی المنت» بگذارید و شناسه HTML را وارد کنید. این بخش فقط برای هدفها است؛ درآمد را از صفحه Revenue پیکربندی کنید.
<button id="signup-btn">ثبتنام</button>Journeys — مسیر کاربران
آلفانا مسیر کاربران را از pageviewهای خودکار میسازد. اگر در محصول milestoneهایی دارید که الزاماً تغییر URL ندارند، آنها را با trackJourneyStep() ثبت کنید.
tracker.trackJourneyStep({
key: 'plan_selected',
label: 'Plan selected',
metadata: {
plan: 'pro',
},
});برای SPAها و Next.js App Router، طبق بخش نصب Next.js مطمئن شوید کهusePageView() روی تغییر مسیرها اجرا میشود؛ در غیر این صورت journey فقط اولین pageview را دارد.
Retention — بازگشت کاربران
Retention از نشستهای تکراری یک visitor ساخته میشود. SDK به صورت خودکار visitorId را در مرورگر نگه میدارد، اما برای دقت بیشتر بین دستگاهها یا بعد از login، حتماً identify() را صدا بزنید.
tracker.identify({
id: user.id,
email: user.email,
plan: user.plan,
});تیم محصول باید بازه تحلیل را مشخص کند: retention روزانه برای محصولهای پرتکرار، هفتگی برای SaaS و ماهانه برای خریدهای با فاصله بیشتر مناسبتر است.