Тильда + Telegram: мгновенные уведомления о заявках

Заявка с Тильды пришла на почту, но вы увидели её через три часа — клиент уже ушёл к конкуренту. Telegram-уведомления решают эту проблему: сообщение приходит за секунду. Разберём три способа настройки — от простого вебхука до серверлесс-функции.

Способ 1: прямой вебхук на Telegram Bot API

Самый быстрый вариант. Тильда отправляет данные формы на ваш endpoint, а тот пересылает их в Telegram. Но есть нюанс — Тильда не умеет отправлять напрямую в Bot API. Нужна прослойка.

Шаг 1: создаём бота

Откройте @BotFather в Telegram, отправьте /newbot, задайте имя и username. Сохраните токен — он выглядит так: 7123456789:AAH...

Шаг 2: узнаём chat_id

Отправьте боту любое сообщение, затем откройте в браузере:

curl "https://api.telegram.org/bot<TOKEN>/getUpdates"

В ответе найдите "chat":{"id":123456789} — это ваш chat_id. Для группового чата id будет отрицательным.

Шаг 3: серверная прослойка на Python

Минимальный скрипт, который принимает POST от Тильды и пересылает в Telegram:

from fastapi import FastAPI, Request
import httpx

app = FastAPI()

BOT_TOKEN = "7123456789:AAH..."
CHAT_ID = "123456789"

@app.post("/webhook/tilda")
async def tilda_webhook(request: Request):
    data = await request.form()

    lines = ["<b>Новая заявка с сайта</b>\n"]
    field_names = {
        "Name": "Имя",
        "Phone": "Телефон",
        "Email": "Email",
        "Message": "Сообщение",
    }

    for key, value in data.items():
        if key.startswith("tilda") or not value:
            continue
        label = field_names.get(key, key)
        lines.append(f"<b>{label}:</b> {value}")

    text = "\n".join(lines)

    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage",
            json={
                "chat_id": CHAT_ID,
                "text": text,
                "parse_mode": "HTML",
            },
        )

    if resp.status_code != 200:
        return {"ok": False, "error": resp.text}
    return {"ok": True}

