n8n Automation

Automatizarea Lead Scoring cu n8n: Construirea de Workflow-uri Inteligente pentru Calificarea Vanzarilor

Petru Constantin
--14 min lectura
#n8n#lead scoring#sales automation#CRM#marketing automation

Automatizarea Lead Scoring cu n8n: Construirea de Workflow-uri Inteligente pentru Calificarea Vanzarilor

Un sistem eficient de lead scoring ajuta echipele de vanzari sa se concentreze pe prospectii cu cel mai mare potential. Acest ghid iti arata cum sa construiesti automatizari inteligente de lead scoring cu n8n.

Framework-ul de Lead Scoring

Motorul Principal de Scorare

// n8n Function Node - Lead Scoring Engine
const leadData = $input.first().json;
 
// Scoring configuration
const scoringModel = {
  demographic: {
    weight: 0.30,
    factors: {
      company_size: {
        'enterprise': 100,
        'mid_market': 80,
        'small_business': 60,
        'startup': 40,
        'unknown': 20
      },
      industry: {
        'technology': 100,
        'finance': 95,
        'healthcare': 90,
        'manufacturing': 85,
        'retail': 75,
        'other': 50
      },
      job_title: {
        patterns: [
          { regex: /^(c-level|ceo|cto|cfo|coo|cmo)/i, score: 100 },
          { regex: /^(vp|vice president|director)/i, score: 90 },
          { regex: /^(head|senior manager|manager)/i, score: 75 },
          { regex: /^(senior|lead|principal)/i, score: 60 },
          { regex: /.+/, score: 40 }
        ]
      },
      location: {
        'tier1_markets': 100,
        'tier2_markets': 80,
        'tier3_markets': 60,
        'other': 40
      }
    }
  },
  behavioral: {
    weight: 0.40,
    factors: {
      page_views: {
        '20+': 100,
        '10-19': 80,
        '5-9': 60,
        '1-4': 40,
        '0': 0
      },
      pricing_page_visits: {
        '3+': 100,
        '2': 80,
        '1': 50,
        '0': 0
      },
      content_downloads: {
        '5+': 100,
        '3-4': 80,
        '1-2': 50,
        '0': 0
      },
      demo_requests: {
        'yes': 100,
        'no': 0
      },
      email_engagement: {
        'high': 100,
        'medium': 60,
        'low': 30,
        'none': 0
      }
    }
  },
  engagement: {
    weight: 0.20,
    factors: {
      email_opens: {
        '10+': 100,
        '5-9': 80,
        '1-4': 50,
        '0': 0
      },
      email_clicks: {
        '5+': 100,
        '2-4': 70,
        '1': 40,
        '0': 0
      },
      webinar_attendance: {
        'attended_live': 100,
        'watched_recording': 70,
        'registered_no_show': 30,
        'none': 0
      },
      social_engagement: {
        'high': 100,
        'medium': 60,
        'low': 30,
        'none': 0
      }
    }
  },
  intent: {
    weight: 0.10,
    factors: {
      recency: {
        '24_hours': 100,
        '7_days': 80,
        '30_days': 50,
        '90_days': 20,
        'older': 0
      },
      frequency: {
        'daily': 100,
        'weekly': 70,
        'monthly': 40,
        'rarely': 10
      }
    }
  }
};
 
// Calculate demographic score
function calculateDemographicScore(lead) {
  let score = 0;
  const factors = scoringModel.demographic.factors;
 
  // Company size
  const sizeScore = factors.company_size[lead.company_size] || factors.company_size['unknown'];
  score += sizeScore * 0.25;
 
  // Industry
  const industryScore = factors.industry[lead.industry] || factors.industry['other'];
  score += industryScore * 0.25;
 
  // Job title
  const titlePatterns = factors.job_title.patterns;
  let titleScore = 40; // default
  for (const pattern of titlePatterns) {
    if (pattern.regex.test(lead.job_title || '')) {
      titleScore = pattern.score;
      break;
    }
  }
  score += titleScore * 0.30;
 
  // Location
  const locationTier = determineLocationTier(lead.country, lead.state);
  const locationScore = factors.location[locationTier] || factors.location['other'];
  score += locationScore * 0.20;
 
  return score;
}
 
