رفتن به محتوای اصلی

React و Vite

راه‌اندازی UserTrackerProvider و Hookهای آلفانا در اپلیکیشن‌های React و Vite.

برای استفاده از آلفانا در پروژه‌های React یا Vite، پیشنهاد می‌شود UserTrackerProvider را یک‌بار در سطح ریشه اپلیکیشن قرار دهید.

Provider مسئول lifecycle اصلی Tracker است. هنگام mount شدن، یک instance از UserTracker می‌سازد و init() را اجرا می‌کند. زمانی که Provider از Component Tree خارج شود نیز در مرحله cleanup، Tracker را با destroy() متوقف می‌کند.

به این شکل، لازم نیست در کامپوننت‌های مختلف به‌صورت دستی instance جداگانه‌ای از Tracker ایجاد کنید و تمام Componentهای زیر Provider می‌توانند از Hookهای آماده alphana-sdk/react استفاده کنند.

راه‌اندازی Provider#

در پروژه‌های Vite می‌توانید Provider را در فایل ورودی اپلیکیشن، برای مثال main.tsx، قرار دهید:

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>,
);

در این ساختار، تمام Componentهای داخل <App /> زیر UserTrackerProvider قرار می‌گیرند و می‌توانند به Tracker و Hookهای React آلفانا دسترسی داشته باشند.

Provider در زمان mount، config را دریافت می‌کند، UserTracker را ایجاد می‌کند و lifecycle collection را با اجرای init() شروع می‌کند.

Environment Variableها#

در Vite، متغیرهایی که باید در کد سمت مرورگر قابل استفاده باشند با پیشوند VITE_ تعریف می‌شوند.

برای App آلفانا می‌توانید مقادیر زیر را در فایل environment پروژه قرار دهید:

env
VITE_TRACKER_APP_ID=your_app_id
VITE_TRACKER_SECRET=your_app_secret

سپس این مقادیر از طریق import.meta.env در اختیار Provider قرار می‌گیرند:

tsx
config={{
  appId: import.meta.env.VITE_TRACKER_APP_ID,
  secretKey: import.meta.env.VITE_TRACKER_SECRET,
}}

این دو مقدار باید مربوط به همان Appی باشند که در داشبورد آلفانا ساخته‌اید.

Lifecycle Provider#

UserTrackerProvider lifecycle Tracker را همراه با lifecycle خودش مدیریت می‌کند.

به‌صورت خلاصه:

  1. Provider mount می‌شود.
  2. یک instance از UserTracker ساخته می‌شود.
  3. init() اجرا می‌شود و collection آغاز می‌شود.
  4. Componentهای زیر Provider از همان Tracker استفاده می‌کنند.
  5. هنگام cleanup، متد destroy() روی Tracker اجرا می‌شود.

بنابراین معمولاً نیازی نیست در Componentهای داخلی اپلیکیشن init() یا destroy() را به‌صورت دستی فراخوانی کنید.

این مسئولیت در integration React توسط Provider مدیریت می‌شود.

استفاده از useTracker#

اگر در یک Component به instance اصلی Tracker نیاز دارید، می‌توانید از useTracker() استفاده کنید:

tsx
import { useTracker } from "alphana-sdk/react";

export function TrackerDebug() {
  const tracker = useTracker();

  if (!tracker) {
    return null;
  }

  return <button onClick={() => tracker.flush()}>Flush</button>;
}

useTracker() instance فعلی UserTracker را برمی‌گرداند.

اگر Component خارج از UserTrackerProvider قرار گرفته باشد، مقدار null دریافت می‌کند. به همین دلیل بهتر است تمام بخش‌هایی که از Hookهای آلفانا استفاده می‌کنند داخل Provider Render شوند.

ثبت Pageview#

در اپلیکیشن‌هایی که Navigation بدون reload کامل صفحه انجام می‌شود، باید مطمئن شوید تغییر مسیرها به‌عنوان Pageview ثبت می‌شوند.

