Guía completa de integración de analítica de producto — SaaS B2B
| Evento | Propiedades | Origen | Objetivo |
|---|---|---|---|
| Sign Up | method (google|email), referrer | Frontend | Analizar canales de adquisición |
| Onboarding Step | step_number (1–5), step_name, completed | Frontend | Detectar puntos de abandono |
| Feature Used | feature (crear_flujo|aprobar_tarea|invitar_miembro|conectar_integration), plan | Ambos | Medir adopción de features |
| Purchase | plan (starter|pro|enterprise), amount, currency | Backend | Atribución de revenue |
| Subscription Cancelled | reason (precio|funcionalidad|competencia|sin_uso), days_active, plan | Backend | Análisis de churn |
import mixpanel from 'mixpanel-browser' export function initMixpanel() { mixpanel.init(process.env.NEXT_PUBLIC_MIXPANEL_TOKEN!, { debug: process.env.NODE_ENV === 'development', track_pageview: 'url-with-path', persistence: 'localStorage', ignore_dnt: false, batch_requests: true, batch_size: 50, batch_flush_interval_ms: 5000, }) }
import mixpanel from 'mixpanel-browser' // Identifica al usuario tras login / signup export function identifyFlowDeskUser( userId: string, traits: { email: string; name: string; plan: string; company: string } ) { mixpanel.identify(userId) mixpanel.people.set({ $email: traits.email, $name: traits.name, plan: traits.plan, // 'starter' | 'pro' | 'enterprise' company: traits.company, signed_up_at: new Date().toISOString(), }) } // Evento de registro export function trackSignUp(method: 'google' | 'email', referrer?: string) { mixpanel.track('Sign Up', { method, referrer: referrer || 'direct' }) mixpanel.people.set_once({ 'First Sign Up Date': new Date().toISOString() }) } // Paso de onboarding (pasos 1–5) export function trackOnboardingStep( step: 1 | 2 | 3 | 4 | 5, stepName: 'crear_cuenta' | 'verificar_email' | 'crear_flujo' | 'invitar_miembro' | 'conectar_integration', completed: boolean ) { mixpanel.track('Onboarding Step', { step_number: step, step_name: stepName, completed, }) } // Uso de feature type FlowDeskFeature = 'crear_flujo' | 'aprobar_tarea' | 'invitar_miembro' | 'conectar_integration' export function trackFeatureUsed(feature: FlowDeskFeature, plan: string) { mixpanel.track('Feature Used', { feature, plan }) mixpanel.people.increment('total_feature_uses') }
import Mixpanel from 'mixpanel' const mp = Mixpanel.init(process.env.MIXPANEL_TOKEN!, { host: 'api-eu.mixpanel.com', // residencia de datos EU (RGPD) }) type FlowPlan = 'starter' | 'pro' | 'enterprise' type ChurnReason = 'precio' | 'funcionalidad' | 'competencia' | 'sin_uso' // Suscripción nueva — se llama desde el webhook de Stripe export function trackSubscription(userId: string, plan: FlowPlan, mrr: number) { mp.track('Purchase', { distinct_id: userId, plan, amount: mrr, currency: 'eur', }) mp.people.set(userId, { plan, mrr, subscription_date: new Date().toISOString(), }) mp.people.track_charge(userId, mrr) } // Cancelación — webhook de Stripe customer.subscription.deleted export function trackChurn( userId: string, reason: ChurnReason, daysActive: number, plan: FlowPlan ) { mp.track('Subscription Cancelled', { distinct_id: userId, reason, days_active: daysActive, plan, }) mp.people.set(userId, { plan: 'free', churned: true, churn_reason: reason }) }
import mixpanel from 'mixpanel-browser' // Vincula usuario a su empresa (en login o signup) export function setUserWorkspace( companyId: string, companyName: string, plan: 'starter' | 'pro' | 'enterprise', seats: number ) { mixpanel.set_group('company', companyId) mixpanel.get_group('company', companyId).set({ $name: companyName, plan, seats, product: 'FlowDesk', }) } // Trackea un evento a nivel de empresa (no solo del usuario individual) export function trackWorkspaceEvent( companyId: string, event: 'Flujo Creado' | 'Miembro Invitado' | 'Integración Conectada', props: Record<string, any> = {} ) { mixpanel.track_with_groups(event, props, { company: companyId }) }
import requests from datetime import date, timedelta import json # ─── Credenciales del Service Account de Mixpanel ─────────────────── PROJECT_ID = "flowdesk_prod_project_id" SA_USERNAME = "service-account@flowdesk.mixpanel.com" SA_SECRET = "sa_secret_key_here" AUTH = (SA_USERNAME, SA_SECRET) def export_raw_events(from_date: date, to_date: date) -> list: """Exporta eventos crudos (NDJSON) para un rango de fechas.""" r = requests.get( 'https://data.mixpanel.com/api/2.0/export', auth=AUTH, params={ 'from_date': from_date.isoformat(), 'to_date': to_date.isoformat(), 'project_id': PROJECT_ID, 'event': '["Sign Up","Feature Used","Purchase","Subscription Cancelled"]', }, stream=True ) return [json.loads(line) for line in r.iter_lines() if line] def import_historical_batch(events: list[dict]) -> None: """Importa eventos históricos (migración desde sistema legacy).""" import base64 credentials = base64.b64encode(SA_SECRET.encode() + b':').decode() requests.post( 'https://api-eu.mixpanel.com/import', params={'strict': 1, 'project_id': PROJECT_ID}, headers={ 'Content-Type': 'application/json', 'Authorization': f'Basic {credentials}', }, json=events ) # ─── Uso rápido ───────────────────────────────────────────────────── if __name__ == '__main__': today = date.today() last_week = today - timedelta(days=7) events = export_raw_events(last_week, today) print(f"Exportados {len(events)} eventos de la última semana")