3. Full Conversation Flow
The chatbot collects information across 12 questions. The flow is designed to feel natural and conversational while capturing all data required for lead scoring and CRM entry. Below is the complete script with expected user responses.

  OPENING
🤖  Hi! 👋 Welcome to Jasmiza! I’m here to help you find the right solution for your team or yourself.
🤖  May I know your name?

  Q1 — Name  (Required)
🤖  May I know your name?
👤  [Lead types their name, e.g. Ahmad Zaki]
Capture: FullName

  Q2 — Company  (Skippable, +4 if provided)
🤖  Nice to meet you, [Name]! 😊 Which company or organisation are you from?
🤖  (Type skip if you prefer not to share)
👤  [Lead types company name OR 'skip']
Capture: CompanyName (null if skipped)  |  Scoring: +4 if provided

  Q3 — Service Interest  (Required, scored)
🤖  We offer 3 services. Which one interests you most?
🤖  1️⃣  Personal Coaching
🤖  2️⃣  In-house Training
🤖  3️⃣  Competency Diagnosis
👤  [Lead replies 1, 2, or 3]
Capture: ServiceInterest  |  Scoring: 1=+4, 2=+6, 3=+8

  Q4 — Service-Specific Follow-Up  (Conditional)
This question adapts based on Q3 selection:

If Personal Coaching selected:
🤖  Is this coaching for yourself, or for someone in your organisation?

If In-house Training selected:
🤖  Approximately how many people will be joining the training?

If Competency Diagnosis selected:
🤖  Is this for an individual assessment or a team / department-wide assessment?
👤  [Lead types their answer]
Capture: ServiceScopeDetail  |  Stored in Sales Notes

  Q5 — Purpose and Context  (Free text, scored on length)
🤖  Could you tell me a little about what you are hoping to achieve?
🤖  (e.g. improve leadership skills, train a team, assess staff competency)
👤  [Lead types their answer]
Capture: PurposeContext  |  Scoring: +3 if response > 50 words  |  Stored in Sales Notes

  Q6 — Biggest Challenge  (Free text, scored on length)
🤖  What is the biggest challenge you are currently facing that made you reach out to us today?
👤  [Lead types their answer]
Capture: BiggestChallenge  |  Scoring: +3 if response > 50 words  |  Appended to Sales Notes

  Q7 — Previous Experience  (+3 if Yes)
🤖  Have you worked with a training or coaching provider before?
🤖  1️⃣  Yes
🤖  2️⃣  No
👤  [Lead replies 1 or 2]
Capture: PreviousExperience (Boolean)  |  Scoring: +3 if Yes

  Q8 — Lead Source  (Scored)
🤖  How did you get to know about us?
🤖  1️⃣  Referred by someone
🤖  2️⃣  Social media (Instagram / Facebook / TikTok)
🤖  3️⃣  Google search
🤖  4️⃣  Other
👤  [Lead replies 1, 2, 3, or 4]
Capture: LeadSource  |  Scoring: Referral=+5, Social/Google=+2, Other=+1

  Q9 — Urgency  (Required, highest weight)
🤖  When are you looking to get started?
🤖  1️⃣  As soon as possible
🤖  2️⃣  Within the next 3 months
🤖  3️⃣  Just exploring for now
👤  [Lead replies 1, 2, or 3]
Capture: UrgencyLevel  |  Scoring: ASAP=+10, 3 months=+6, Exploring=+2

  Q10 — Preferred Language
🤖  What is your preferred language for communication?
🤖  1️⃣  English
🤖  2️⃣  Bahasa Malaysia
🤖  3️⃣  Both are fine
👤  [Lead replies 1, 2, or 3]
Capture: PreferredLanguage  |  Used by sales rep for follow-up

  Q11 — Contact Preference  (+3 if complete)
🤖  Almost done! 😊 How would you like our team to reach you?
🤖  1️⃣  WhatsApp (this number)
🤖  2️⃣  Email
👤  [Lead replies 1 or 2]
Capture: ContactMethod  |  Scoring: +3 if answer provided

  Q12 — Email Address  (Conditional on Q11 = Email)
🤖  Please share your email address and we will get back to you shortly.
👤  [Lead types email address]
Capture: ContactEmail  |  Null if WhatsApp chosen in Q11

  CLOSING
🤖  Thank you, [Name]! 🙏 Our team will be in touch with you soon.
🤖  Have a wonderful day! ✨


4. Lead Scoring Rules
After the conversation ends, the Twilio Function calculates the lead score by summing all applicable criteria from the table below. The score determines the Hot, Warm, or Cold classification that is stored in the CRM.

