n8n Automation

Automatizare onboarding clienti cu n8n: Workflow-uri complete de la inceput la sfarsit

Petru Constantin
--15 min lectura
#n8n#customer onboarding#automation#CRM#user experience

Automatizare onboarding clienti cu n8n: Workflow-uri complete de la inceput la sfarsit

Un onboarding eficient al clientilor stimuleaza retentia si satisfactia. Acest ghid arata cum sa construiesti automatizari complete de onboarding cu n8n pentru experiente fluide ale clientilor.

Arhitectura workflow-ului de onboarding

Handler trigger client nou

// n8n Function Node - New Customer Processor
const webhookData = $input.first().json;
 
// Validate incoming customer data
const requiredFields = ['email', 'name', 'plan'];
const missingFields = requiredFields.filter(f => !webhookData[f]);
 
if (missingFields.length > 0) {
  throw new Error(`Missing required fields: ${missingFields.join(', ')}`);
}
 
// Normalize and enrich customer data
const customer = {
  id: webhookData.customer_id || `cust_${Date.now()}`,
  email: webhookData.email.toLowerCase().trim(),
  firstName: extractFirstName(webhookData.name),
  lastName: extractLastName(webhookData.name),
  fullName: webhookData.name,
  company: webhookData.company || null,
  plan: webhookData.plan,
  planTier: determinePlanTier(webhookData.plan),
  source: webhookData.source || 'website',
  signupDate: new Date().toISOString(),
  timezone: webhookData.timezone || 'UTC',
  locale: webhookData.locale || 'en',
  metadata: {
    utm_source: webhookData.utm_source,
    utm_medium: webhookData.utm_medium,
    utm_campaign: webhookData.utm_campaign,
    referrer: webhookData.referrer
  }
};
 
// Determine onboarding path
const onboardingPath = determineOnboardingPath(customer);
 
function extractFirstName(fullName) {
  return fullName.split(' ')[0];
}
 
function extractLastName(fullName) {
  const parts = fullName.split(' ');
  return parts.length > 1 ? parts.slice(1).join(' ') : '';
}
 
function determinePlanTier(plan) {
  const tiers = {
    'starter': 'basic',
    'professional': 'standard',
    'business': 'premium',
    'enterprise': 'enterprise'
  };
  return tiers[plan.toLowerCase()] || 'basic';
}
 
function determineOnboardingPath(customer) {
  // Clientii enterprise primesc onboarding personalizat
  if (customer.planTier === 'enterprise') {
    return {
      type: 'enterprise',
      steps: ['sales_handoff', 'kickoff_call', 'custom_setup', 'training', 'go_live'],
      assignedCSM: true,
      duration: '30_days'
    };
  }
 
  // Premium primeste onboarding ghidat
  if (customer.planTier === 'premium') {
    return {
      type: 'guided',
      steps: ['welcome', 'setup_wizard', 'demo_call', 'training_videos', 'check_in'],
      assignedCSM: false,
      duration: '14_days'
    };
  }
 
  // Onboarding self-service standard
  return {
    type: 'self_service',
    steps: ['welcome', 'setup_wizard', 'email_sequence', 'in_app_guides'],
    assignedCSM: false,
    duration: '7_days'
  };
}
 
return {
  json: {
    customer,
    onboarding: {
      path: onboardingPath,
      startedAt: new Date().toISOString(),
      currentStep: 0,
      completedSteps: [],
      status: 'started'
    }
  }
};

Workflow de provizionare utilizatori

// n8n Function Node - Account Provisioning
const { customer, onboarding } = $input.first().json;
 
// Generate secure credentials
const provisioning = {
  customerId: customer.id,
  accountId: `acc_${generateSecureId()}`,
  apiKey: `sk_live_${generateSecureId(32)}`,
  webhookSecret: `whsec_${generateSecureId(24)}`,
  tempPassword: generateTempPassword(),
  passwordResetToken: generateSecureId(48),
  tokenExpiry: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString() // 24 ore
};
 