// Calculate behavioral score
function calculateBehavioralScore(lead) {
  let score = 0;
  const factors = scoringModel.behavioral.factors;
  const behavior = lead.behavior || {};
 
  // Page views
  const pageViews = behavior.page_views || 0;
  const pvScore = pageViews >= 20 ? 100 : pageViews >= 10 ? 80 : pageViews >= 5 ? 60 : pageViews >= 1 ? 40 : 0;
  score += pvScore * 0.20;
 
  // Pricing page visits
  const pricingVisits = behavior.pricing_page_visits || 0;
  const ppScore = pricingVisits >= 3 ? 100 : pricingVisits === 2 ? 80 : pricingVisits === 1 ? 50 : 0;
  score += ppScore * 0.25;
 
  // Content downloads
  const downloads = behavior.content_downloads || 0;
  const dlScore = downloads >= 5 ? 100 : downloads >= 3 ? 80 : downloads >= 1 ? 50 : 0;
  score += dlScore * 0.20;
 
  // Demo request
  const demoScore = behavior.demo_requested ? 100 : 0;
  score += demoScore * 0.25;
 
  // Email engagement
  const emailEngagement = behavior.email_engagement || 'none';
  const emailScore = factors.email_engagement[emailEngagement] || 0;
  score += emailScore * 0.10;
 
  return score;
}
 
// Calculate engagement score
function calculateEngagementScore(lead) {
  let score = 0;
  const engagement = lead.engagement || {};
 
  // Email opens
  const opens = engagement.email_opens || 0;
  const openScore = opens >= 10 ? 100 : opens >= 5 ? 80 : opens >= 1 ? 50 : 0;
  score += openScore * 0.25;
 
  // Email clicks
  const clicks = engagement.email_clicks || 0;
  const clickScore = clicks >= 5 ? 100 : clicks >= 2 ? 70 : clicks >= 1 ? 40 : 0;
  score += clickScore * 0.30;
 
  // Webinar attendance
  const webinarStatus = engagement.webinar_status || 'none';
  const webinarScore = scoringModel.engagement.factors.webinar_attendance[webinarStatus] || 0;
  score += webinarScore * 0.25;
 
  // Social engagement
  const socialEngagement = engagement.social_engagement || 'none';
  const socialScore = scoringModel.engagement.factors.social_engagement[socialEngagement] || 0;
  score += socialScore * 0.20;
 
  return score;
}
 
// Calculate intent score
function calculateIntentScore(lead) {
  let score = 0;
  const intent = lead.intent || {};
 
  // Recency
  const lastActivityDate = new Date(intent.last_activity || 0);
  const daysSinceActivity = Math.floor((Date.now() - lastActivityDate) / (1000 * 60 * 60 * 24));
 
  let recencyScore = 0;
  if (daysSinceActivity <= 1) recencyScore = 100;
  else if (daysSinceActivity <= 7) recencyScore = 80;
  else if (daysSinceActivity <= 30) recencyScore = 50;
  else if (daysSinceActivity <= 90) recencyScore = 20;
  score += recencyScore * 0.50;
 
  // Frequency
  const visitFrequency = intent.visit_frequency || 'rarely';
  const freqScore = scoringModel.intent.factors.frequency[visitFrequency] || 10;
  score += freqScore * 0.50;
 
  return score;
}
 
function determineLocationTier(country, state) {
  const tier1 = ['US', 'GB', 'CA', 'AU', 'DE'];
  const tier2 = ['FR', 'NL', 'SE', 'NO', 'DK', 'CH', 'JP'];
 
  if (tier1.includes(country)) return 'tier1_markets';
  if (tier2.includes(country)) return 'tier2_markets';
  return 'tier3_markets';
}
 
