n8n Automation

n8n automatizare onboarding clienti: end-to-end

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

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.


Sistemul tau AI e conform cu EU AI Act? Evaluare gratuita de risc - afla in 2 minute →

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

Programează o consultație de 30 de minute, pe cheltuiala noastră. Fără obligații.

Programeaza un Apel

Înainte de apel poți vedea ce construim, cum stabilim prețul, cât costă de obicei o automatizare cu AI sau ne poți scrie direct.

Weekly AI Agents, Automation & Security Digest

How we build AI agents and automations with Claude Code, plus practical AI security, integrations, and platform notes, delivered weekly.

No spam. Unsubscribe anytime.