// Determine initial setup based on plan
const initialSetup = {
  features: getFeaturesByPlan(customer.plan),
  limits: getLimitsByPlan(customer.plan),
  defaults: getDefaultSettings(customer.planTier),
  integrations: []
};
 
// Create provisioning tasks
const tasks = [
  {
    type: 'create_account',
    data: {
      accountId: provisioning.accountId,
      email: customer.email,
      name: customer.fullName,
      plan: customer.plan
    }
  },
  {
    type: 'create_api_credentials',
    data: {
      accountId: provisioning.accountId,
      apiKey: provisioning.apiKey,
      webhookSecret: provisioning.webhookSecret
    }
  },
  {
    type: 'setup_initial_config',
    data: initialSetup
  },
  {
    type: 'create_sample_data',
    data: {
      accountId: provisioning.accountId,
      templates: getSampleTemplates(customer.planTier)
    }
  }
];
 
function generateSecureId(length = 16) {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
}
 
function generateTempPassword() {
  const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  const lower = 'abcdefghijklmnopqrstuvwxyz';
  const numbers = '0123456789';
  const special = '!@#$%^&*';
 
  let password = '';
  password += upper.charAt(Math.floor(Math.random() * upper.length));
  password += lower.charAt(Math.floor(Math.random() * lower.length));
  password += numbers.charAt(Math.floor(Math.random() * numbers.length));
  password += special.charAt(Math.floor(Math.random() * special.length));
 
  const allChars = upper + lower + numbers + special;
  for (let i = 0; i < 8; i++) {
    password += allChars.charAt(Math.floor(Math.random() * allChars.length));
  }
 
  return password.split('').sort(() => Math.random() - 0.5).join('');
}
 
function getFeaturesByPlan(plan) {
  const features = {
    starter: ['basic_dashboard', 'email_support', 'api_access'],
    professional: ['advanced_analytics', 'priority_support', 'api_access', 'integrations'],
    business: ['custom_reports', 'dedicated_support', 'advanced_api', 'sso', 'audit_logs'],
    enterprise: ['all_features', 'custom_development', 'sla', 'dedicated_infrastructure']
  };
  return features[plan.toLowerCase()] || features.starter;
}
 
function getLimitsByPlan(plan) {
  const limits = {
    starter: { users: 5, storage_gb: 10, api_calls_monthly: 10000 },
    professional: { users: 25, storage_gb: 100, api_calls_monthly: 100000 },
    business: { users: 100, storage_gb: 500, api_calls_monthly: 500000 },
    enterprise: { users: -1, storage_gb: -1, api_calls_monthly: -1 } // Nelimitat
  };
  return limits[plan.toLowerCase()] || limits.starter;
}
 
function getDefaultSettings(tier) {
  return {
    notifications: { email: true, in_app: true, slack: tier !== 'basic' },
    security: { mfa_required: tier === 'enterprise', session_timeout: 3600 },
    privacy: { analytics_enabled: true, crash_reports: true }
  };
}
 
function getSampleTemplates(tier) {
  const templates = ['getting_started', 'basic_workflow'];
  if (tier !== 'basic') {
    templates.push('advanced_automation', 'reporting_template');
  }
  if (tier === 'enterprise') {
    templates.push('enterprise_integration', 'compliance_workflow');
  }
  return templates;
}
 
return {
  json: {
    customer,
    onboarding,
    provisioning,
    tasks
  }
};

Secventa de email-uri de bun venit

// n8n Function Node - Email Sequence Builder
const { customer, onboarding, provisioning } = $input.first().json;
 
// Build personalized email sequence
const emailSequence = [];
 
// Ziua 0 - Email de bun venit
emailSequence.push({
  day: 0,
  hours: 0,
  template: 'welcome',
  subject: `Welcome to ${process.env.COMPANY_NAME}, ${customer.firstName}!`,
  personalization: {
    firstName: customer.firstName,
    plan: customer.plan,
    loginUrl: `${process.env.APP_URL}/login`,
    passwordResetUrl: `${process.env.APP_URL}/reset-password?token=${provisioning.passwordResetToken}`,
    supportEmail: process.env.SUPPORT_EMAIL
  },
  tags: ['onboarding', 'day_0', 'welcome']
});
 