Criteria	Parameter	Score	Max
Service Interest	Competency Diagnosis	+8	8
    In-house Training	+6	
    Personal Coaching	+4	
Urgency	As soon as possible	+10	10
    Within 3 months	+6	
    Just exploring	+2	
Company Provided	Yes (not skipped)	+4	4
Contact Complete	Name + contact provided	+3	3
Previous Experience	Has worked with provider before	+3	3
Lead Source	Referral	+5	5
    Social media / Google	+2	
Response Detail (Q5)	Answer > 50 words	+3	3
Response Detail (Q6)	Challenge description > 50 words	+3	3
TOTAL MAXIMUM			39

4.1  Score Bands
Band	Score Range	Label
Cold	0 - 10	Cold Lead
Warm	11 - 20	Warm Lead
Hot	21+	Hot Lead



4.2  Scoring Logic (Twilio Function Pseudocode)
function calculateScore(session) {
  let score = 0;
 
  // Service Interest
  if (session.serviceInterest === 'competency_diagnosis') score += 8;
  else if (session.serviceInterest === 'in_house_training')  score += 6;
  else if (session.serviceInterest === 'personal_coaching')  score += 4;
 
  // Urgency
  if (session.urgency === 'asap')          score += 10;
  else if (session.urgency === '3_months') score += 6;
  else if (session.urgency === 'exploring') score += 2;
 
  // Company provided
  if (session.company && session.company !== 'skip') score += 4;
 
  // Contact completeness
  if (session.name && session.contactMethod) score += 3;
 
  // Previous experience
  if (session.previousExperience === 'yes') score += 3;
 
  // Lead source
  if (session.source === 'referral')        score += 5;
  else if (['social', 'google'].includes(session.source)) score += 2;
  else                                      score += 1;
 
  // Response detail (word count)
  if (wordCount(session.purposeContext)   > 50) score += 3;
  if (wordCount(session.biggestChallenge) > 50) score += 3;
 
  // Assign band
  session.leadScore   = score;
  session.leadSegment = score >= 21 ? 'Hot' : score >= 11 ? 'Warm' : 'Cold';
  return session;
}
 

5.2  Flow Widget Structure
Build the Studio flow using the following widget sequence:

•	Trigger widget: incomingMessage (entry point)
•	Send Message widget: Opening greeting
•	Send & Wait for Reply widgets: Q1 through Q12 (one widget per question)
•	Split Based On widget: after Q3 to branch into service-specific Q4
•	Split Based On widget: after Q11 to branch into Q12 (email only)
•	Run Function widget: score-and-submit (calls the Twilio Function at end of flow)
•	Send Message widget: Closing message

5.3  Storing Answers in Flow Variables
Use Set Variables widgets after each Send and Wait for Reply widget to capture the answer into a flow variable. Naming convention:

{{contact.channel_attributes.from}}  -> phone (auto from Twilio)
{{widgets.q1_name.inbound.Body}}      -> var_name
{{widgets.q2_company.inbound.Body}}   -> var_company
{{widgets.q3_service.inbound.Body}}   -> var_service
{{widgets.q4_scope.inbound.Body}}     -> var_scope
{{widgets.q5_purpose.inbound.Body}}   -> var_purpose
{{widgets.q6_challenge.inbound.Body}} -> var_challenge
{{widgets.q7_experience.inbound.Body}}-> var_experience
{{widgets.q8_source.inbound.Body}}    -> var_source
{{widgets.q9_urgency.inbound.Body}}   -> var_urgency
{{widgets.q10_language.inbound.Body}} -> var_language
{{widgets.q11_contact.inbound.Body}}  -> var_contact_method
{{widgets.q12_email.inbound.Body}}    -> var_email
 
6. Twilio Function: score-and-submit
This function is triggered at the end of the Studio flow. It receives all collected session variables, calculates the lead score, and POSTs the result to the Jasmiza CRM API.

