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
- Personalizeaza pe segment: Clienti diferiti au nevoie de fluxuri de onboarding diferite
- Urmareste milestone-urile: Defineste metrici clare de succes pentru fiecare etapa de onboarding
- Intervino devreme: Monitorizeaza scorurile de sanatate si actioneaza inainte ca clientii sa plece
- 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.