// Ziua 1 - Ghid de inceput
emailSequence.push({
  day: 1,
  hours: 10, // Trimite la ora 10 in fusul orar al clientului
  template: 'getting_started',
  subject: `Get started with ${process.env.COMPANY_NAME} in 5 minutes`,
  personalization: {
    firstName: customer.firstName,
    quickStartUrl: `${process.env.APP_URL}/quickstart`,
    videoTutorialUrl: `${process.env.DOCS_URL}/tutorials/getting-started`,
    features: getTopFeatures(customer.plan)
  },
  tags: ['onboarding', 'day_1', 'education'],
  condition: {
    type: 'not_completed',
    milestone: 'first_login'
  }
});
 
// Ziua 3 - Prezentare functionalitate
emailSequence.push({
  day: 3,
  hours: 14,
  template: 'feature_spotlight',
  subject: `Did you know? ${getFeatureSpotlight(customer.plan).title}`,
  personalization: {
    firstName: customer.firstName,
    feature: getFeatureSpotlight(customer.plan),
    cta_url: `${process.env.APP_URL}/features/${getFeatureSpotlight(customer.plan).slug}`
  },
  tags: ['onboarding', 'day_3', 'feature'],
  condition: {
    type: 'not_used',
    feature: getFeatureSpotlight(customer.plan).slug
  }
});
 
// Ziua 5 - Sugestii de integrari
if (customer.planTier !== 'basic') {
  emailSequence.push({
    day: 5,
    hours: 10,
    template: 'integrations',
    subject: `Connect ${process.env.COMPANY_NAME} to your favorite tools`,
    personalization: {
      firstName: customer.firstName,
      suggestedIntegrations: getSuggestedIntegrations(customer),
      integrationsUrl: `${process.env.APP_URL}/integrations`
    },
    tags: ['onboarding', 'day_5', 'integrations']
  });
}
 
// Ziua 7 - Verificare
emailSequence.push({
  day: 7,
  hours: 10,
  template: 'check_in',
  subject: `How's it going, ${customer.firstName}?`,
  personalization: {
    firstName: customer.firstName,
    usageStats: '{{usage_stats}}', // Placeholder pentru date dinamice
    feedbackUrl: `${process.env.APP_URL}/feedback`,
    bookCallUrl: onboarding.path.type !== 'self_service' ?
      `${process.env.CALENDLY_URL}/onboarding-call` : null
  },
  tags: ['onboarding', 'day_7', 'engagement']
});
 
// Ziua 14 - Sfaturi de succes (pentru onboarding ghidat)
if (onboarding.path.type !== 'self_service') {
  emailSequence.push({
    day: 14,
    hours: 10,
    template: 'success_tips',
    subject: `Pro tips for ${customer.plan} users`,
    personalization: {
      firstName: customer.firstName,
      tips: getProTips(customer.planTier),
      communityUrl: `${process.env.COMMUNITY_URL}`,
      webinarUrl: `${process.env.APP_URL}/webinars`
    },
    tags: ['onboarding', 'day_14', 'education']
  });
}
 
function getTopFeatures(plan) {
  const features = {
    starter: [
      { name: 'Dashboard', description: 'Vezi toate datele tale dintr-o privire' },
      { name: 'Reports', description: 'Genereaza rapoarte de baza' }
    ],
    professional: [
      { name: 'Advanced Analytics', description: 'Analizeaza in profunzime metricile tale' },
      { name: 'Integrations', description: 'Conecteaza instrumentele tale preferate' }
    ],
    business: [
      { name: 'Custom Reports', description: 'Construieste rapoarte dupa nevoile tale' },
      { name: 'Team Collaboration', description: 'Lucreaza eficient in echipa' }
    ],
    enterprise: [
      { name: 'SSO', description: 'Autentificare unica securizata' },
      { name: 'Audit Logs', description: 'Urmarire completa a activitatii' }
    ]
  };
  return features[plan.toLowerCase()] || features.starter;
}
 