// Calculate all scores
const demographicScore = calculateDemographicScore(leadData);
const behavioralScore = calculateBehavioralScore(leadData);
const engagementScore = calculateEngagementScore(leadData);
const intentScore = calculateIntentScore(leadData);
 
// Calculate weighted total
const totalScore = Math.round(
  demographicScore * scoringModel.demographic.weight +
  behavioralScore * scoringModel.behavioral.weight +
  engagementScore * scoringModel.engagement.weight +
  intentScore * scoringModel.intent.weight
);
 
// Determine lead grade
function determineGrade(score) {
  if (score >= 80) return 'A';
  if (score >= 60) return 'B';
  if (score >= 40) return 'C';
  if (score >= 20) return 'D';
  return 'F';
}
 
// Determine MQL/SQL status
function determineQualificationStatus(score, grade, lead) {
  // SQL criteria
  if (score >= 75 && lead.behavior?.demo_requested) {
    return 'SQL';
  }
  if (score >= 80) {
    return 'SQL';
  }
 
  // MQL criteria
  if (score >= 50 && grade <= 'B') {
    return 'MQL';
  }
  if (score >= 40 && lead.behavior?.pricing_page_visits >= 2) {
    return 'MQL';
  }
 
  return 'Lead';
}
 
const grade = determineGrade(totalScore);
const qualification = determineQualificationStatus(totalScore, grade, leadData);
 
// Build scoring result
const scoringResult = {
  lead_id: leadData.id,
  email: leadData.email,
  scores: {
    demographic: Math.round(demographicScore),
    behavioral: Math.round(behavioralScore),
    engagement: Math.round(engagementScore),
    intent: Math.round(intentScore),
    total: totalScore
  },
  grade: grade,
  qualification_status: qualification,
  score_breakdown: {
    demographic_factors: {
      company_size: leadData.company_size,
      industry: leadData.industry,
      job_title: leadData.job_title,
      location: leadData.country
    },
    behavioral_factors: {
      page_views: leadData.behavior?.page_views || 0,
      pricing_visits: leadData.behavior?.pricing_page_visits || 0,
      downloads: leadData.behavior?.content_downloads || 0,
      demo_requested: leadData.behavior?.demo_requested || false
    }
  },
  scored_at: new Date().toISOString(),
  previous_score: leadData.previous_score || null,
  score_change: leadData.previous_score ? totalScore - leadData.previous_score : null
};
 
return { json: scoringResult };

Actualizari de Scor in Timp Real

// n8n Function Node - Real-Time Score Updater
const event = $input.first().json;
const currentScores = $('Get Lead Scores').first()?.json || {};
 
// Event scoring adjustments
const eventScoreAdjustments = {
  // Website events
  'page_view': 1,
  'pricing_page_view': 5,
  'product_page_view': 3,
  'case_study_view': 4,
  'blog_post_view': 1,
 
  // Content events
  'ebook_download': 10,
  'whitepaper_download': 12,
  'checklist_download': 8,
  'webinar_registration': 15,
  'webinar_attendance': 20,
 
  // Form submissions
  'demo_request': 30,
  'contact_form': 25,
  'pricing_request': 28,
  'trial_signup': 35,
 
  // Email events
  'email_open': 2,
  'email_click': 5,
  'email_reply': 15,
  'unsubscribe': -20,
 
  // Negative events
  'bounce': -10,
  'spam_complaint': -50,
  'inactive_30_days': -15,
  'inactive_60_days': -25,
  'inactive_90_days': -40
};
 
// Calculate score adjustment
const eventType = event.event_type;
const adjustment = eventScoreAdjustments[eventType] || 0;
 
