Skip to main content

useSubscriptionTracking

Access subscription tracking methods to monitor subscription lifecycle events.
function useSubscriptionTracking(): {
  trackSubscriptionStarted: (properties: SubscriptionProperties) => void;
  trackSubscriptionUpgraded: (properties: SubscriptionProperties & { previous_plan?: string }) => void;
  trackSubscriptionDowngraded: (properties: SubscriptionProperties & { previous_plan?: string }) => void;
  trackSubscriptionCanceled: (properties: SubscriptionProperties & { cancellation_reason?: string }) => void;
  trackSubscriptionPaused: (properties: SubscriptionProperties) => void;
  trackSubscriptionReactivated: (properties: SubscriptionProperties) => void;
  trackTrialStarted: (properties: SubscriptionProperties) => void;
  trackTrialConverted: (properties: SubscriptionProperties) => void;
  trackTrialExpired: (properties: SubscriptionProperties) => void;
  trackPaymentFailed: (properties: PaymentEventProperties) => void;
  trackPaymentSucceeded: (properties: PaymentEventProperties) => void;
  getSubscriptionData: () => SubscriptionProperties | null;
}

Return Values

trackSubscriptionStarted
function
Track when a user starts a new subscription
trackSubscriptionUpgraded
function
Track when a user upgrades their subscription plan
trackSubscriptionDowngraded
function
Track when a user downgrades their subscription plan
trackSubscriptionCanceled
function
Track when a user cancels their subscription
trackSubscriptionPaused
function
Track when a subscription is paused
trackSubscriptionReactivated
function
Track when a canceled or paused subscription is reactivated
trackTrialStarted
function
Track when a user starts a trial period
trackTrialConverted
function
Track when a trial converts to a paid subscription
trackTrialExpired
function
Track when a trial expires without conversion
trackPaymentFailed
function
Track failed payment attempts
trackPaymentSucceeded
function
Track successful payment events
getSubscriptionData
function
Retrieve current subscription data from storageReturns SubscriptionProperties | null

Usage Example

import { useSubscriptionTracking } from "mentiq-sdk";

function SubscriptionManager() {
  const {
    trackSubscriptionStarted,
    trackSubscriptionUpgraded,
    trackSubscriptionCanceled,
    trackPaymentSucceeded,
    getSubscriptionData,
  } = useSubscriptionTracking();

  const handleUpgrade = async (newPlan: string) => {
    const currentSub = getSubscriptionData();
    
    trackSubscriptionUpgraded({
      status: "active",
      plan_id: newPlan,
      plan_name: "Pro",
      plan_tier: "pro",
      mrr: 4900, // $49.00 in cents
      currency: "usd",
      billing_interval: "month",
      previous_plan: currentSub?.plan_name,
    });
  };

  const handleCancellation = (reason: string) => {
    trackSubscriptionCanceled({
      status: "canceled",
      plan_id: "pro_monthly",
      cancel_at_period_end: true,
      cancellation_reason: reason,
      canceled_at: new Date().toISOString(),
    });
  };

  return (
    <div>
      <button onClick={() => handleUpgrade("pro_monthly")}>
        Upgrade to Pro
      </button>
      <button onClick={() => handleCancellation("Too expensive")}>
        Cancel Subscription
      </button>
    </div>
  );
}

useChurnRisk

Monitor customer churn risk in real-time with automatic refresh and callback triggers.
function useChurnRisk(options?: {
  refreshInterval?: number;
  onHighRisk?: (risk: ChurnRiskMetrics) => void;
  onCriticalRisk?: (risk: ChurnRiskMetrics) => void;
}): {
  churnRisk: ChurnRiskMetrics | null;
  isLoading: boolean;
  isHighRisk: boolean;
  isCriticalRisk: boolean;
  refresh: () => ChurnRiskMetrics | null;
}

Parameters

Return Values

churnRisk
ChurnRiskMetrics | null
Current churn risk metrics including score, category, and contributing factors
isLoading
boolean
Whether churn risk calculation is in progress
isHighRisk
boolean
True if risk category is “high” or “critical”
isCriticalRisk
boolean
True if risk category is “critical”
refresh
function
Manually trigger churn risk recalculation. Returns updated ChurnRiskMetrics | null

Usage Example

import { useChurnRisk } from "mentiq-sdk";
import { useState } from "react";