function getFeatureSpotlight(plan) {
  const spotlights = {
    starter: { title: 'Automated Reminders', slug: 'reminders', description: 'Nu mai rata taskuri importante' },
    professional: { title: 'Workflow Automation', slug: 'workflows', description: 'Automatizeaza taskurile repetitive' },
    business: { title: 'Custom Dashboards', slug: 'dashboards', description: 'Construieste vizualizarea perfecta' },
    enterprise: { title: 'API Access', slug: 'api', description: 'Construieste integrari personalizate' }
  };
  return spotlights[plan.toLowerCase()] || spotlights.starter;
}
 
function getSuggestedIntegrations(customer) {
  // Ar fi bazat pe industria/cazul de utilizare al clientului
  return [
    { name: 'Slack', icon: 'slack', description: 'Primeste notificari in Slack' },
    { name: 'Google Calendar', icon: 'google-calendar', description: 'Sincronizeaza programul tau' },
    { name: 'Zapier', icon: 'zapier', description: 'Conecteaza 3000+ aplicatii' }
  ];
}
 
function getProTips(tier) {
  return [
    'Foloseste scurtaturi de tastatura pentru navigare mai rapida',
    'Configureaza rezumate saptamanale prin email pentru actualizari de echipa',
    'Creeaza template-uri pentru taskurile frecvente'
  ];
}
 
// Calculeaza orele de trimitere
const scheduledEmails = emailSequence.map(email => {
  const sendDate = new Date(customer.signupDate);
  sendDate.setDate(sendDate.getDate() + email.day);
  sendDate.setHours(email.hours, 0, 0, 0);
 
  return {
    ...email,
    scheduledAt: sendDate.toISOString(),
    recipientEmail: customer.email,
    recipientName: customer.fullName,
    customerId: customer.id
  };
});
 
return {
  json: {
    customer,
    onboarding,
    emailSequence: scheduledEmails
  }
};

Urmarire progres

// n8n Function Node - Onboarding Progress Tracker
const customer = $input.first().json.customer;
const currentProgress = $('Get Current Progress').first()?.json || {};
 
// Defineste milestone-urile de onboarding
const milestones = {
  self_service: [
    { id: 'account_created', name: 'Cont creat', weight: 10 },
    { id: 'first_login', name: 'Prima autentificare', weight: 15 },
    { id: 'profile_completed', name: 'Profil completat', weight: 10 },
    { id: 'first_project', name: 'Primul proiect creat', weight: 20 },
    { id: 'invited_team', name: 'Membru echipa invitat', weight: 15 },
    { id: 'used_core_feature', name: 'Functionalitate principala folosita', weight: 20 },
    { id: 'completed_tutorial', name: 'Tutorial finalizat', weight: 10 }
  ],
  guided: [
    { id: 'account_created', name: 'Cont creat', weight: 5 },
    { id: 'first_login', name: 'Prima autentificare', weight: 10 },
    { id: 'profile_completed', name: 'Profil completat', weight: 5 },
    { id: 'demo_completed', name: 'Apel demo finalizat', weight: 15 },
    { id: 'first_project', name: 'Primul proiect creat', weight: 15 },
    { id: 'integration_setup', name: 'Integrare configurata', weight: 15 },
    { id: 'invited_team', name: 'Echipa invitata', weight: 15 },
    { id: 'training_completed', name: 'Training finalizat', weight: 20 }
  ],
  enterprise: [
    { id: 'kickoff_completed', name: 'Apel kickoff finalizat', weight: 10 },
    { id: 'requirements_gathered', name: 'Cerinte colectate', weight: 10 },
    { id: 'environment_setup', name: 'Mediu configurat', weight: 15 },
    { id: 'sso_configured', name: 'SSO configurat', weight: 10 },
    { id: 'data_migration', name: 'Migrare date completa', weight: 15 },
    { id: 'team_training', name: 'Training echipa complet', weight: 15 },
    { id: 'pilot_launched', name: 'Pilot lansat', weight: 10 },
    { id: 'go_live', name: 'Go Live complet', weight: 15 }
  ]
};
 