6.1  Function Code (Node.js)
exports.handler = async function(context, event, callback) {
  const axios = require('axios');
 
  // Map Twilio flow variables
  const session = {
    phone:             event.phone,
    name:              event.var_name,
    company:           event.var_company,
    serviceInterest:   mapService(event.var_service),
    serviceScopeDetail:event.var_scope,
    purposeContext:    event.var_purpose,
    biggestChallenge:  event.var_challenge,
    previousExperience:event.var_experience === '1' ? 'yes' : 'no',
    source:            mapSource(event.var_source),
    urgency:           mapUrgency(event.var_urgency),
    preferredLanguage: mapLanguage(event.var_language),
    contactMethod:     event.var_contact_method === '1' ? 'whatsapp' : 'email',
    contactEmail:      event.var_email || null,
    chatTranscript:    buildTranscript(event),
  };
 
  // Calculate score
  const scored = calculateScore(session);
 
  // POST to Jasmiza CRM
  try {
    await axios.post(context.JASMIZA_CRM_API_URL, scored, {
      headers: { Authorization: 'Bearer ' + context.JASMIZA_API_KEY }
    });
  } catch (err) {
    console.error('CRM POST failed:', err.message);
  }
 
  return callback(null, {});
};
 
function mapService(v) {
  return { '1':'personal_coaching','2':'in_house_training','3':'competency_diagnosis' }[v] || 'unknown';
}
function mapSource(v) {
  return { '1':'referral','2':'social','3':'google','4':'other' }[v] || 'other';
}
function mapUrgency(v) {
  return { '1':'asap','2':'3_months','3':'exploring' }[v] || 'exploring';
}
function mapLanguage(v) {
  return { '1':'english','2':'bahasa_malaysia','3':'both' }[v] || 'both';
}
function wordCount(str) {
  return str ? str.trim().split(/\s+/).length : 0;
}
function buildTranscript(event) {
  return [
    'Q1 Name: '              + event.var_name,
    'Q2 Company: '           + event.var_company,
    'Q3 Service: '           + event.var_service,
    'Q4 Scope: '             + event.var_scope,
    'Q5 Purpose: '           + event.var_purpose,
    'Q6 Challenge: '         + event.var_challenge,
    'Q7 Experience: '        + event.var_experience,
    'Q8 Source: '            + event.var_source,
    'Q9 Urgency: '           + event.var_urgency,
    'Q10 Language: '         + event.var_language,
    'Q11 Contact Method: '   + event.var_contact_method,
    'Q12 Email: '            + (event.var_email || 'N/A'),
  ].join('\n');
}
 
7. CRM API Payload Specification
The Twilio Function POSTs a JSON payload to the Jasmiza CRM. The CRM API endpoint must accept this structure and create a new lead record.

7.1  Sample POST Payload
POST /api/leads/whatsapp-ingest
Authorization: Bearer <JASMIZA_API_KEY>
Content-Type: application/json
 
{
  "phone":              "+60123456789",
  "name":               "Ahmad Zaki",
  "company":            "Zaki Solutions",
  "serviceInterest":    "personal_coaching",
  "serviceScopeDetail": "For myself",
  "purposeContext":     "Looking to improve leadership presence...",
  "biggestChallenge":   "Struggling to manage a growing team...",
  "previousExperience": "yes",
  "source":             "referral",
  "urgency":            "asap",
  "preferredLanguage":  "english",
  "contactMethod":      "whatsapp",
  "contactEmail":       null,
  "leadScore":          24,
  "leadSegment":        "Hot",
  "chatTranscript":     "Q1 Name: Ahmad Zaki\nQ2 Company: ...",
  "dateTimeCaptured":   "2026-05-19T10:30:00Z"
}

7.2  CRM Field Mapping
CRM Field	Twilio Source	Notes
FullName	From (WA number) + Q1 answer	Extracted from conversation state
Phone	From (WA number)	Auto-captured from Twilio webhook
CompanyName	Q2 answer	Null if lead types 'skip'
ServiceInterest	Q3 selection (1/2/3)	Mapped to service name
ServiceScopeDetail	Q4 answer	Scope answer specific to service
PurposeContext	Q5 free text	Stored in Sales Notes
BiggestChallenge	Q6 free text	Appended to Sales Notes
PreviousExperience	Q7 selection (1/2)	Boolean: Yes/No
LeadSource	Q8 selection (1/2/3/4)	Referral / Social / Google / Other
UrgencyLevel	Q9 selection (1/2/3)	ASAP / 3 months / Exploring
PreferredLanguage	Q10 selection (1/2/3)	EN / BM / Both
ContactMethod	Q11 selection (1/2)	WhatsApp or Email
ContactEmail	Q12 free text (if email chosen)	Null if WhatsApp chosen
LeadScore	Auto-calculated	Sum of scoring rules
LeadSegment	Auto-assigned	Cold / Warm / Hot based on score
ChatTranscript	Full conversation log	Stored as text in CRM database
DateTimeCaptured	Twilio timestamp	Auto-captured on session end
 
