Skip to main content

@54vie/analytics - Analytics & Tracking

Tracking and analytics module for 54VIE Super App, supporting event tracking, user identification, A/B testing, and performance monitoring.

Installation

pnpm add @54vie/analytics

Quick Start

import { AnalyticsProvider, useAnalytics } from '@54vie/analytics';

// 1. Wrap app with provider
function App() {
return (
<AnalyticsProvider config={{
appId: '54vie-app',
apiKey: 'your-api-key',
apiEndpoint: 'https://analytics.54vie.vn',
debug: __DEV__,
}}>
<MainApp />
</AnalyticsProvider>
);
}

// 2. Track events
function ProductScreen({ productId }) {
const { track, screen } = useAnalytics();

useEffect(() => {
screen('ProductScreen', { productId });
track('view_product', { product_id: productId });
}, [productId]);
}

Event Tracking

Basic Events

import { useAnalytics } from '@54vie/analytics';

function MyComponent() {
const { track, screen, identify, reset } = useAnalytics();

// Track custom event
track('button_clicked', {
button_name: 'checkout',
screen: 'cart',
});

// Track screen view
screen('HomeScreen', { referrer: 'push_notification' });

// Identify user (after login)
identify('user_123', {
name: 'John Doe',
email: 'john@example.com',
plan: 'premium',
});

// Reset (on logout)
reset();
}

Standard Events

import { Analytics, StandardEvents } from '@54vie/analytics';

// Auth events
Analytics.track(StandardEvents.LOGIN, { method: 'email' });
Analytics.track(StandardEvents.SIGN_UP, { method: 'google' });
Analytics.track(StandardEvents.LOGOUT);

// E-commerce events
Analytics.track(StandardEvents.VIEW_PRODUCT, {
product_id: '123',
product_name: 'iPhone 15',
price: 25000000,
currency: 'VND',
});

Analytics.track(StandardEvents.ADD_TO_CART, {
product_id: '123',
quantity: 1,
});

Analytics.track(StandardEvents.PURCHASE, {
order_id: 'order_456',
total: 25000000,
currency: 'VND',
items: [{ product_id: '123', quantity: 1 }],
});

// Mini-app events
Analytics.track(StandardEvents.MINI_APP_OPEN, {
app_id: 'com.54vie.shopping',
});

Revenue Tracking

import { Analytics } from '@54vie/analytics';

Analytics.trackRevenue({
amount: 500000,
currency: 'VND',
productId: 'premium_monthly',
productName: 'Premium Monthly',
orderId: 'order_789',
});

Timed Events

const { startTimer, endTimer } = useAnalytics();

// Start timer
startTimer('checkout_flow');

// ... user completes checkout ...

// End timer (auto-tracks duration)
endTimer('checkout_flow', {
payment_method: 'card',
success: true,
});
// Tracks: checkout_flow { duration: 45000, payment_method: 'card', success: true }

User Properties

import { useUserProperties } from '@54vie/analytics';

function ProfileScreen() {
const { setProperty, setProperties, increment } = useUserProperties();

// Set single property
setProperty('subscription_tier', 'premium');

// Set multiple properties
setProperties({
city: 'Ho Chi Minh',
age_group: '25-34',
interests: ['tech', 'finance'],
});

// Increment counter
increment('purchase_count');
increment('total_spent', 500000);
}

Session Tracking

import { useSession } from '@54vie/analytics';

function MyComponent() {
const { sessionId, startTime, duration, screenCount } = useSession();

console.log(`Session: ${sessionId}`);
console.log(`Duration: ${duration}ms`);
console.log(`Screens viewed: ${screenCount}`);
}

Performance Tracking

import { usePerformance } from '@54vie/analytics';

function HeavyComponent() {
const { startTrace, logMetric } = usePerformance();

useEffect(() => {
const trace = startTrace('heavy_component_render');

// Add custom attributes
trace.putAttribute('data_size', 'large');

// Add metrics
trace.putMetric('items_count', items.length);

// Stop when done
trace.stop();
}, []);

// Log standalone metric
logMetric('api_response_time', 245, 'ms');
}

Screen Performance

import { useScreenPerformance } from '@54vie/analytics';

function ProductListScreen() {
const { markInteractive, markFullyLoaded } = useScreenPerformance('ProductList');

useEffect(() => {
// Mark when user can interact
markInteractive();
}, []);

useEffect(() => {
if (data && images) {
// Mark when everything is loaded
markFullyLoaded();
}
}, [data, images]);
}

A/B Testing

Setup Experiments

import { registerExperiment } from '@54vie/analytics';

// Register experiment
registerExperiment({
id: 'checkout_flow_v2',
name: 'New Checkout Flow',
variants: [
{ id: 'control', name: 'Original', weight: 50 },
{ id: 'variant_a', name: 'Simplified', weight: 50 },
],
defaultVariant: 'control',
});

Use Experiments

import { useExperiment } from '@54vie/analytics';

function CheckoutScreen() {
const { variant, isLoading, variantConfig } = useExperiment('checkout_flow_v2');

if (isLoading) return <Loading />;

if (variant === 'variant_a') {
return <SimplifiedCheckout />;
}

return <OriginalCheckout />;
}

Feature Flags

import { useFeatureFlag } from '@54vie/analytics';

function NewFeature() {
const isEnabled = useFeatureFlag('new_feature_enabled');

if (!isEnabled) return null;

return <NewFeatureComponent />;
}

Track Conversions

import { useExperimentConversion } from '@54vie/analytics';

function CheckoutSuccess() {
const { trackConversion } = useExperimentConversion('checkout_flow_v2');

useEffect(() => {
trackConversion('purchase_completed', orderTotal);
}, []);
}

Mini-App Attribution

import { useAnalytics } from '@54vie/analytics';

// In mini-app
function ShoppingMiniApp() {
const { setMiniAppContext, trackMiniAppEvent } = useAnalytics();

useEffect(() => {
// Set context for attribution
setMiniAppContext({
appId: 'com.54vie.shopping',
version: '1.2.0',
name: 'Shopping',
});

return () => clearMiniAppContext();
}, []);

// Events automatically include mini-app context
trackMiniAppEvent('product_viewed', { product_id: '123' });
}

Debug Mode

// Enable in development
<AnalyticsProvider config={{
debug: __DEV__,
// Events will be logged to console
}}>

// Manual flush
const { flush } = useAnalytics();
await flush(); // Force send queued events

Configuration

<AnalyticsProvider config={{
// Required
appId: '54vie-app',
apiKey: 'your-api-key',
apiEndpoint: 'https://analytics.54vie.vn',

// Batching
flushInterval: 30000, // Send every 30s
batchSize: 20, // Or when 20 events queued

// Features
trackAppLifecycle: true, // Auto-track app open/close
trackScreenViews: true, // Auto-track screen views
trackDeepLinks: true, // Auto-track deep links
trackCrashes: true, // Auto-track crashes

// Session
sessionTimeout: 30 * 60 * 1000, // 30 minutes

// Privacy
anonymizeIp: true,

// Debug
debug: __DEV__,
}}>

Best Practices

1. Use Standard Events

// Good - Use standard events
track(StandardEvents.PURCHASE, { ... });

// Avoid - Custom names for standard actions
track('user_bought_item', { ... });

2. Include Context

// Good - Include relevant context
track('search', {
query: 'iphone',
results_count: 25,
filters: { category: 'phones', price_max: 30000000 },
});

// Avoid - Missing context
track('search', { query: 'iphone' });

3. Track User Journey

// Track funnel
track('checkout_started');
track('shipping_selected');
track('payment_entered');
track('order_placed');