@rivtor/viral
v1.1.0
Published
Product-Led Growth Viral Loops with referral tracking and fraud detection
Maintainers
Readme
@rivtor/viral
Production-ready product-led growth viral loops with referral tracking and fraud detection
Features
- Referral Code Generator: Collision detection for unique, memorable codes
- Attribution Tracking: Track referrals across multiple touchpoints
- Fraud Detection: Rate limits, device fingerprinting, and pattern analysis
- Reward Distribution: Credits, discounts, trials, and feature unlocks
- Analytics Dashboard: Conversion rates, top referrers, and performance metrics
- React Widgets: Pre-built referral widgets and share buttons
Installation
npm install @rivtor/viral
# or
yarn add @rivtor/viral
# or
pnpm add @rivtor/viralQuick Start
1. Generate Referral Code
import { generateReferralCode } from '@rivtor/viral/server';
const code = await generateReferralCode('user-123', {
type: 'credits',
value: 100,
expiresIn: 30 * 24 * 60 * 60 // 30 days
});
console.log(code);
// Returns: 'GETRIVTORXYZ' or similar2. Track Referral Click
import { trackReferral } from '@rivtor/viral/server';
const referral = await trackReferral('GETRIVTORXYZ', 'user-456', {
ipAddress: '192.168.1.1',
userAgent: 'Mozilla/5.0...',
deviceId: 'device-123',
referrer: 'https://twitter.com'
});
console.log(referral);
// {
// id: 'referral-123',
// code: 'GETRIVTORXYZ',
// referrerId: 'user-123',
// refereeId: 'user-456',
// status: 'pending',
// fraudScore: 0
// }3. Convert Referral
import { convertReferral } from '@rivtor/viral/server';
const converted = await convertReferral('user-456', 'signup', {
plan: 'pro',
value: 29
});
console.log(converted);
// {
// success: true,
// referralId: 'referral-123',
// referrerReward: { type: 'credits', value: 100 },
// refereeReward: { type: 'discount', value: 10 }
// }4. Display Referral Widget
'use client';
import { RivtorReferralWidget } from '@rivtor/viral/react';
export default function ReferralPage() {
return (
<RivtorReferralWidget
userId="user-123"
showStats
variant="detailed"
onShare={(platform) => console.log(`Shared on ${platform}`)}
/>
);
}5. Share Buttons
'use client';
import { RivtorShareButtons } from '@rivtor/viral/react';
export default function ShareSection() {
return (
<RivtorShareButtons
referralCode="GETRIVTORXYZ"
title="Join me on Rivtor!"
message="I've been using Rivtor and love it. Sign up with my code for 10% off!"
variant="horizontal"
platforms={['twitter', 'facebook', 'linkedin', 'email', 'copy']}
/>
);
}API Reference
Server Functions
import {
generateReferralCode,
trackReferral,
convertReferral,
getReferralStats,
validateReferralCode
} from '@rivtor/viral/server';
// Generate referral code
await generateReferralCode(
userId: string,
options?: {
type?: 'credits' | 'discount' | 'trial' | 'feature';
value?: number;
expiresIn?: number;
maxUses?: number;
customCode?: string;
}
): Promise<string>; // Returns referral code
// Track referral click
await trackReferral(
code: string,
refereeId: string,
context: {
ipAddress?: string;
userAgent?: string;
deviceId?: string;
referrer?: string;
}
): Promise<Referral>;
// Convert referral (when user completes action)
await convertReferral(
refereeId: string,
action: 'signup' | 'purchase' | 'subscription',
metadata?: Record<string, unknown>
): Promise<ConversionResult>;
// Get referral stats
await getReferralStats(userId: string): Promise<{
totalReferrals: number;
successfulConversions: number;
pendingConversions: number;
totalRewards: number;
conversionRate: number;
}>;
// Validate referral code
await validateReferralCode(code: string): Promise<{
valid: boolean;
code?: string;
reward?: Reward;
reason?: string;
}>;Reward Management
import {
createReward,
distributeReward,
getUserRewards,
applyReward
} from '@rivtor/viral/server';
// Create reward
await createReward({
name: 'Signup Bonus',
type: 'credits',
value: 100,
expiresIn: 30 * 24 * 60 * 60
});
// Distribute reward to user
await distributeReward('user-123', {
rewardId: 'reward-123',
referralId: 'referral-456',
reason: 'referral_conversion'
});
// Get user rewards
await getUserRewards('user-123', {
status: 'available',
type: 'credits'
});
// Apply reward
await applyReward('reward-123', {
userId: 'user-123',
orderId: 'order-456'
});Fraud Detection
import {
checkFraud,
flagSuspiciousActivity,
getFraudScore
} from '@rivtor/viral/server';
// Check for fraud
await checkFraud(referralId: string): Promise<{
isFraudulent: boolean;
fraudScore: number;
reasons: string[];
}>;
// Flag suspicious activity
await flagSuspiciousActivity({
referralId: 'referral-123',
reason: 'multiple_same_device',
severity: 'high'
});
// Get fraud score
await getFraudScore(userId: string): Promise<{
score: number;
riskLevel: 'low' | 'medium' | 'high';
factors: {
sameDeviceReferrals: number;
sameIpReferrals: number;
timeBetweenReferrals: number;
conversionRate: number;
};
}>;Analytics
import {
getReferralAnalytics,
getTopReferrers,
getConversionMetrics
} from '@rivtor/viral/server';
// Get referral analytics
await getReferralAnalytics({
startDate: new Date('2024-01-01'),
endDate: new Date('2024-01-31'),
groupBy: 'day'
});
// Get top referrers
await getTopReferrers({
limit: 10,
sortBy: 'conversions' | 'revenue'
});
// Get conversion metrics
await getConversionMetrics({
funnel: ['click', 'signup', 'purchase'],
cohort: 'january_2024'
});React Components
RivtorReferralWidget
<RivtorReferralWidget
userId="user-123"
variant="compact" // | 'detailed' | 'minimal'
showStats={true}
showShareButtons={true}
showLeaderboard={false}
onShare={(platform) => console.log(`Shared on ${platform}`)}
onCopy={() => console.log('Code copied')}
theme="light" // | 'dark' | 'custom'
customTheme={{
primaryColor: '#3b82f6',
borderRadius: '8px'
}}
/>RivtorShareButtons
<RivtorShareButtons
referralCode="GETRIVTORXYZ"
title="Join me on Rivtor!"
message="I've been using Rivtor and love it. Sign up with my code for 10% off!"
variant="horizontal" // | 'vertical'
platforms={[
'twitter',
'facebook',
'linkedin',
'email',
'whatsapp',
'copy'
]}
size="medium" // | 'small' | 'large'
onShare={(platform) => console.log(`Shared on ${platform}`)}
/>RivtorLeaderboard
<RivtorLeaderboard
period="month" // | 'week' | 'all-time'
limit={10}
showRank={true}
showStats={true}
currentUserOnly={false}
onUserClick={(userId) => console.log(`View ${userId}`)}
/>Database Schema
-- Referral codes
CREATE TABLE referral_codes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code TEXT UNIQUE NOT NULL,
user_id UUID NOT NULL,
reward_type TEXT NOT NULL,
reward_value NUMERIC NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
max_uses INTEGER,
total_uses INTEGER DEFAULT 0,
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
metadata JSONB
);
-- Referrals
CREATE TABLE referrals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referral_code_id UUID NOT NULL REFERENCES referral_codes(id),
referrer_id UUID NOT NULL,
referee_id UUID NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
converted_at TIMESTAMPTZ,
reward_applied BOOLEAN DEFAULT FALSE,
fraud_score NUMERIC DEFAULT 0,
fraud_reasons TEXT[],
ip_address TEXT,
user_agent TEXT,
device_id TEXT,
referrer TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Rewards
CREATE TABLE rewards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL,
referral_id UUID REFERENCES referrals(id),
type TEXT NOT NULL,
value NUMERIC NOT NULL,
status TEXT NOT NULL DEFAULT 'available',
expires_at TIMESTAMPTZ,
applied_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indexes for efficient queries
CREATE INDEX idx_referral_codes_user ON referral_codes(user_id);
CREATE INDEX idx_referral_codes_code ON referral_codes(code);
CREATE INDEX idx_referrals_referrer ON referrals(referrer_id);
CREATE INDEX idx_referrals_referee ON referrals(referee_id);
CREATE INDEX idx_referrals_status ON referrals(status);
CREATE INDEX idx_rewards_user ON rewards(user_id);
CREATE INDEX idx_rewards_status ON rewards(status);Configuration
import { configureViral } from '@rivtor/viral/server';
configureViral({
// Referral code settings
codes: {
length: 12,
prefix: 'GET',
charset: 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789', // No ambiguous characters
maxUses: 100,
expiresIn: 30 * 24 * 60 * 60 // 30 days
},
// Reward settings
rewards: {
referrer: {
type: 'credits',
value: 100
},
referee: {
type: 'discount',
value: 10
},
expiresIn: 90 * 24 * 60 * 60 // 90 days
},
// Fraud detection
fraud: {
enabled: true,
maxSameDeviceReferrals: 3,
maxSameIpReferrals: 5,
minTimeBetweenReferrals: 60 * 60, // 1 hour
maxConversionRate: 0.5,
flagThreshold: 0.7
},
// Attribution window
attribution: {
windowDays: 30,
touchpoints: ['first', 'last'],
trackMultipleConversions: false
}
});Reward Types
| Type | Description | Example | |------|-------------|---------| | credits | Account credits | $100 in credits | | discount | Percentage discount | 10% off next purchase | | trial | Free trial extension | 30 days free | | feature | Feature unlock | Unlock premium feature | | cash | Cash payout | $50 cash reward |
Fraud Detection Factors
The fraud detection system considers:
- Same Device: Multiple referrals from same device
- Same IP: Multiple referrals from same IP address
- Timing Pattern: Unusual timing between referrals
- Conversion Rate: Abnormally high or low conversion rates
- User Behavior: Suspicious user activity patterns
Best Practices
- Set Reasonable Limits: Limit max uses per referral code
- Monitor Fraud: Regularly review fraud detection logs
- A/B Test Rewards: Test different reward types and values
- Clear Communication: Clearly explain reward terms to users
- Track Attribution: Use multiple touchpoint attribution for accuracy
License
MIT
Made with ❤️ by Rivtor