برای این کار می‌توانید مسیر فعلی Router را به usePageView() بدهید:

tsx
import { usePageView } from "alphana-sdk/react";

export function PageTracker({ path }: { path: string }) {
  usePageView(path);

  return null;
}

هر زمان مقدار path تغییر کند، Hook می‌تواند Pageview مربوط به مسیر جدید را ثبت کند.

نحوه دریافت path به Router مورد استفاده در پروژه شما بستگی دارد.

ثبت Goal#

برای رفتارهایی که یک هدف مشخص در محصول دارند، می‌توانید از useTrackGoal() استفاده کنید:

tsx
import { useTrackGoal } from "alphana-sdk/react";

export function SignupComplete() {
  const trackGoal = useTrackGoal();

  return (
    <button
      onClick={() =>
        trackGoal({
          key: "signup_completed",
        })
      }
    >
      تکمیل ثبت‌نام
    </button>
  );
}

در این مثال، کلیک روی دکمه یک Goal با کلید signup_completed ثبت می‌کند.

استفاده از Hook اختصاصی کمک می‌کند معنای رفتار در کد روشن باقی بماند و نیازی به دسترسی مستقیم به Tracker در هر Component نداشته باشید.

ثبت Revenue#

برای اتفاق‌های مالی می‌توانید از useTrackRevenue() استفاده کنید:

tsx
import { useTrackRevenue } from "alphana-sdk/react";

export function PaymentSuccess() {
  const trackRevenue = useTrackRevenue();

  const handlePayment = () => {
    trackRevenue({
      eventName: "purchase",
      transactionId: "order_12345",
      amount: 1490000,
      currency: "IRR",
      status: "paid",
    });
  };

  return <button onClick={handlePayment}>ثبت پرداخت</button>;
}

اطلاعات مالی مثل transactionId، amount و status باید از منبع قابل اعتماد پرداخت دریافت شوند.

جزئیات کامل در ثبت Revenue قرار دارد.

ثبت Journey Step#

اگر می‌خواهید رسیدن کاربر به یک مرحله معنادار از مسیر محصول را ثبت کنید، useTrackJourneyStep() در دسترس است:

tsx
import { useTrackJourneyStep } from "alphana-sdk/react";

export function PlanSelected() {
  const trackJourneyStep = useTrackJourneyStep();

  return (
    <button
      onClick={() =>
        trackJourneyStep({
          key: "plan_selected",
          label: "Plan selected",
        })
      }
    >
      انتخاب پلن
    </button>
  );
}

Journey Step برای milestoneهایی مناسب است که می‌خواهید در تحلیل مسیر کاربر به‌صورت مشخص قابل تشخیص باشند.

Feature Flagها#

Integration React چند Hook برای خواندن Feature Flagها در اختیار شما قرار می‌دهد.

برای دریافت map تمام Flagهای فعلی:

tsx
import { useFeatureFlags } from "alphana-sdk/react";

const flags = useFeatureFlags();

اگر فقط وضعیت یک Flag مشخص را می‌خواهید:

tsx
import { useFeatureFlag } from "alphana-sdk/react";

const enabled = useFeatureFlag("new_checkout");

useFeatureFlag() نتیجه boolean مربوط به همان Flag را برمی‌گرداند و هنگام refresh شدن Flagها، Component می‌تواند با مقدار جدید rerender شود.

A/B Testها#

برای دسترسی به assignmentهای آزمایش، Hookهای مربوط به A/B Test نیز از ورودی React صادر می‌شوند.

برای دریافت همه Assignmentها:

tsx
import { useAbTests } from "alphana-sdk/react";

const tests = useAbTests();

برای خواندن Variant یک آزمایش مشخص:

tsx
import { useAbVariant } from "alphana-sdk/react";

const variant = useAbVariant("checkout_experiment");

و اگر فقط می‌خواهید بررسی کنید کاربر داخل یک Variant مشخص قرار دارد:

tsx
import { useIsAbVariant } from "alphana-sdk/react";