// Apply decay for old scores
function applyScoreDecay(currentScore, lastActivityDate) {
  const daysSinceActivity = Math.floor(
    (Date.now() - new Date(lastActivityDate).getTime()) / (1000 * 60 * 60 * 24)
  );
 
  // Apply 2% decay per inactive week
  const weeksInactive = Math.floor(daysSinceActivity / 7);
  const decayMultiplier = Math.pow(0.98, weeksInactive);
 
  return Math.round(currentScore * decayMultiplier);
}
 
// Calculate new score
let newBehavioralScore = currentScores.behavioral || 0;
 
// Apply event adjustment
newBehavioralScore += adjustment;
 
// Apply decay if needed
if (event.event_type.includes('inactive')) {
  newBehavioralScore = applyScoreDecay(
    newBehavioralScore,
    currentScores.last_activity_date
  );
}
 
// Ensure score stays within bounds
newBehavioralScore = Math.max(0, Math.min(100, newBehavioralScore));
 
// Check for threshold crossings
const thresholds = {
  mql: 50,
  sql: 75,
  hot_lead: 85
};
 
const previousTotal = currentScores.total || 0;
const newTotal = Math.round(
  currentScores.demographic * 0.30 +
  newBehavioralScore * 0.40 +
  currentScores.engagement * 0.20 +
  currentScores.intent * 0.10
);
 
const thresholdsCrossed = [];
for (const [name, threshold] of Object.entries(thresholds)) {
  if (previousTotal < threshold && newTotal >= threshold) {
    thresholdsCrossed.push({ threshold: name, direction: 'up' });
  } else if (previousTotal >= threshold && newTotal < threshold) {
    thresholdsCrossed.push({ threshold: name, direction: 'down' });
  }
}
 
// Determine actions based on score change
const actions = [];
 
if (thresholdsCrossed.some(t => t.threshold === 'sql' && t.direction === 'up')) {
  actions.push({
    type: 'notify_sales',
    priority: 'high',
    message: `Lead ${event.lead_id} is now SQL (score: ${newTotal})`
  });
  actions.push({
    type: 'create_task',
    assignee: 'sales_round_robin',
    task: `Follow up with SQL: ${event.lead_email}`
  });
}
 
if (thresholdsCrossed.some(t => t.threshold === 'mql' && t.direction === 'up')) {
  actions.push({
    type: 'add_to_nurture',
    campaign: 'mql_nurture',
    message: 'Added to MQL nurture sequence'
  });
}
 
if (thresholdsCrossed.some(t => t.threshold === 'hot_lead' && t.direction === 'up')) {
  actions.push({
    type: 'notify_sales',
    priority: 'urgent',
    message: `Hot lead alert! ${event.lead_id} score: ${newTotal}`
  });
}
 
return {
  json: {
    lead_id: event.lead_id,
    event: eventType,
    score_adjustment: adjustment,
    scores: {
      previous: {
        behavioral: currentScores.behavioral,
        total: previousTotal
      },
      current: {
        behavioral: newBehavioralScore,
        total: newTotal
      }
    },
    thresholds_crossed: thresholdsCrossed,
    actions: actions,
    updated_at: new Date().toISOString()
  }
};

Rutarea Lead-urilor

// n8n Function Node - Lead Router
const scoredLead = $input.first().json;
const salesTeam = $('Get Sales Team').all().map(i => i.json);
 
// Routing rules configuration
const routingRules = {
  enterprise: {
    condition: (lead) => lead.company_size === 'enterprise' || lead.scores.total >= 85,
    team: 'enterprise_sales',
    sla_minutes: 15
  },
  mid_market: {
    condition: (lead) => lead.company_size === 'mid_market' || lead.scores.total >= 70,
    team: 'mid_market_sales',
    sla_minutes: 30
  },
  smb: {
    condition: (lead) => true, // Default
    team: 'smb_sales',
    sla_minutes: 60
  }
};
 
// Industry-specific routing
const industryRouting = {
  'healthcare': 'healthcare_specialist',
  'finance': 'financial_services_specialist',
  'technology': 'tech_specialist'
};
 