// Ia milestone-urile relevante pentru client
const customerMilestones = milestones[currentProgress.onboardingType] || milestones.self_service;
 
// Calculeaza progresul
const completedMilestones = currentProgress.completedMilestones || [];
const completedWeight = customerMilestones
  .filter(m => completedMilestones.includes(m.id))
  .reduce((sum, m) => sum + m.weight, 0);
 
const progressPercentage = Math.round(completedWeight);
 
// Determina pasul curent
const pendingMilestones = customerMilestones.filter(m => !completedMilestones.includes(m.id));
const nextMilestone = pendingMilestones[0];
 
// Calculeaza scorul de sanatate
const healthScore = calculateHealthScore(customer, currentProgress);
 
// Determina daca este nevoie de interventie
const intervention = checkForIntervention(customer, currentProgress, healthScore);
 
function calculateHealthScore(customer, progress) {
  let score = 100;
 
  // Zile de la inregistrare
  const daysSinceSignup = Math.floor(
    (Date.now() - new Date(customer.signupDate).getTime()) / (1000 * 60 * 60 * 24)
  );
 
  // Penalizeaza progresul lent
  const expectedProgress = Math.min(daysSinceSignup * 10, 70); // Asteapta ~70% pana in ziua 7
  const actualProgress = progressPercentage;
 
  if (actualProgress < expectedProgress) {
    score -= (expectedProgress - actualProgress);
  }
 
  // Penalizeaza lipsa activitatii recente
  const lastActivity = progress.lastActivityAt ?
    Math.floor((Date.now() - new Date(progress.lastActivityAt).getTime()) / (1000 * 60 * 60 * 24)) : daysSinceSignup;
 
  if (lastActivity > 3) {
    score -= (lastActivity - 3) * 5;
  }
 
  // Bonus pentru actiuni cheie
  if (completedMilestones.includes('invited_team')) score += 10;
  if (completedMilestones.includes('integration_setup')) score += 10;
 
  return Math.max(0, Math.min(100, score));
}
 
function checkForIntervention(customer, progress, healthScore) {
  const interventions = [];
 
  // Scor de sanatate scazut
  if (healthScore < 50) {
    interventions.push({
      type: 'low_health',
      action: 'personal_outreach',
      priority: 'high',
      message: 'Clientul poate avea nevoie de asistenta'
    });
  }
 
  // Fara autentificare dupa 48 de ore
  if (!progress.completedMilestones?.includes('first_login')) {
    const hoursSinceSignup = (Date.now() - new Date(customer.signupDate).getTime()) / (1000 * 60 * 60);
    if (hoursSinceSignup > 48) {
      interventions.push({
        type: 'no_login',
        action: 'reminder_email',
        priority: 'medium',
        message: 'Clientul nu s-a autentificat'
      });
    }
  }
 
  // Blocat la un anumit milestone
  if (progress.stalledAt) {
    interventions.push({
      type: 'stalled_progress',
      action: 'help_content',
      priority: 'medium',
      milestone: progress.stalledAt,
      message: `Clientul este blocat la ${progress.stalledAt}`
    });
  }
 
  return interventions;
}
 
// Construieste raportul de progres
const progressReport = {
  customerId: customer.id,
  email: customer.email,
  plan: customer.plan,
  onboardingType: currentProgress.onboardingType || 'self_service',
  startedAt: customer.signupDate,
  lastActivityAt: currentProgress.lastActivityAt,
  progress: {
    percentage: progressPercentage,
    completedMilestones: completedMilestones,
    pendingMilestones: pendingMilestones.map(m => m.id),
    nextMilestone: nextMilestone,
    totalMilestones: customerMilestones.length
  },
  healthScore: healthScore,
  interventionsNeeded: intervention,
  status: progressPercentage >= 100 ? 'completed' :
          progressPercentage >= 50 ? 'on_track' :
          healthScore < 50 ? 'at_risk' : 'in_progress',
  generatedAt: new Date().toISOString()
};
 
