UNPKG

shipdeck

Version:

Ship MVPs in 48 hours. Fix bugs in 30 seconds. The command deck for developers who ship.

1,152 lines (1,025 loc) 37.1 kB
/** * Growth Hacker Agent - Rapid User Acquisition & Viral Growth Strategies * * Specializes in finding and exploiting growth opportunities through * marketing, product features, and analytics to drive viral user acquisition. * * @author Shipdeck Ultimate Framework * @version 1.0.0 */ const { BaseAgent } = require('./base-agent'); /** * Growth Hacker Agent for viral user acquisition and retention strategies */ class GrowthHackerAgent extends BaseAgent { constructor(options = {}) { super({ name: 'GrowthHackerAgent', description: 'Specialized agent for rapid user acquisition, viral growth loops, and conversion optimization', version: '1.0.0', ...options }); // Growth strategy templates this.growthTemplates = { viral: ['referral', 'social-sharing', 'invite-friends', 'network-effects'], acquisition: ['waitlist', 'landing-pages', 'content-marketing', 'partnerships'], retention: ['onboarding', 'gamification', 'notifications', 'engagement-loops'], conversion: ['a-b-testing', 'funnel-optimization', 'social-proof', 'scarcity'] }; // Analytics tracking events this.growthEvents = [ 'user_signup', 'referral_sent', 'referral_converted', 'social_share', 'invite_sent', 'feature_adoption', 'subscription_upgrade', 'churn_risk' ]; } /** * Get agent capabilities * @returns {Array<string>} Array of capability strings */ getCapabilities() { return [ 'viral-loops', 'user-acquisition', 'retention', 'a-b-testing', 'analytics' ]; } /** * Get system prompt for growth hacking tasks * @returns {string} System prompt */ getSystemPrompt() { return `You are a Growth Hacker Agent specialized in rapid user acquisition and viral growth strategies. Your expertise includes: - Viral loop mechanisms and referral systems - User acquisition funnels and conversion optimization - A/B testing frameworks and growth analytics - Retention strategies and engagement loops - Social proof and scarcity tactics - Onboarding flows that convert and retain users You generate production-ready React/Next.js code with: - Complete error handling and loading states - Analytics tracking integration - Mobile-responsive designs - Accessibility compliance - Performance optimization - TypeScript support when requested Focus on measurable growth metrics and data-driven optimization.`; } /** * Execute growth hacking task * @param {Object} task - Task configuration * @param {Object} context - Execution context * @returns {Promise<Object>} Execution result */ async execute(task, context = {}) { this.validateTask(task); const prompt = this.createPrompt(task, context); const response = await this.sendMessage(prompt, { temperature: 0.7, maxTokens: 4096 }); if (!response.success) { throw new Error(`Growth hacker execution failed: ${response.error}`); } return this.parseResponse(response.content); } /** * Create viral referral system * @param {Object} config - Referral system configuration * @returns {Promise<Object>} Generated referral system code */ async createReferralSystem(config = {}) { const task = { type: 'viral-loops', description: 'Create a comprehensive viral referral system', requirements: [ 'Referral code generation and tracking', 'Reward system for referrers and referees', 'Social sharing integration', 'Analytics tracking for referral metrics', 'Email notifications for successful referrals', 'Dashboard for tracking referral performance' ], input: { rewards: config.rewards || { referrer: '10% credit', referee: '20% discount' }, channels: config.channels || ['email', 'social', 'link'], analytics: config.analytics || true, notifications: config.notifications || true } }; return await this.execute(task); } /** * Build user acquisition funnel * @param {Object} config - Funnel configuration * @returns {Promise<Object>} Generated acquisition funnel */ async buildAcquisitionFunnel(config = {}) { const task = { type: 'user-acquisition', description: 'Build complete user acquisition funnel with landing pages and conversion optimization', requirements: [ 'High-converting landing pages', 'Lead capture forms with validation', 'Email sequence automation', 'A/B testing framework for optimization', 'Analytics and conversion tracking', 'Social proof and testimonials integration' ], input: { pages: config.pages || ['landing', 'signup', 'onboarding'], abTests: config.abTests || ['headline', 'cta', 'form-fields'], socialProof: config.socialProof || true, emailSequence: config.emailSequence || true } }; return await this.execute(task); } /** * Create retention and engagement system * @param {Object} config - Retention system configuration * @returns {Promise<Object>} Generated retention system */ async createRetentionSystem(config = {}) { const task = { type: 'retention', description: 'Create user retention and engagement system with gamification', requirements: [ 'User onboarding flow with progress tracking', 'Gamification elements (points, badges, levels)', 'Push notification system for re-engagement', 'Email drip campaigns for inactive users', 'In-app messaging and tooltips', 'Churn prediction and intervention' ], input: { onboarding: config.onboarding || { steps: 5, progress: true }, gamification: config.gamification || { points: true, badges: true, leaderboard: false }, notifications: config.notifications || ['push', 'email', 'in-app'], churnPrevention: config.churnPrevention || true } }; return await this.execute(task); } /** * Setup A/B testing framework * @param {Object} config - A/B testing configuration * @returns {Promise<Object>} Generated A/B testing system */ async setupABTesting(config = {}) { const task = { type: 'a-b-testing', description: 'Setup comprehensive A/B testing framework for growth experiments', requirements: [ 'Feature flag system for experiment control', 'User segmentation and targeting', 'Statistical significance testing', 'Real-time results dashboard', 'Experiment management interface', 'Integration with analytics platforms' ], input: { experiments: config.experiments || ['landing-page', 'pricing', 'onboarding'], segmentation: config.segmentation || ['new-users', 'returning-users', 'geographic'], analytics: config.analytics || ['conversion', 'retention', 'revenue'], dashboard: config.dashboard || true } }; return await this.execute(task); } /** * Build growth analytics dashboard * @param {Object} config - Analytics dashboard configuration * @returns {Promise<Object>} Generated analytics dashboard */ async buildGrowthAnalytics(config = {}) { const task = { type: 'analytics', description: 'Build comprehensive growth analytics dashboard with key metrics', requirements: [ 'Key growth metrics visualization (CAC, LTV, Churn)', 'Funnel analysis and conversion tracking', 'Cohort analysis for retention insights', 'Real-time user activity monitoring', 'Custom event tracking system', 'Automated reporting and alerts' ], input: { metrics: config.metrics || ['cac', 'ltv', 'churn', 'mrr', 'viral-coefficient'], visualizations: config.visualizations || ['charts', 'funnels', 'cohorts', 'heatmaps'], realtime: config.realtime || true, alerts: config.alerts || ['goal-reached', 'anomaly-detected', 'experiment-complete'] } }; return await this.execute(task); } /** * Generate growth strategy templates * @param {string} strategy - Strategy type (viral, acquisition, retention, conversion) * @returns {Object} Strategy template configuration */ getGrowthTemplate(strategy) { const templates = { viral: { name: 'Viral Growth Loop', components: ['referral-system', 'social-sharing', 'invite-mechanism'], metrics: ['viral-coefficient', 'referral-rate', 'sharing-rate'], tactics: [ 'Double-sided incentives (referrer + referee rewards)', 'Social proof in sharing messages', 'Gamified invitation process', 'Network effect amplification' ] }, acquisition: { name: 'User Acquisition Funnel', components: ['landing-pages', 'lead-magnets', 'conversion-forms'], metrics: ['conversion-rate', 'cac', 'traffic-sources'], tactics: [ 'High-value lead magnets', 'Social proof and testimonials', 'Scarcity and urgency tactics', 'Multi-step micro-conversions' ] }, retention: { name: 'User Retention System', components: ['onboarding', 'engagement-loops', 'notification-system'], metrics: ['retention-rate', 'dau-mau-ratio', 'feature-adoption'], tactics: [ 'Progressive onboarding with quick wins', 'Habit-forming engagement loops', 'Personalized re-engagement campaigns', 'Churn prediction and intervention' ] }, conversion: { name: 'Conversion Optimization', components: ['a-b-tests', 'funnel-analysis', 'user-feedback'], metrics: ['conversion-rate', 'ltv', 'mrr-growth'], tactics: [ 'Continuous A/B testing program', 'Friction analysis and removal', 'Social proof at conversion points', 'Value proposition optimization' ] } }; return templates[strategy] || null; } /** * Create viral loop implementation * @param {Object} config - Viral loop configuration * @returns {string} React component code for viral loop */ generateViralLoopCode(config = {}) { const { rewardType = 'credit', socialChannels = ['twitter', 'facebook', 'linkedin'] } = config; return `import React, { useState, useEffect } from 'react'; import { useUser } from '@/hooks/useUser'; import { trackEvent } from '@/lib/analytics'; /** * Viral Referral System Component * Implements double-sided incentive referral system with social sharing */ export default function ViralReferralSystem() { const { user } = useUser(); const [referralCode, setReferralCode] = useState(''); const [referralStats, setReferralStats] = useState({ invitesSent: 0, conversions: 0, totalRewards: 0 }); const [shareUrl, setShareUrl] = useState(''); useEffect(() => { // Generate unique referral code const generateReferralCode = () => { return user?.id ? \`\${user.username || 'user'}\${Date.now().toString(36)}\` : ''; }; if (user) { const code = generateReferralCode(); setReferralCode(code); setShareUrl(\`\${window.location.origin}?ref=\${code}\`); // Track viral loop view trackEvent('viral_loop_viewed', { userId: user.id }); } }, [user]); const handleSocialShare = async (platform) => { const shareMessage = \`🚀 Join me on this amazing platform! Use my link to get ${config.refereeReward || '20% off'}: \${shareUrl}\`; const shareUrls = { twitter: \`https://twitter.com/intent/tweet?text=\${encodeURIComponent(shareMessage)}\`, facebook: \`https://www.facebook.com/sharer/sharer.php?u=\${encodeURIComponent(shareUrl)}\`, linkedin: \`https://www.linkedin.com/sharing/share-offsite/?url=\${encodeURIComponent(shareUrl)}\` }; // Track social share trackEvent('referral_shared', { userId: user.id, platform, referralCode, shareUrl }); // Open share window window.open(shareUrls[platform], '_blank', 'width=600,height=400'); }; const copyReferralLink = async () => { try { await navigator.clipboard.writeText(shareUrl); trackEvent('referral_link_copied', { userId: user.id, referralCode }); // Show success toast } catch (err) { console.error('Failed to copy:', err); } }; const sendEmailInvite = async (email) => { try { const response = await fetch('/api/referrals/invite', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ referrerCode: referralCode, email, message: \`I'd love for you to try this platform! Use my referral link: \${shareUrl}\` }) }); if (response.ok) { trackEvent('email_invite_sent', { userId: user.id, referralCode, email }); // Show success message } } catch (error) { console.error('Email invite failed:', error); } }; return ( <div className="max-w-2xl mx-auto p-6 bg-white rounded-lg shadow-lg"> <div className="text-center mb-8"> <h2 className="text-3xl font-bold text-gray-900 mb-2"> Earn ${config.referrerReward || '10% credit'} for Every Friend! </h2> <p className="text-gray-600"> Share your unique referral link and both you and your friends get rewards </p> </div> {/* Referral Stats */} <div className="grid grid-cols-3 gap-4 mb-8"> <div className="text-center p-4 bg-blue-50 rounded-lg"> <div className="text-2xl font-bold text-blue-600">{referralStats.invitesSent}</div> <div className="text-sm text-gray-600">Invites Sent</div> </div> <div className="text-center p-4 bg-green-50 rounded-lg"> <div className="text-2xl font-bold text-green-600">{referralStats.conversions}</div> <div className="text-sm text-gray-600">Friends Joined</div> </div> <div className="text-center p-4 bg-purple-50 rounded-lg"> <div className="text-2xl font-bold text-purple-600">\${referralStats.totalRewards}</div> <div className="text-sm text-gray-600">Total Earned</div> </div> </div> {/* Referral Link */} <div className="mb-6"> <label className="block text-sm font-medium text-gray-700 mb-2"> Your Referral Link </label> <div className="flex"> <input type="text" value={shareUrl} readOnly className="flex-1 px-3 py-2 border border-gray-300 rounded-l-md bg-gray-50" /> <button onClick={copyReferralLink} className="px-4 py-2 bg-blue-600 text-white rounded-r-md hover:bg-blue-700 transition-colors" > Copy </button> </div> </div> {/* Social Sharing */} <div className="mb-6"> <h3 className="text-lg font-medium text-gray-900 mb-3">Share on Social Media</h3> <div className="flex gap-3"> {socialChannels.map(platform => ( <button key={platform} onClick={() => handleSocialShare(platform)} className={\`px-4 py-2 rounded-md text-white transition-colors \${ platform === 'twitter' ? 'bg-blue-400 hover:bg-blue-500' : platform === 'facebook' ? 'bg-blue-600 hover:bg-blue-700' : 'bg-blue-800 hover:bg-blue-900' }\`} > Share on {platform.charAt(0).toUpperCase() + platform.slice(1)} </button> ))} </div> </div> {/* Email Invite */} <div className="border-t pt-6"> <h3 className="text-lg font-medium text-gray-900 mb-3">Invite by Email</h3> <EmailInviteForm onSend={sendEmailInvite} /> </div> {/* How It Works */} <div className="mt-8 p-4 bg-gray-50 rounded-lg"> <h4 className="font-medium text-gray-900 mb-2">How It Works:</h4> <ul className="text-sm text-gray-600 space-y-1"> <li>1. Share your referral link with friends</li> <li>2. They sign up using your link and get ${config.refereeReward || '20% off'}</li> <li>3. You earn ${config.referrerReward || '10% credit'} for each successful referral</li> <li>4. There's no limit to how much you can earn!</li> </ul> </div> </div> ); } /** * Email Invite Form Component */ function EmailInviteForm({ onSend }) { const [email, setEmail] = useState(''); const [isLoading, setIsLoading] = useState(false); const handleSubmit = async (e) => { e.preventDefault(); if (!email) return; setIsLoading(true); await onSend(email); setEmail(''); setIsLoading(false); }; return ( <form onSubmit={handleSubmit} className="flex gap-2"> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="friend@example.com" className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" required /> <button type="submit" disabled={isLoading} className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 disabled:opacity-50 transition-colors" > {isLoading ? 'Sending...' : 'Send Invite'} </button> </form> ); }`; } /** * Generate A/B testing framework code * @param {Object} config - A/B test configuration * @returns {string} A/B testing hook and component code */ generateABTestingCode(config = {}) { return `import React, { useState, useEffect, createContext, useContext } from 'react'; import { trackEvent } from '@/lib/analytics'; /** * A/B Testing Context and Provider * Manages experiment variants and user assignments */ const ABTestContext = createContext(); export function ABTestProvider({ children }) { const [experiments, setExperiments] = useState({}); const [userId, setUserId] = useState(null); useEffect(() => { // Initialize user ID and load experiments const initializeABTests = async () => { const user = await getCurrentUser(); setUserId(user?.id); // Load active experiments const activeExperiments = await fetchActiveExperiments(); const userExperiments = {}; for (const experiment of activeExperiments) { const variant = await assignUserToVariant(user?.id, experiment); userExperiments[experiment.name] = variant; // Track experiment assignment trackEvent('experiment_assigned', { userId: user?.id, experimentName: experiment.name, variant: variant.name, timestamp: new Date().toISOString() }); } setExperiments(userExperiments); }; initializeABTests(); }, []); const getVariant = (experimentName, defaultVariant = 'control') => { return experiments[experimentName]?.name || defaultVariant; }; const trackConversion = (experimentName, goalName, value = 1) => { const variant = experiments[experimentName]; if (variant) { trackEvent('experiment_conversion', { userId, experimentName, variant: variant.name, goalName, value, timestamp: new Date().toISOString() }); } }; return ( <ABTestContext.Provider value={{ experiments, getVariant, trackConversion }}> {children} </ABTestContext.Provider> ); } /** * Hook for using A/B tests in components * @param {string} experimentName - Name of the experiment * @param {string} defaultVariant - Default variant if experiment not found * @returns {Object} Experiment utilities */ export function useABTest(experimentName, defaultVariant = 'control') { const context = useContext(ABTestContext); if (!context) { throw new Error('useABTest must be used within ABTestProvider'); } const { getVariant, trackConversion } = context; const variant = getVariant(experimentName, defaultVariant); return { variant, isVariant: (variantName) => variant === variantName, trackConversion: (goalName, value) => trackConversion(experimentName, goalName, value) }; } /** * A/B Test Component for declarative testing */ export function ABTest({ name, variants, defaultVariant = 'control', children }) { const { variant } = useABTest(name, defaultVariant); const renderVariant = variants[variant] || variants[defaultVariant]; return renderVariant ? renderVariant() : children; } /** * Utility functions for A/B testing */ async function getCurrentUser() { try { const response = await fetch('/api/user/me'); return response.ok ? await response.json() : null; } catch (error) { console.error('Failed to get current user:', error); return null; } } async function fetchActiveExperiments() { try { const response = await fetch('/api/experiments/active'); return response.ok ? await response.json() : []; } catch (error) { console.error('Failed to fetch experiments:', error); return []; } } async function assignUserToVariant(userId, experiment) { try { const response = await fetch('/api/experiments/assign', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId, experimentName: experiment.name }) }); if (response.ok) { return await response.json(); } // Fallback to client-side assignment return clientSideAssignment(userId, experiment); } catch (error) { console.error('Failed to assign variant:', error); return clientSideAssignment(userId, experiment); } } function clientSideAssignment(userId, experiment) { // Deterministic assignment based on user ID and experiment name const hash = simpleHash(\`\${userId}-\${experiment.name}\`); const bucketSize = 1 / experiment.variants.length; const bucket = (hash % 1000) / 1000; for (let i = 0; i < experiment.variants.length; i++) { if (bucket < bucketSize * (i + 1)) { return experiment.variants[i]; } } return experiment.variants[0]; // Fallback } function simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash); } // Example usage components export function ExampleLandingPageTest() { const { variant, trackConversion } = useABTest('landing-page-headline'); const handleSignup = () => { trackConversion('signup', 1); // Handle actual signup logic }; return ( <div className="text-center py-16"> {variant === 'control' && ( <h1 className="text-4xl font-bold mb-4"> Welcome to Our Amazing Product </h1> )} {variant === 'benefits' && ( <h1 className="text-4xl font-bold mb-4"> Save 50% Time with Our Solution </h1> )} {variant === 'social-proof' && ( <h1 className="text-4xl font-bold mb-4"> Join 10,000+ Happy Customers </h1> )} <button onClick={handleSignup} className="px-8 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors" > Get Started Free </button> </div> ); } export function ExamplePricingTest() { return ( <ABTest name="pricing-display" variants={{ control: () => <StandardPricing />, discount: () => <DiscountPricing />, social: () => <SocialProofPricing /> }} /> ); }`; } /** * Create growth analytics dashboard code * @param {Object} config - Analytics configuration * @returns {string} Analytics dashboard component code */ generateGrowthAnalyticsCode(config = {}) { return `import React, { useState, useEffect } from 'react'; import { trackEvent } from '@/lib/analytics'; /** * Growth Analytics Dashboard * Displays key growth metrics, funnels, and cohort analysis */ export default function GrowthAnalyticsDashboard() { const [metrics, setMetrics] = useState({ cac: 0, ltv: 0, churnRate: 0, mrr: 0, viralCoefficient: 0, conversionRate: 0 }); const [funnelData, setFunnelData] = useState([]); const [cohortData, setCohortData] = useState([]); const [realTimeUsers, setRealTimeUsers] = useState(0); const [isLoading, setIsLoading] = useState(true); useEffect(() => { loadGrowthMetrics(); const interval = setInterval(loadRealTimeData, 30000); // Update every 30 seconds return () => clearInterval(interval); }, []); const loadGrowthMetrics = async () => { try { setIsLoading(true); const [metricsRes, funnelRes, cohortRes] = await Promise.all([ fetch('/api/analytics/growth-metrics'), fetch('/api/analytics/funnel'), fetch('/api/analytics/cohort') ]); if (metricsRes.ok) { const data = await metricsRes.json(); setMetrics(data); } if (funnelRes.ok) { const data = await funnelRes.json(); setFunnelData(data); } if (cohortRes.ok) { const data = await cohortRes.json(); setCohortData(data); } trackEvent('growth_dashboard_loaded', { timestamp: new Date().toISOString() }); } catch (error) { console.error('Failed to load growth metrics:', error); } finally { setIsLoading(false); } }; const loadRealTimeData = async () => { try { const response = await fetch('/api/analytics/realtime'); if (response.ok) { const data = await response.json(); setRealTimeUsers(data.activeUsers); } } catch (error) { console.error('Failed to load real-time data:', error); } }; if (isLoading) { return <AnalyticsSkeleton />; } return ( <div className="p-6 space-y-6"> <div className="flex justify-between items-center"> <h1 className="text-3xl font-bold text-gray-900">Growth Analytics</h1> <div className="flex items-center space-x-2"> <div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div> <span className="text-sm text-gray-600">{realTimeUsers} users online</span> </div> </div> {/* Key Metrics Grid */} <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <MetricCard title="Customer Acquisition Cost" value={\`$\${metrics.cac.toFixed(2)}\`} change={metrics.cacChange} trend={metrics.cacTrend} /> <MetricCard title="Lifetime Value" value={\`$\${metrics.ltv.toFixed(2)}\`} change={metrics.ltvChange} trend={metrics.ltvTrend} /> <MetricCard title="Churn Rate" value={\`\${(metrics.churnRate * 100).toFixed(1)}%\`} change={metrics.churnChange} trend={metrics.churnTrend} inverse={true} /> <MetricCard title="Monthly Recurring Revenue" value={\`$\${(metrics.mrr / 1000).toFixed(1)}k\`} change={metrics.mrrChange} trend={metrics.mrrTrend} /> <MetricCard title="Viral Coefficient" value={metrics.viralCoefficient.toFixed(2)} change={metrics.viralChange} trend={metrics.viralTrend} /> <MetricCard title="Conversion Rate" value={\`\${(metrics.conversionRate * 100).toFixed(1)}%\`} change={metrics.conversionChange} trend={metrics.conversionTrend} /> </div> {/* Funnel Analysis */} <div className="bg-white rounded-lg shadow p-6"> <h2 className="text-xl font-bold text-gray-900 mb-4">Conversion Funnel</h2> <ConversionFunnel data={funnelData} /> </div> {/* Cohort Analysis */} <div className="bg-white rounded-lg shadow p-6"> <h2 className="text-xl font-bold text-gray-900 mb-4">Cohort Analysis</h2> <CohortTable data={cohortData} /> </div> {/* Real-time Activity */} <div className="bg-white rounded-lg shadow p-6"> <h2 className="text-xl font-bold text-gray-900 mb-4">Real-time Activity</h2> <RealTimeActivity /> </div> </div> ); } /** * Metric Card Component */ function MetricCard({ title, value, change, trend, inverse = false }) { const isPositive = inverse ? change < 0 : change > 0; const changeColor = isPositive ? 'text-green-600' : 'text-red-600'; const changeIcon = isPositive ? '↗' : '↘'; return ( <div className="bg-white rounded-lg shadow p-6"> <div className="flex items-center justify-between"> <div> <p className="text-sm font-medium text-gray-600">{title}</p> <p className="text-2xl font-bold text-gray-900">{value}</p> </div> <div className="flex items-center space-x-1"> <span className={\`text-sm font-medium \${changeColor}\`}> {changeIcon} {Math.abs(change).toFixed(1)}% </span> </div> </div> <div className="mt-4 h-2 bg-gray-200 rounded"> <div className={\`h-2 rounded \${isPositive ? 'bg-green-400' : 'bg-red-400'}\`} style={{ width: \`\${Math.min(Math.abs(change), 100)}%\` }} ></div> </div> </div> ); } /** * Conversion Funnel Component */ function ConversionFunnel({ data }) { if (!data || data.length === 0) { return <div className="text-gray-500 text-center py-8">No funnel data available</div>; } const maxUsers = data[0]?.users || 1; return ( <div className="space-y-4"> {data.map((step, index) => { const percentage = (step.users / maxUsers) * 100; const conversionRate = index > 0 ? ((step.users / data[index - 1].users) * 100) : 100; return ( <div key={step.name} className="flex items-center space-x-4"> <div className="w-32 text-sm font-medium text-gray-700">{step.name}</div> <div className="flex-1"> <div className="flex items-center justify-between mb-1"> <span className="text-sm text-gray-600">{step.users.toLocaleString()} users</span> <span className="text-sm text-gray-600">{conversionRate.toFixed(1)}% conversion</span> </div> <div className="w-full bg-gray-200 rounded-full h-2"> <div className="bg-blue-600 h-2 rounded-full transition-all duration-300" style={{ width: \`\${percentage}%\` }} ></div> </div> </div> </div> ); })} </div> ); } /** * Cohort Analysis Table */ function CohortTable({ data }) { if (!data || data.length === 0) { return <div className="text-gray-500 text-center py-8">No cohort data available</div>; } const weeks = Array.from({ length: 12 }, (_, i) => \`Week \${i + 1}\`); return ( <div className="overflow-x-auto"> <table className="min-w-full divide-y divide-gray-200"> <thead className="bg-gray-50"> <tr> <th className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Cohort </th> <th className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> Users </th> {weeks.map(week => ( <th key={week} className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> {week} </th> ))} </tr> </thead> <tbody className="bg-white divide-y divide-gray-200"> {data.map((cohort, index) => ( <tr key={index}> <td className="px-3 py-2 whitespace-nowrap text-sm font-medium text-gray-900"> {cohort.period} </td> <td className="px-3 py-2 whitespace-nowrap text-sm text-gray-500"> {cohort.users.toLocaleString()} </td> {cohort.retention.map((rate, weekIndex) => ( <td key={weekIndex} className="px-3 py-2 whitespace-nowrap text-sm text-gray-900"> <div className={\`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium \${ rate > 0.5 ? 'bg-green-100 text-green-800' : rate > 0.2 ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800' }\`} > {(rate * 100).toFixed(0)}% </div> </td> ))} </tr> ))} </tbody> </table> </div> ); } /** * Real-time Activity Component */ function RealTimeActivity() { const [activities, setActivities] = useState([]); useEffect(() => { const loadActivities = async () => { try { const response = await fetch('/api/analytics/activity'); if (response.ok) { const data = await response.json(); setActivities(data); } } catch (error) { console.error('Failed to load activities:', error); } }; loadActivities(); const interval = setInterval(loadActivities, 5000); // Update every 5 seconds return () => clearInterval(interval); }, []); return ( <div className="space-y-3"> {activities.map((activity, index) => ( <div key={index} className="flex items-center space-x-3 p-3 bg-gray-50 rounded-lg"> <div className="flex-shrink-0"> <div className={\`w-2 h-2 rounded-full \${ activity.type === 'signup' ? 'bg-green-400' : activity.type === 'referral' ? 'bg-blue-400' : activity.type === 'purchase' ? 'bg-purple-400' : 'bg-gray-400' }\`}></div> </div> <div className="flex-1 min-w-0"> <p className="text-sm text-gray-900">{activity.description}</p> <p className="text-xs text-gray-500">{activity.timestamp}</p> </div> </div> ))} </div> ); } /** * Loading Skeleton Component */ function AnalyticsSkeleton() { return ( <div className="p-6 space-y-6"> <div className="h-8 bg-gray-200 rounded w-1/3 animate-pulse"></div> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {Array.from({ length: 6 }).map((_, i) => ( <div key={i} className="bg-white rounded-lg shadow p-6"> <div className="h-4 bg-gray-200 rounded w-1/2 mb-2 animate-pulse"></div> <div className="h-8 bg-gray-200 rounded w-1/3 animate-pulse"></div> </div> ))} </div> <div className="bg-white rounded-lg shadow p-6"> <div className="h-6 bg-gray-200 rounded w-1/4 mb-4 animate-pulse"></div> <div className="space-y-3"> {Array.from({ length: 4 }).map((_, i) => ( <div key={i} className="h-8 bg-gray-200 rounded animate-pulse"></div> ))} </div> </div> </div> ); }`; } /** * Format task prompt with growth-specific context * @param {Object} task - Task configuration * @returns {string} Formatted task prompt */ formatTaskPrompt(task) { const basePrompt = super.formatTaskPrompt(task); // Add growth-specific context const growthContext = ` Growth Strategy Context: - Focus on measurable metrics and data-driven optimization - Implement viral mechanics and network effects - Create frictionless user acquisition flows - Build retention and engagement loops - Include comprehensive analytics tracking - Ensure mobile-responsive and accessible design - Provide production-ready error handling`; return `${basePrompt}\n\n${growthContext}`; } /** * Validate growth-specific task requirements * @param {Object} task - Task to validate * @returns {boolean} True if valid */ validateTask(task) { super.validateTask(task); const validTypes = ['viral-loops', 'user-acquisition', 'retention', 'a-b-testing', 'analytics']; if (!validTypes.includes(task.type)) { throw new Error(`Invalid task type: ${task.type}. Must be one of: ${validTypes.join(', ')}`); } return true; } } module.exports = { GrowthHackerAgent };