AskHandle

AskHandle Blog

How to Build a Lead Generation Bot Without a Chatbot Builder

June 12, 2025Nina Kimes3 min read
  • Lead Generation
  • Chatbot
  • JSON-driven

How to Build a Lead Generation Bot Without a Chatbot Builder

Most chatbot tools make it easy to drag, drop, and deploy — until you hit a wall.

Maybe you want full control over logic. Maybe you need to integrate with your own backend. Or maybe you just don’t want to pay for yet another SaaS.

Whatever the reason, if you're ready to build a lead generation chatbot using code, without any external builder, this guide walks you through how to do it — cleanly, scalably, and with future flexibility in mind.

We’ll create a bot that collects:

  • Name
  • Date of Birth
  • Phone Number

But rather than a brittle switch or if-else setup, we’ll use a JSON-driven conversation structure. This makes the bot logic:

  • Easier to expand
  • Easier to debug
  • Easy to jump between steps or insert validation

Let’s dive in.

Step 1: Define the Bot Flow in JSON

First, define the lead collection steps in a modular format:

js
1// flow.js
2module.exports = [
3  {
4    key: "name",
5    [prompt](/glossary/prompt): "Hi! What's your name?",
6    validate: (input) => input.length > 1,
7    error: "Please enter a valid name.",
8  },
9  {
10    key: "dob",
11    prompt: "Great. What's your date of birth?",
12    validate: (input) => /\d{4}-\d{2}-\d{2}/.test(input),
13    error: "Please use YYYY-MM-DD format.",
14  },
15  {
16    key: "phone",
17    prompt: "Thanks! What's your phone number?",
18    validate: (input) => /^\+?\d{10,15}$/.test(input),
19    error: "Enter a valid phone number.",
20  },
21];

This structure can later support branching, conditional logic, and even localization.

Step 2: Set Up the Bot Engine (Node.js + Express)

This is the core of the chatbot logic:

js
1// server.js
2const express = require("express");
3const bodyParser = require("body-parser");
4const flow = require("./flow");
5
6const app = express();
7app.use(bodyParser.json());
8
9let sessions = {}; // In-memory session store
10
11app.post("/chat", (req, res) => {
12  const { sessionId, message } = req.body;
13
14  if (!sessions[sessionId]) {
15    sessions[sessionId] = { step: 0, data: {} };
16  }
17
18  const session = sessions[sessionId];
19  const step = flow[session.step];
20
21  if (!step) {
22    return res.json({ reply: "You're all done. Thanks!" });
23  }
24
25  if (message) {
26    if (!step.validate(message)) {
27      return res.json({ reply: step.error });
28    }
29
30    session.data[step.key] = message;
31    session.step++;
32  }
33
34  const nextStep = flow[session.step];
35  if (nextStep) {
36    return res.json({ reply: nextStep.prompt });
37  } else {
38    return res.json({
39      reply: `Thanks! Here's what we got:\n${Object.entries(session.data)
40        .map(([k, v]) => `${k}: ${v}`)
41        .join("\n")}`,
42    });
43  }
44});
45
46app.listen(3000, () => console.log("Bot running on http://localhost:3000"));

This code:

  • Tracks user progress through the flow
  • Validates inputs
  • Handles dynamic response generation
  • Easily supports features like "back" commands, skipping, or conditional paths

Step 3: Simple Chat UI (Optional)

You can quickly test this with a basic HTML page:

html
1<!-- index.html -->
2<div id="chat"></div>
3<input id="input" placeholder="Type here..." />
4<button onclick="send()">Send</button>
5
6<script>
7  const sessionId = Math.random().toString(36).substr(2, 9);
8
9  async function send() {
10    const input = document.getElementById('input');
11    const message = input.value;
12    append("You: " + message);
13    input.value = '';
14
15    const res = await fetch('/chat', {
16      method: 'POST',
17      headers: { 'Content-Type': 'application/json' },
18      body: JSON.stringify({ sessionId, message }),
19    });
20
21    const data = await res.json();
22    append("Bot: " + data.reply);
23  }
24
25  function append(text) {
26    const chat = document.getElementById('chat');
27    chat.innerHTML += `<div>${text}</div>`;
28  }
29
30  // Start the conversation
31  fetch('/chat', {
32    method: 'POST',
33    headers: { 'Content-Type': 'application/json' },
34    body: JSON.stringify({ sessionId, message: '' }),
35  }).then(res => res.json()).then(data => append("Bot: " + data.reply));
36</script>

This JSON-first, code-driven approach gives you:

  • 🔄 Modularity – Add, remove, or reorder questions easily
  • 🔒 Control – Validate inputs however you like
  • 🔗 Integration – Seamlessly plug into your backend or database
  • 🚀 Scalability – Build multi-step flows, support “back” commands, or even A/B test flows with ease

And it’s all yours — no vendor lock-in, no limits, and no hidden costs.

If you're building a serious product and want full ownership of your lead gen experience, building your own chatbot with a JSON-driven engine is a no-brainer.

It’s lightweight, flexible, and future-proof — and once set up, can be just as easy to manage as any no-code tool.