return { json: progressReport };

Ghiduri personalizate in aplicatie

// n8n Function Node - In-App Guide Builder
const customer = $input.first().json;
const userBehavior = $('Get User Behavior').first()?.json || {};
 
// Defineste template-uri de ghiduri
const guideTemplates = {
  welcome_tour: {
    id: 'welcome_tour',
    name: 'Tur de bun venit',
    type: 'product_tour',
    steps: [
      {
        target: '#dashboard',
        title: 'Dashboard-ul tau',
        content: 'Aici vei vedea toate metricile importante dintr-o privire.',
        position: 'bottom'
      },
      {
        target: '#create-button',
        title: 'Creeaza primul tau proiect',
        content: 'Apasa aici pentru a incepe primul proiect. Te vom ghida prin proces.',
        position: 'right'
      },
      {
        target: '#settings-menu',
        title: 'Personalizeaza experienta',
        content: 'Acceseaza setarile pentru a personaliza spatiul de lucru.',
        position: 'left'
      }
    ],
    trigger: 'first_login',
    dismissible: true
  },
 
  feature_discovery: {
    id: 'feature_discovery',
    name: 'Descoperire functionalitati',
    type: 'tooltip_sequence',
    steps: [
      {
        target: '#analytics-tab',
        title: 'Analytics',
        content: 'Analizeaza in profunzime datele tale cu analytics avansat.',
        position: 'bottom',
        condition: { plan_tier: ['standard', 'premium', 'enterprise'] }
      },
      {
        target: '#automations',
        title: 'Automatizari',
        content: 'Configureaza workflow-uri automatizate pentru a economisi timp.',
        position: 'right'
      }
    ],
    trigger: 'milestone_completed',
    milestone: 'first_project'
  },
 
  empty_state_prompt: {
    id: 'empty_state_prompt',
    name: 'Prompt de inceput',
    type: 'modal',
    content: {
      title: 'Sa incepem!',
      body: 'Creeaza primul proiect pentru a debloca potentialul complet al platformei.',
      cta_text: 'Creeaza proiect',
      cta_action: 'open_create_modal',
      secondary_text: 'Vezi tutorial',
      secondary_action: 'open_tutorial'
    },
    trigger: 'empty_state',
    entity: 'projects'
  },
 
  integration_prompt: {
    id: 'integration_prompt',
    name: 'Sugestie integrari',
    type: 'banner',
    content: {
      title: 'Conecteaza instrumentele tale',
      body: 'Integreaza cu aplicatiile preferate pentru a eficientiza workflow-ul.',
      cta_text: 'Vezi integrari',
      cta_action: 'navigate_integrations'
    },
    trigger: 'time_in_app',
    threshold_minutes: 30,
    condition: { integrations_count: 0 }
  },
 
  upgrade_prompt: {
    id: 'upgrade_prompt',
    name: 'Prompt upgrade',
    type: 'modal',
    content: {
      title: 'Deblocheaza mai multe functionalitati',
      body: 'Folosesti {{usage_percentage}}% din limitele planului tau. Fa upgrade pentru mai mult.',
      features: ['Proiecte nelimitate', 'Analytics avansat', 'Suport prioritar'],
      cta_text: 'Vezi planuri',
      cta_action: 'navigate_pricing'
    },
    trigger: 'usage_threshold',
    threshold: 80
  }
};
 