// Geographic routing
const geoRouting = {
  'US': { 'CA': 'west_coast_team', 'NY': 'east_coast_team' },
  'GB': 'emea_team',
  'DE': 'emea_team',
  'JP': 'apac_team',
  'AU': 'apac_team'
};
 
function determineRoute(lead) {
  // Determine segment
  let segment = 'smb';
  for (const [seg, rule] of Object.entries(routingRules)) {
    if (rule.condition(lead)) {
      segment = seg;
      break;
    }
  }
 
  // Check for specialist routing
  let specialist = null;
  if (industryRouting[lead.industry]) {
    specialist = industryRouting[lead.industry];
  }
 
  // Check geographic routing
  let geoTeam = null;
  if (geoRouting[lead.country]) {
    if (typeof geoRouting[lead.country] === 'object') {
      geoTeam = geoRouting[lead.country][lead.state] || null;
    } else {
      geoTeam = geoRouting[lead.country];
    }
  }
 
  return {
    segment,
    team: routingRules[segment].team,
    specialist,
    geo_team: geoTeam,
    sla_minutes: routingRules[segment].sla_minutes
  };
}
 
function selectSalesRep(team, availableReps) {
  // Filter by team and availability
  const teamReps = availableReps.filter(rep =>
    rep.team === team && rep.is_available && rep.current_leads < rep.max_leads
  );
 
  if (teamReps.length === 0) {
    // Fall back to any available rep
    const anyAvailable = availableReps.filter(rep =>
      rep.is_available && rep.current_leads < rep.max_leads
    );
    if (anyAvailable.length === 0) return null;
    return anyAvailable.sort((a, b) => a.current_leads - b.current_leads)[0];
  }
 
  // Round-robin with load balancing
  return teamReps.sort((a, b) => {
    // Prioritize by current load
    const loadDiff = a.current_leads - b.current_leads;
    if (loadDiff !== 0) return loadDiff;
 
    // Then by last assignment time
    return new Date(a.last_assigned) - new Date(b.last_assigned);
  })[0];
}
 
const route = determineRoute(scoredLead);
const assignedRep = selectSalesRep(route.team, salesTeam);
 
const routingResult = {
  lead_id: scoredLead.lead_id,
  routing: {
    segment: route.segment,
    team: route.team,
    specialist_required: route.specialist,
    geographic_team: route.geo_team,
    sla_minutes: route.sla_minutes,
    sla_deadline: new Date(Date.now() + route.sla_minutes * 60 * 1000).toISOString()
  },
  assignment: assignedRep ? {
    rep_id: assignedRep.id,
    rep_name: assignedRep.name,
    rep_email: assignedRep.email,
    assigned_at: new Date().toISOString()
  } : null,
  fallback_required: !assignedRep,
  lead_score: scoredLead.scores.total,
  lead_grade: scoredLead.grade,
  qualification: scoredLead.qualification_status
};
 
return { json: routingResult };

Integrarea cu CRM

// n8n Function Node - CRM Sync
const routingResult = $input.first().json;
const scoredLead = $('Lead Scoring').first().json;
 