В настройках формы на Тильде: «Ещё» → «Webhook» → вставьте URL вашего сервера (https://yourdomain.com/webhook/tilda).

Способ 2: через n8n (no-code)

Если не хотите писать код — используйте n8n. Это open-source платформа автоматизации, можно развернуть бесплатно на своём сервере или использовать n8n.cloud.

Схема workflow

  1. Webhook — принимает POST от Тильды
  2. Set — форматирует текст сообщения
  3. Telegram — отправляет сообщение через Bot API

Настройка ноды Webhook

Создайте workflow, добавьте ноду «Webhook»:

— HTTP Method: POST

— Path: tilda-lead

— Response Mode: Last Node

Скопируйте Production URL — его вставите в настройки формы Тильды.

Настройка ноды Set (форматирование)

Добавьте ноду «Set» и настройте expression для текста:

// Expression в поле "text"
{{ "📋 *Новая заявка*\n\n" +
   "*Имя:* " + ($json.body.Name || "—") + "\n" +
   "*Телефон:* " + ($json.body.Phone || "—") + "\n" +
   "*Email:* " + ($json.body.Email || "—") + "\n" +
   "*Сообщение:* " + ($json.body.Message || "—")
}}

Настройка ноды Telegram

Добавьте ноду «Telegram»:

— Operation: Send Message

— Chat ID: ваш chat_id

— Text: подключите output ноды Set

— Parse Mode: Markdown

— Credentials: добавьте Bot Token

Активируйте workflow — готово.

Способ 3: серверлесс-функция (Vercel / Cloudflare Workers)

Бесплатный и надёжный вариант без собственного сервера. Покажу на Vercel.

Структура проекта

tilda-telegram/
├── api/
│   └── webhook.js
├── package.json
└── vercel.json

api/webhook.js

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const BOT_TOKEN = process.env.BOT_TOKEN;
  const CHAT_ID = process.env.CHAT_ID;

  if (!BOT_TOKEN || !CHAT_ID) {
    return res.status(500).json({ error: 'Missing config' });
  }

  const data = req.body;

  const fieldMap = {
    Name: 'Имя',
    Phone: 'Телефон',
    Email: 'Email',
    Message: 'Сообщение',
  };

  let text = '<b>Новая заявка с сайта</b>\n\n';

  for (const [key, value] of Object.entries(data)) {
    if (key.startsWith('tilda') || !value) continue;
    const label = fieldMap[key] || key;
    text += `<b>${label}:</b> ${value}\n`;
  }

  // Добавляем UTM-метки, если есть
  const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign'];
  const utms = utmKeys
    .filter(k => data[k])
    .map(k => `${k}=${data[k]}`)
    .join(', ');

  if (utms) {
    text += `\n<i>UTM: ${utms}</i>`;
  }

  try {
    const response = await fetch(
      `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          chat_id: CHAT_ID,
          text: text,
          parse_mode: 'HTML',
        }),
      }
    );

    const result = await response.json();

    if (!result.ok) {
      console.error('Telegram API error:', result);
      return res.status(500).json({ error: 'Telegram send failed' });
    }

    return res.status(200).json({ ok: true });
  } catch (error) {
    console.error('Webhook error:', error);
    return res.status(500).json({ error: 'Internal error' });
  }
}

vercel.json

{
  "version": 2,
  "builds": [
    { "src": "api/webhook.js", "use": "@vercel/node" }
  ]
}

Деплой

npm i -g vercel
vercel login
vercel --prod

# Добавляем переменные окружения
vercel env add BOT_TOKEN
vercel env add CHAT_ID

Webhook URL: https://your-project.vercel.app/api/webhook

Форматирование сообщений

Telegram поддерживает HTML и Markdown. Рекомендую HTML — он предсказуемее:

<b>Жирный текст</b>
<i>Курсив</i>
<code>Моноширинный</code>
<a href="https://example.com">Ссылка</a>
<pre>Блок кода</pre>
<s>Зачёркнутый</s>

Не используйте вложенные теги — Telegram их не поддерживает. <b><i>текст</i></b> не сработает.

Обработка ошибок и дублей

Тильда может отправить вебхук повторно, если не получила 200 в ответ. Добавьте защиту от дублей:

const processedIds = new Set();

export default async function handler(req, res) {
  const formId = req.body.tranid || req.body.formid;

  if (formId && processedIds.has(formId)) {
    return res.status(200).json({ ok: true, duplicate: true });
  }

  if (formId) {
    processedIds.add(formId);
    // Очищаем старые записи через 10 минут
    setTimeout(() => processedIds.delete(formId), 600000);
  }

  // ... основная логика
}

Для продакшена вместо Set используйте Redis или KV-хранилище Vercel/Cloudflare.

Уведомления в несколько чатов

Разные формы — разным менеджерам:

const chatRouting = {
  'order': '-100123456789',     // чат отдела продаж
  'support': '-100987654321',   // чат поддержки
  'default': '123456789',       // личный чат владельца
};

function getChatId(formData) {
  const formName = (formData.formname || '').toLowerCase();
  if (formName.includes('заказ')) return chatRouting.order;
  if (formName.includes('поддержк')) return chatRouting.support;
  return chatRouting.default;
}

Сравнение способов

Критерий Прямой вебхук n8n Serverless
Сложность Средняя Низкая Средняя
Стоимость VPS от 300 ₽/мес Бесплатно (self-hosted) Бесплатно (Vercel free tier)
Надёжность Зависит от сервера Зависит от сервера Высокая (CDN)
Кастомизация Полная Через ноды Полная
Обслуживание Сервер, SSL, uptime Обновления n8n Минимальное

Для большинства случаев рекомендую серверлесс-функцию на Vercel — бесплатно, быстро, не нужно следить за сервером. Если уже используете n8n для других автоматизаций — добавьте Telegram как ещё один workflow.

Есть идея? Реализуем

Разрабатываем проекты, которые решают задачи бизнеса — от лендинга до сложного сервиса. Расскажите о своей задаче, подберём решение.

Написать в Telegram

29.03.2026

Нужна консультация?

Оставьте свои контактные данные, или свяжитесь с нами удобным для вас способом

Привет! Меня зовут Багира. Пишите, я все передам хозяевам!

Привет! Меня зовут Багира. Пишите, я все передам хозяевам!

Нажимая кнопку «Принять», вы соглашаетесь на сбор cookie. Мы используем их для обеспечения функционирования веб-сайта, аналитики действий и улучшения качества обслуживания. Если Вы не хотите, чтобы эти данные обрабатывались, отключите cookie в настройках браузера или прекратите использовать сайт.
Принять