// Determina ce ghiduri sa afiseze pe baza starii utilizatorului
function selectGuidesForUser(customer, behavior) {
  const selectedGuides = [];
  const now = new Date();
  const signupDate = new Date(customer.signupDate);
  const daysSinceSignup = Math.floor((now - signupDate) / (1000 * 60 * 60 * 24));
 
  // Prima autentificare - afiseaza turul de bun venit
  if (behavior.loginCount <= 1 && !behavior.completedGuides?.includes('welcome_tour')) {
    selectedGuides.push({
      ...guideTemplates.welcome_tour,
      priority: 1,
      reason: 'Prima autentificare'
    });
  }
 
  // Dupa primul proiect - afiseaza descoperire functionalitati
  if (behavior.projectsCreated >= 1 && !behavior.completedGuides?.includes('feature_discovery')) {
    const guide = guideTemplates.feature_discovery;
    // Filtreaza pasii pe baza planului
    guide.steps = guide.steps.filter(step => {
      if (!step.condition) return true;
      if (step.condition.plan_tier) {
        return step.condition.plan_tier.includes(customer.planTier);
      }
      return true;
    });
    selectedGuides.push({
      ...guide,
      priority: 2,
      reason: 'Primul proiect finalizat'
    });
  }
 
  // Stare goala - indeamna la creare
  if (behavior.projectsCreated === 0 && daysSinceSignup >= 1) {
    selectedGuides.push({
      ...guideTemplates.empty_state_prompt,
      priority: 1,
      reason: 'Niciun proiect dupa 24 de ore'
    });
  }
 
  // Prompt integrari dupa timp petrecut in aplicatie
  if (behavior.totalMinutesInApp >= 30 &&
      behavior.integrationsCount === 0 &&
      !behavior.dismissedGuides?.includes('integration_prompt')) {
    selectedGuides.push({
      ...guideTemplates.integration_prompt,
      priority: 3,
      reason: 'Nicio integrare dupa 30 de minute'
    });
  }
 
  // Prompt upgrade la pragul de utilizare
  if (behavior.usagePercentage >= 80 && customer.planTier !== 'enterprise') {
    const guide = { ...guideTemplates.upgrade_prompt };
    guide.content.body = guide.content.body.replace('{{usage_percentage}}', behavior.usagePercentage);
    selectedGuides.push({
      ...guide,
      priority: 2,
      reason: 'Utilizare ridicata'
    });
  }
 
  return selectedGuides.sort((a, b) => a.priority - b.priority);
}
 
// Personalizeaza continutul ghidului
function personalizeGuide(guide, customer) {
  const personalized = JSON.parse(JSON.stringify(guide));
 
  // Inlocuieste placeholder-urile
  const replacements = {
    '{{firstName}}': customer.firstName,
    '{{company}}': customer.company || 'echipa ta',
    '{{plan}}': customer.plan
  };
 
  const contentStr = JSON.stringify(personalized);
  let personalizedContent = contentStr;
  for (const [placeholder, value] of Object.entries(replacements)) {
    personalizedContent = personalizedContent.replace(new RegExp(placeholder, 'g'), value);
  }
 
  return JSON.parse(personalizedContent);
}
 
const selectedGuides = selectGuidesForUser(customer, userBehavior);
const personalizedGuides = selectedGuides.map(guide => personalizeGuide(guide, customer));
 
return {
  json: {
    customerId: customer.id,
    guides: personalizedGuides,
    behavior: userBehavior,
    generatedAt: new Date().toISOString()
  }
};

Finalizare si predare

// n8n Function Node - Onboarding Completion Handler
const progressReport = $input.first().json;
 
// Verifica daca onboarding-ul este complet
const isComplete = progressReport.progress.percentage >= 100;
const isTimedOut = checkOnboardingTimeout(progressReport);
 