function ChurnDashboard() {
  const [showIntervention, setShowIntervention] = useState(false);

  const { churnRisk, isLoading, isHighRisk, isCriticalRisk, refresh } = useChurnRisk({
    refreshInterval: 30000, // Check every 30 seconds
    onHighRisk: (risk) => {
      console.log("High churn risk detected:", risk);
      setShowIntervention(true);
    },
    onCriticalRisk: (risk) => {
      // Send alert to customer success team
      sendAlertToCSTeam(risk);
    },
  });

  if (isLoading) return <div>Calculating churn risk...</div>;

  return (
    <div>
      <h2>Churn Risk Monitor</h2>
      {churnRisk && (
        <div>
          <div className={`risk-badge ${churnRisk.risk_category}`}>
            {churnRisk.risk_category.toUpperCase()} RISK
          </div>
          <p>Risk Score: {churnRisk.risk_score}/100</p>
          <p>Days Since Active: {churnRisk.factors.days_since_last_active}</p>
          <p>Engagement Score: {churnRisk.factors.engagement_score}</p>
          {churnRisk.intervention_recommended && (
            <button onClick={() => setShowIntervention(true)}>
              Start Intervention
            </button>
          )}
        </div>
      )}
      <button onClick={refresh}>Refresh Now</button>
    </div>
  );
}

useSubscriptionData

Access current subscription data with automatic refresh and convenience flags.
function useSubscriptionData(): {
  subscription: SubscriptionProperties | null;
  isLoading: boolean;
  isPaidUser: boolean;
  isTrialing: boolean;
  isCanceled: boolean;
  willCancelAtPeriodEnd: boolean;
  refresh: () => void;
}

Return Values

subscription
SubscriptionProperties | null
Complete subscription object with all properties. See SubscriptionProperties for full schema.
isLoading
boolean
Whether subscription data is being loaded
isPaidUser
boolean
True if subscription status is “active” or “trialing”
isTrialing
boolean
True if subscription status is “trialing”
isCanceled
boolean
True if subscription status is “canceled”
willCancelAtPeriodEnd
boolean
True if subscription is set to cancel at end of current billing period
refresh
function
Manually refresh subscription data from storage

Usage Example

import { useSubscriptionData } from "mentiq-sdk";

function SubscriptionStatus() {
  const {
    subscription,
    isLoading,
    isPaidUser,
    isTrialing,
    willCancelAtPeriodEnd,
    refresh,
  } = useSubscriptionData();

  if (isLoading) return <div>Loading subscription...</div>;

  if (!subscription) {
    return <div>No active subscription</div>;
  }

  return (
    <div>
      <h2>Your Subscription</h2>
      <p>Plan: {subscription.plan_name}</p>
      <p>Status: {subscription.status}</p>
      
      {isPaidUser && <span className="badge">Paid User</span>}
      {isTrialing && (
        <p>Trial ends: {new Date(subscription.trial_end!).toLocaleDateString()}</p>
      )}
      
      {willCancelAtPeriodEnd && (
        <div className="alert">
          Your subscription will cancel on{" "}
          {new Date(subscription.current_period_end!).toLocaleDateString()}
        </div>
      )}
      
      <button onClick={refresh}>Refresh Status</button>
    </div>
  );
}

useSubscriptionAutoDetect

Manually trigger subscription auto-detection from common payment providers.
function useSubscriptionAutoDetect(): {
  detect: () => Promise<{
    detected: boolean;
    provider?: string;
    confidence: number;
  } | null>;
  isDetecting: boolean;
  result: {
    detected: boolean;
    provider?: string;
    confidence: number;
  } | null;
}

Return Values

detect
function
Trigger subscription detection. Returns a promise with detection results:
isDetecting
boolean
Whether auto-detection is currently running
result
object | null
Last detection result, or null if detection hasn’t run

Usage Example

import { useSubscriptionAutoDetect } from "mentiq-sdk";
import { useEffect } from "react";

function SubscriptionDetector() {
  const { detect, isDetecting, result } = useSubscriptionAutoDetect();

  useEffect(() => {
    // Auto-detect on component mount
    detect();
  }, []);

  const handleManualDetect = async () => {
    const detection = await detect();
    
    if (detection?.detected) {
      console.log(`Subscription detected from ${detection.provider}`);
      console.log(`Confidence: ${detection.confidence * 100}%`);
    } else {
      console.log("No subscription detected");
    }
  };

  return (
    <div>
      <button onClick={handleManualDetect} disabled={isDetecting}>
        {isDetecting ? "Detecting..." : "Detect Subscription"}
      </button>
      
      {result && (
        <div>
          {result.detected ? (
            <p>
              Detected {result.provider} subscription 
              ({Math.round(result.confidence * 100)}% confidence)
            </p>
          ) : (
            <p>No subscription detected</p>
          )}
        </div>
      )}
    </div>
  );
}

useSyncSubscription

