How to Build a Telegram Bot That Captures Leads 24/7

Building a lead-capturing Telegram bot requires a robust architecture to handle state, data persistence, and process management. We will use aiogram 3.x for its asynchronous performance and gspread for Google Sheets integration.

Prerequisites and Setup

You need a VPS running Ubuntu 22.04+, Python 3.10+, and a Telegram Bot Token from @BotFather.

Checklist

  • [ ] Telegram Bot Token.
  • [ ] Google Cloud Project with "Google Sheets API" and "Google Drive API" enabled.
  • [ ] A JSON service account key (downloaded from Google Cloud).
  • [ ] A shared Google Sheet (share the email from your JSON key with edit access).

Project Structure

lead_bot/
├── bot.py          # Main logic
├── config.py       # API keys and constants
├── requirements.txt
├── service_account.json
└── venv/

Implementation

1. Dependencies

Create requirements.txt:

aiogram==3.4.1
gspread==6.0.2
oauth2client==4.1.3

2. Google Sheets Integration

Create sheets.py to handle data storage:

import gspread
from oauth2client.service_account import ServiceAccountCredentials

scope = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/spreadsheets']
creds = ServiceAccountCredentials.from_json_keyfile_name('service_account.json', scope)
client = gspread.authorize(creds)
sheet = client.open("Leads").sheet1

def save_lead(user_id, username, phone):
    sheet.append_row([user_id, username, phone])

3. Bot Logic with Anti-Spam

We use aiogram's middleware for basic anti-spam (rate limiting).

import asyncio
from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from sheets import save_lead

bot = Bot(token="YOUR_TOKEN")
dp = Dispatcher()

class LeadForm(StatesGroup):
    waiting_for_phone = State()

@dp.message(Command("start"))
async def start(message: types.Message):
    kb = [[types.InlineKeyboardButton(text="Leave Contact", callback_data="get_lead")]]
    await message.answer("Welcome! Click below to leave your contact.", reply_markup=types.InlineKeyboardMarkup(inline_keyboard=kb))

@dp.callback_query(F.data == "get_lead")
async def ask_phone(call: types.CallbackQuery, state: FSMContext):
    await call.message.answer("Please send your phone number.")
    await state.set_state(LeadForm.waiting_for_phone)

@dp.message(LeadForm.waiting_for_phone)
async def process_phone(message: types.Message, state: FSMContext):
    save_lead(message.from_user.id, message.from_user.username, message.text)
    await message.answer("Thanks! We will contact you soon.")
    await state.clear()

async def main():
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

Deployment on VPS with Systemd

Running the bot as a background process is non-negotiable. Do not use screen or nohup.

Step 1: Prepare the environment

sudo apt update && sudo apt install python3-venv -y
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Step 2: Create a systemd service

Create a file: /etc/systemd/system/leadbot.service

[Unit]
Description=Telegram Lead Bot
After=network.target

[Service]
User=root
WorkingDirectory=/root/lead_bot
ExecStart=/root/lead_bot/venv/bin/python /root/lead_bot/bot.py
Restart=always

[Install]
WantedBy=multi-user.target

Step 3: Enable and Start

sudo systemctl daemon-reload
sudo systemctl enable leadbot
sudo systemctl start leadbot

Common Mistakes to Avoid

  1. Hardcoding Tokens: Never commit your service_account.json or bot tokens to GitHub. Use environment variables (os.getenv) or a .env file.
  2. Blocking Operations: Do not use time.sleep() in an async bot. Always use await asyncio.sleep(). Blocking the event loop will freeze the bot for all users.
  3. Ignoring Errors: If the Google Sheet API rate limits you, the bot will crash. Wrap your save_lead call in a try-except block to log errors without stopping the bot.
  4. Missing FSM Storage: By default, aiogram stores states in memory. If the bot restarts, active leads are lost. For production, use RedisStorage.
  5. Not Handling User Input: Users will send text when you expect a number. Always validate input using Regex or simple length checks before saving to the CRM.

Maintenance Checklist

  • Check logs: journalctl -u leadbot -f
  • Monitor Google Sheet API quotas in the Google Cloud Console.
  • Ensure the VPS firewall allows only necessary ports (SSH 22).

Need this done for you? Hire me on Freelancehunt: https://freelancehunt.com/freelancer/sspoisk

Originally posted at https://guardlabs.online/care/

Комментарии

Популярные сообщения из этого блога

Как обновить 40 000 товаров на OkayCMS за секунды и не потерять 120 тысяч рублей на заказах

Архитектура торговых систем: уроки инженера-строителя