// Determina pasii urmatori
function determineNextSteps(report) {
  if (isComplete) {
    return {
      action: 'complete_onboarding',
      tasks: [
        { type: 'send_completion_email', template: 'onboarding_complete' },
        { type: 'update_customer_stage', stage: 'active' },
        { type: 'trigger_nps_survey', delay_days: 7 },
        { type: 'schedule_success_call', condition: 'premium_or_higher' }
      ]
    };
  }
 
  if (isTimedOut) {
    return {
      action: 'escalate_stalled',
      tasks: [
        { type: 'notify_csm', priority: 'high' },
        { type: 'send_reengagement_email', template: 'stuck_onboarding' },
        { type: 'create_support_ticket', reason: 'Onboarding blocat' }
      ]
    };
  }
 
  if (report.interventionsNeeded.length > 0) {
    return {
      action: 'intervention_required',
      tasks: report.interventionsNeeded.map(i => ({
        type: `handle_${i.type}`,
        ...i
      }))
    };
  }
 
  return {
    action: 'continue_monitoring',
    tasks: []
  };
}
 
function checkOnboardingTimeout(report) {
  const maxDays = {
    self_service: 14,
    guided: 30,
    enterprise: 60
  };
 
  const daysSinceStart = Math.floor(
    (Date.now() - new Date(report.startedAt).getTime()) / (1000 * 60 * 60 * 24)
  );
 
  const timeout = maxDays[report.onboardingType] || 14;
  return daysSinceStart > timeout && report.progress.percentage < 100;
}
 
// Construieste raportul de finalizare
const completionReport = {
  customerId: progressReport.customerId,
  email: progressReport.email,
  plan: progressReport.plan,
  onboardingType: progressReport.onboardingType,
  finalStatus: isComplete ? 'completed' : isTimedOut ? 'timed_out' : 'in_progress',
  completionPercentage: progressReport.progress.percentage,
  healthScore: progressReport.healthScore,
  completedMilestones: progressReport.progress.completedMilestones,
  pendingMilestones: progressReport.progress.pendingMilestones,
  timeToComplete: isComplete ? calculateTimeToComplete(progressReport) : null,
  nextSteps: determineNextSteps(progressReport),
  recommendations: generateRecommendations(progressReport),
  reportedAt: new Date().toISOString()
};
 
function calculateTimeToComplete(report) {
  const start = new Date(report.startedAt);
  const end = new Date();
  return Math.floor((end - start) / (1000 * 60 * 60 * 24)); // zile
}
 
function generateRecommendations(report) {
  const recommendations = [];
 
  if (report.progress.percentage < 50) {
    recommendations.push({
      type: 'engagement',
      message: 'Ia in considerare o abordare personalizata pentru a imbunatati engagement-ul'
    });
  }
 
  if (!report.progress.completedMilestones.includes('invited_team')) {
    recommendations.push({
      type: 'expansion',
      message: 'Incurajeaza invitatiile in echipa pentru o adoptie mai buna'
    });
  }
 
  if (report.healthScore < 70) {
    recommendations.push({
      type: 'support',
      message: 'Se recomanda un apel proactiv de suport'
    });
  }
 
  return recommendations;
}
 
return { json: completionReport };

Bune practici

Design de onboarding

  1. Personalizeaza pe segment: Clienti diferiti au nevoie de fluxuri de onboarding diferite
  2. Urmareste milestone-urile: Defineste metrici clare de succes pentru fiecare etapa de onboarding
  3. Intervino devreme: Monitorizeaza scorurile de sanatate si actioneaza inainte ca clientii sa plece
  4. Itereaza continuu: Imbunatateste pe baza ratelor de finalizare si a feedback-ului

Sfaturi de automatizare

  • Foloseste secvente de email conditionate pe baza actiunilor utilizatorului
  • Implementeaza pauze inteligente intre punctele de contact
  • Combina ghiduri in aplicatie cu email pentru engagement pe mai multe canale
  • Urmareste fiecare interactiune pentru optimizare

Onboarding-ul automatizat cu n8n asigura experiente consistente si personalizate care contribuie la succesul si retentia clientilor.

Ai nevoie de ajutor cu conformitatea EU AI Act sau securitatea AI?

Programeaza o consultatie gratuita de 30 de minute. Fara obligatii.

Programeaza un Apel

Weekly AI Security & Automation Digest

Get the latest on AI Security, workflow automation, secure integrations, and custom platform development delivered weekly.

No spam. Unsubscribe anytime.