const isVariantB = useIsAbVariant("checkout_experiment", "variant_b");

این Hookها به شما اجازه می‌دهند Assignment فعلی را بدون دسترسی مستقیم به UserTracker در Componentهای React استفاده کنید.

Hookهای در دسترس#

Hookها و APIهای اصلی صادرشده از alphana-sdk/react شامل موارد زیر هستند:

Hookکاربرد
useTracker()دسترسی به instance فعلی UserTracker
usePageView()ثبت Pageview هنگام تغییر مسیر
useTrackGoal()ثبت Goal
useTrackRevenue()ثبت Revenue Event
useTrackJourneyStep()ثبت milestoneهای Journey
useFeatureFlags()دریافت map تمام Feature Flagها
useFeatureFlag()بررسی وضعیت یک Feature Flag
useAbTests()دریافت Assignmentهای آزمایش
useAbVariant()دریافت Variant یک آزمایش مشخص
useIsAbVariant()بررسی حضور کاربر در یک Variant مشخص

جزئیات قرارداد، خروجی و fallback هر Hook در React Hooks توضیح داده شده است.

رفتار خارج از Provider#

Hookهای آلفانا برای استفاده زیر UserTrackerProvider طراحی شده‌اند.

اگر useTracker() خارج از Provider اجرا شود، مقدار null برمی‌گرداند. Hookهای عملیاتی نیز fallback امن دارند تا نبود Provider باعث شکستن Runtime اپلیکیشن نشود.

با این حال، fallback فقط از ایجاد خطا جلوگیری می‌کند؛ در خارج از Provider داده‌ای توسط همان عملیات در آلفانا ثبت نخواهد شد.

بنابراین اگر انتظار دارید یک Component واقعاً Goal، Revenue، Journey یا سایر telemetryها را ثبت کند، مطمئن شوید داخل محدوده Provider قرار گرفته است.

React Strict Mode#

در نمونه بالا از <StrictMode> استفاده شده است:

tsx
<StrictMode>
  <UserTrackerProvider>
    <App />
  </UserTrackerProvider>
</StrictMode>

در محیط Development، React Strict Mode ممکن است lifecycle بعضی Componentها را برای پیدا کردن side effectهای ناامن دوباره اجرا کند.

Provider lifecycle خود را مدیریت می‌کند، اما هنگام بررسی نصب در Development بهتر است رفتار Tracker را از روی Network و داده‌های واقعی collection بررسی کنید و تفاوت رفتار محیط Development و Production را در نظر داشته باشید.

بررسی نصب#

بعد از راه‌اندازی Provider، پروژه را اجرا کنید و DevTools مرورگر را باز کنید.

در بخش Network باید درخواست‌های collection آلفانا قابل مشاهده باشند:

text
POST /api/collect

سپس چند رفتار معمول مثل Navigation، Goal یا تعامل‌های موردنظر را انجام دهید و بررسی کنید داده‌ها وارد pipeline می‌شوند.

اگر درخواست collection مشاهده نمی‌شود، موارد زیر را بررسی کنید:

  • VITE_TRACKER_APP_ID مقدار صحیح داشته باشد.
  • VITE_TRACKER_SECRET مربوط به همان App باشد.
  • Provider واقعاً در ریشه App Render شده باشد.
  • دامنه فعلی با دامنه ثبت‌شده App هماهنگ باشد.
  • Console مرورگر خطای مربوط به initialization یا Network نداشته باشد.

ساختار پیشنهادی#

در یک پروژه Vite ساده، ساختار integration می‌تواند به این شکل باشد:

text
src/
├── main.tsx
├── App.tsx
├── components/
└── ...

و UserTrackerProvider فقط در main.tsx تعریف شود تا همه Componentهای برنامه از یک Tracker مشترک استفاده کنند.

در پروژه‌های بزرگ‌تر نیز همین اصل را حفظ کنید: Provider را در سطحی پایدار قرار دهید و از ساخت Tracker جداگانه برای بخش‌های مختلف اپلیکیشن خودداری کنید.