// Build CRM update payload
function buildCRMPayload(lead, routing) {
  return {
    // Contact fields
    contact: {
      id: lead.lead_id,
      email: lead.email,
      custom_fields: {
        lead_score: lead.scores.total,
        lead_grade: lead.grade,
        demographic_score: lead.scores.demographic,
        behavioral_score: lead.scores.behavioral,
        engagement_score: lead.scores.engagement,
        intent_score: lead.scores.intent,
        last_scored_at: new Date().toISOString()
      }
    },
 
    // Lead stage update
    lifecycle: {
      stage: mapQualificationToStage(lead.qualification_status),
      status: 'active',
      score: lead.scores.total
    },
 
    // Owner assignment
    assignment: routing.assignment ? {
      owner_id: routing.assignment.rep_id,
      assigned_at: routing.assignment.assigned_at,
      assignment_reason: `Auto-routed: ${routing.routing.segment} segment`
    } : null,
 
    // Task creation
    task: routing.assignment ? {
      title: `Follow up with ${lead.qualification_status}: ${lead.email}`,
      description: buildTaskDescription(lead, routing),
      due_date: routing.routing.sla_deadline,
      priority: lead.scores.total >= 80 ? 'high' : 'normal',
      assignee_id: routing.assignment.rep_id,
      type: 'follow_up'
    } : null,
 
    // Activity log
    activity: {
      type: 'score_update',
      timestamp: new Date().toISOString(),
      details: {
        previous_score: lead.previous_score,
        new_score: lead.scores.total,
        score_change: lead.score_change,
        triggered_by: 'automated_scoring'
      }
    }
  };
}
 
function mapQualificationToStage(qualification) {
  const mapping = {
    'Lead': 'new_lead',
    'MQL': 'marketing_qualified',
    'SQL': 'sales_qualified',
    'Opportunity': 'opportunity'
  };
  return mapping[qualification] || 'new_lead';
}
 
function buildTaskDescription(lead, routing) {
  return `
## Lead Overview
- **Score**: ${lead.scores.total} (Grade: ${lead.grade})
- **Status**: ${lead.qualification_status}
- **Segment**: ${routing.routing.segment}
 
## Score Breakdown
- Demographic: ${lead.scores.demographic}/100
- Behavioral: ${lead.scores.behavioral}/100
- Engagement: ${lead.scores.engagement}/100
- Intent: ${lead.scores.intent}/100
 
## Key Signals
${lead.score_breakdown.behavioral_factors.demo_requested ? '- ✅ Requested demo\n' : ''}
${lead.score_breakdown.behavioral_factors.pricing_visits > 0 ? `- 👀 Visited pricing page ${lead.score_breakdown.behavioral_factors.pricing_visits} times\n` : ''}
${lead.score_breakdown.behavioral_factors.downloads > 0 ? `- 📥 Downloaded ${lead.score_breakdown.behavioral_factors.downloads} resources\n` : ''}
 
## SLA
- **Deadline**: ${routing.routing.sla_deadline}
- **Time allowed**: ${routing.routing.sla_minutes} minutes
  `.trim();
}
 
const crmPayload = buildCRMPayload(scoredLead, routingResult);
 
// Build notification for sales rep
const notification = routingResult.assignment ? {
  type: 'new_lead_assignment',
  recipient: routingResult.assignment.rep_email,
  subject: `New ${scoredLead.qualification_status} Assigned: ${scoredLead.email}`,
  body: {
    lead_email: scoredLead.email,
    score: scoredLead.scores.total,
    grade: scoredLead.grade,
    sla_deadline: routingResult.routing.sla_deadline,
    quick_view_url: `${process.env.CRM_URL}/leads/${scoredLead.lead_id}`
  },
  channel: scoredLead.scores.total >= 80 ? 'slack_dm' : 'email'
} : null;
 
return {
  json: {
    crm_payload: crmPayload,
    notification: notification,
    metadata: {
      lead_id: scoredLead.lead_id,
      processed_at: new Date().toISOString()
    }
  }
};

Analiza si Raportare

// n8n Function Node - Scoring Analytics
const allLeads = $input.all().map(i => i.json);
 
// Calculate scoring metrics
const metrics = {
  total_leads: allLeads.length,
  by_grade: { A: 0, B: 0, C: 0, D: 0, F: 0 },
  by_qualification: { Lead: 0, MQL: 0, SQL: 0 },
  score_distribution: [],
  conversion_rates: {},
  average_scores: {
    demographic: 0,
    behavioral: 0,
    engagement: 0,
    intent: 0,
    total: 0
  }
};
 