Automatically sync subscription state changes and track lifecycle events.
function useSyncSubscription(
  subscription: SubscriptionProperties | null | undefined,
  options?: {
    trackChanges?: boolean;
  }
): void

Parameters

Behavior

This hook automatically:
  • Stores subscription data in localStorage
  • Compares with previous subscription state
  • Tracks appropriate events when changes are detected:
    • Upgrade: When MRR increases or plan changes to higher tier
    • Downgrade: When MRR decreases or plan changes to lower tier
    • Cancellation: When status changes to “canceled”
    • Reactivation: When status changes from “canceled” to “active”
    • Trial Conversion: When status changes from “trialing” to “active”

Usage Example

import { useSyncSubscription } from "mentiq-sdk";
import { useSubscription } from "@/hooks/useSubscription"; // Your custom hook

function App() {
  // Get subscription from your database or payment provider
  const { data: subscription } = useSubscription();

  // Automatically sync and track changes
  useSyncSubscription(subscription, {
    trackChanges: true, // Enable automatic event tracking
  });

  return <div>Your app content</div>;
}

Example with Stripe

import { useSyncSubscription } from "mentiq-sdk";
import { useStripeSubscription } from "@/hooks/stripe";

function StripeIntegration() {
  const { subscription: stripeSubscription } = useStripeSubscription();

  // Transform Stripe subscription to SubscriptionProperties
  const subscription = stripeSubscription ? {
    status: stripeSubscription.status,
    plan_id: stripeSubscription.items.data[0].price.id,
    plan_name: stripeSubscription.items.data[0].price.nickname,
    mrr: stripeSubscription.items.data[0].price.unit_amount,
    currency: stripeSubscription.currency,
    billing_interval: stripeSubscription.items.data[0].price.recurring.interval,
    current_period_start: new Date(stripeSubscription.current_period_start * 1000).toISOString(),
    current_period_end: new Date(stripeSubscription.current_period_end * 1000).toISOString(),
    cancel_at_period_end: stripeSubscription.cancel_at_period_end,
    provider: "stripe" as const,
    provider_subscription_id: stripeSubscription.id,
    provider_customer_id: stripeSubscription.customer,
  } : null;

  // Sync with Mentiq Analytics
  useSyncSubscription(subscription, { trackChanges: true });

  return <div>Stripe subscription synced</div>;
}

Type Definitions

SubscriptionProperties

interface SubscriptionProperties {
  // Status & Plan
  status: "active" | "trialing" | "past_due" | "canceled" | "paused" | "incomplete" | "incomplete_expired" | "unpaid";
  plan_id?: string;
  plan_name?: string;
  plan_tier?: string;

  // Pricing (in cents)
  mrr?: number; // Monthly Recurring Revenue
  arr?: number; // Annual Recurring Revenue
  ltv?: number; // Lifetime Value
  currency?: string;

  // Billing Cycle
  billing_interval?: "day" | "week" | "month" | "year";
  billing_cycle_anchor?: string; // ISO date
  current_period_start?: string; // ISO date
  current_period_end?: string; // ISO date

  // Trial
  trial_start?: string; // ISO date
  trial_end?: string; // ISO date
  is_trial?: boolean;

  // Payment (PCI-safe)
  payment_method_type?: string;
  payment_method_last4?: string;
  payment_method_brand?: string;

  // Cancellation
  cancel_at_period_end?: boolean;
  canceled_at?: string; // ISO date
  cancellation_reason?: string;

  // Provider
  provider?: "stripe" | "paddle" | "chargebee" | "manual" | string;
  provider_customer_id?: string;
  provider_subscription_id?: string;

  // Metadata
  created_at?: string; // ISO date
  updated_at?: string; // ISO date

  // Custom fields
  [key: string]: string | number | boolean | null | undefined;
}

PaymentEventProperties

interface PaymentEventProperties {
  amount?: number;
  currency?: string;
  payment_status?: "succeeded" | "failed" | "pending" | "refunded";
  failure_reason?: string;
  invoice_id?: string;
  charge_id?: string;
  [key: string]: string | number | boolean | null | undefined;
}

ChurnRiskMetrics

interface ChurnRiskMetrics {
  risk_score: number; // 0-100
  risk_category: "low" | "medium" | "high" | "critical";
  factors: {
    engagement_score?: number;
    days_since_last_active?: number;
    feature_adoption_rate?: number;
    support_tickets?: number;
    negative_feedback_count?: number;
    payment_failures?: number;
  };
  predicted_churn_date?: string; // ISO date
  intervention_recommended?: boolean;
}

Build docs developers (and LLMs) love