// Aggregate metrics
for (const lead of allLeads) {
  metrics.by_grade[lead.grade] = (metrics.by_grade[lead.grade] || 0) + 1;
  metrics.by_qualification[lead.qualification_status] = (metrics.by_qualification[lead.qualification_status] || 0) + 1;
 
  metrics.average_scores.demographic += lead.scores.demographic;
  metrics.average_scores.behavioral += lead.scores.behavioral;
  metrics.average_scores.engagement += lead.scores.engagement;
  metrics.average_scores.intent += lead.scores.intent;
  metrics.average_scores.total += lead.scores.total;
}
 
// Calculate averages
const count = allLeads.length || 1;
for (const key in metrics.average_scores) {
  metrics.average_scores[key] = Math.round(metrics.average_scores[key] / count);
}
 
// Score distribution buckets
const buckets = [
  { min: 0, max: 20, label: '0-20' },
  { min: 21, max: 40, label: '21-40' },
  { min: 41, max: 60, label: '41-60' },
  { min: 61, max: 80, label: '61-80' },
  { min: 81, max: 100, label: '81-100' }
];
 
for (const bucket of buckets) {
  const count = allLeads.filter(l =>
    l.scores.total >= bucket.min && l.scores.total <= bucket.max
  ).length;
  metrics.score_distribution.push({
    range: bucket.label,
    count,
    percentage: Math.round((count / allLeads.length) * 100)
  });
}
 
// Calculate conversion rates (would need historical data)
metrics.conversion_rates = {
  mql_to_sql: 0.35, // Placeholder
  sql_to_opportunity: 0.45,
  opportunity_to_won: 0.25
};
 
// Build report
const report = {
  generated_at: new Date().toISOString(),
  period: 'last_30_days',
  metrics,
  insights: generateInsights(metrics),
  recommendations: generateRecommendations(metrics)
};
 
function generateInsights(metrics) {
  const insights = [];
 
  const aGradePercent = (metrics.by_grade.A / metrics.total_leads) * 100;
  if (aGradePercent < 10) {
    insights.push({
      type: 'warning',
      message: `Only ${aGradePercent.toFixed(1)}% of leads are A-grade. Consider reviewing acquisition channels.`
    });
  }
 
  const avgScore = metrics.average_scores.total;
  if (avgScore < 40) {
    insights.push({
      type: 'info',
      message: `Average lead score is ${avgScore}. Focus on lead quality improvement.`
    });
  }
 
  return insights;
}
 
function generateRecommendations(metrics) {
  const recommendations = [];
 
  if (metrics.average_scores.behavioral < 40) {
    recommendations.push({
      area: 'engagement',
      recommendation: 'Implement more interactive content to boost behavioral scores'
    });
  }
 
  if (metrics.by_qualification.MQL > metrics.by_qualification.SQL * 3) {
    recommendations.push({
      area: 'conversion',
      recommendation: 'Review MQL to SQL conversion - consider adjusting thresholds or nurture campaigns'
    });
  }
 
  return recommendations;
}
 
return { json: report };

Bune Practici

Designul Lead Scoring-ului

  1. Incepe simplu: Porneste cu un scoring de baza si rafineaza pe parcurs
  2. Valideaza cu echipa de vanzari: Asigura-te ca scorurile se coreleaza cu conversiile reale
  3. Calibrare regulata: Ajusteaza ponderile pe baza datelor de performanta
  4. Scorare negativa: Nu uita sa penalizezi lipsa de engagement

Sfaturi de Implementare

  • Actualizeaza scorurile in timp real pentru actiuni prompte
  • Implementeaza score decay pentru lead-urile inactive
  • Creeaza procese clare de predare la depasirea pragurilor
  • Monitorizeaza regulat acuratetea modelului de scoring

Automatizarea lead scoring-ului cu n8n asigura calificare consistenta, permitand in acelasi timp echipelor de vanzari sa se concentreze pe oportunitatile cu cel mai mare potential.

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.