---
title: "VK Lead Forms и Google Sheets через n8n | Nodbot"
source_url: "https://nodbot.ru/workflows/vk-lead-form-to-sheets/"
canonical_url: "https://nodbot.ru/workflows/vk-lead-form-to-sheets/"
language: "ru"
content_type: "WorkflowTemplate"
section: "workflows"
generated_at: "2026-05-30"
word_count_source: 1202
---

# VK Lead Forms → n8n → Google Sheets: заявки с UTM без дублей

## AI summary

Практический workflow для заявок VK Lead Forms: принять lead_id, нормализовать телефон и UTM, найти строку в Google Sheets по стабильному ключу, обновить существующую запись или добавить новую, а ошибки API отправить в alert/DLQ.

## Best used for

Полноценный Problem/Solution-мануал для внедрения в n8n: импортировать workflow JSON, настроить API, выполнить production-тесты и передать решение команде.

## Table of contents

- Проблема: где ломается сценарий
- Архитектура workflow
- Контракт входных данных
- Code Node: нормализация и контроль
- Готовый workflow JSON
- Пошаговая настройка
- Тесты перед production
- Production-риски
- Полезные ссылки и смежные workflow
- Критерии готовности

## Key topics

- VK Lead Forms
- n8n
- Google Sheets
- upsert
- UTM
- lead_id
- deduplication
- VK Ads

## Source outline

VK Lead Forms → n8n → Google Sheets: заявки с UTM без дублей ¶ Обновлено: 2026-05-30 AI summary: Практический workflow для заявок VK Lead Forms: принять lead_id, нормализовать телефон и UTM, найти строку в Google Sheets по стабильному ключу, обновить существующую запись или добавить новую, а ошибки API отправить в alert/DLQ. Шаблон для внедрения Скачать workflow JSON Скачать test payload Скопировать curl Импортируйте workflow, замените credentials и прогоните тестовый payload до включения production. Содержание Проблема: где ломается сценарий Архитектура workflow Контракт входных данных Code Node: нормализация и контроль Готовый workflow JSON Пошаговая настройка Тесты перед production Production-риски Полезные ссылки и смежные workflow Критерии готовности Проблема: лиды из VK Lead Forms часто приходят повторно, содержат телефон в разных форматах и теряют рекламные метки при ручной выгрузке. Если каждый lead append-ить в Google Sheets, менеджеры быстро получают дубли и грязную таблицу. Решение: делаем контролируемую интеграцию VK Lead Forms и Google Sheets через n8n: используем `lead_id` и нормализованный телефон как ключи, сохраняем UTM в отдельные колонки, обновляем существующую строку и добавляем новые заявки только при настоящем новом лиде. Workflow принимает заявку VK Lead Forms, нормализует телефон и UTM, находит строку и делает update или append. Проблема: почему VK Lead Forms создают дубли в Google Sheets ¶ В рекламной воронке VK Lead Ads Google Sheets часто используется как быстрый операционный буфер: маркетолог смотрит заявки, менеджер отмечает статус, руководитель выгружает отчёт. Но append каждой заявки превращает таблицу в хаос: повторный lead, одинаковый телефон, разные UTM и ручные правки создают несколько строк на одного клиента. Эта страница решает конкретную задачу: настроить передачу данных из формы VK в Google Sheets через n8n так, чтобы строка обновлялась по `lead_id` или телефону, а не плодила дубли. При этом UTM, форма, кампания и статус обработки остаются отдельными колонками. Архитектура workflow VK Lead Forms → n8n → Sheets ¶ Нода Роль Что проверить VK lead event передаёт lead_id и поля формы секрет, group_id, form_id, lead_id Normalize lead чистит телефон, имя, UTM +7, 8, пробелы, lowercase email Find row in Sheets ищет строку по lead_id/phone колонки lead_id и phone_normalized Update or append row обновляет или добавляет заявку статус, updated_at, update_count Notify manager отправляет уведомление при новом лиде без дублей и без персональных данных в публичный чат Error route пишет ошибку в DLQ/alert 429, Google API, неверные поля формы Для новых версий Google Sheets node можно использовать встроенную операцию Append or Update. Ручная схема Find → IF → Update/Append полезна, когда нужно вести `update_count`, разные правила для новых и повторных лидов или отдельный alert только для новых заявок. Контракт входных данных VK lead event ¶ { "lead_id": "vk-lead-77821", "group_id": "club123456", "form_id": "consultation-main", "created_at": "2026-05-30T10:00:00+03:00", "name": "Олег", "phone": "8 (916) 555-44-33", "email": "oleg@example.ru", "utm_source": "vk", "utm_medium": "cpc", "utm_campaign": "n8n_leads", "utm_content": "leadform_banner", "ad_id": "ad-987", "campaign_id": "camp-321" } Если VK отдаёт только `lead_id`, а полные поля нужно забирать отдельным API-запросом, оставьте этот же контракт внутри n8n после enrichment-ноды. Для Google Sheets важно, чтобы на выходе был стабильный `lead_id` и `phone_normalized`. Code Node: нормализация телефона, UTM и ключа строки ¶ const src = $json.body ?? $json; const leadId = String(src.lead_id ?? src.id ?? '').trim(); if (!leadId) throw new Error('Missing VK lead_id'); const rawPhone = String(src.phone ?? src.Phone ?? '').trim(); let digits = rawPhone.replace(/\D/g, ''); if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`; if (digits.length === 10) digits = `7${digits}`; if (!/^7\d{10}$/.test(digits)) throw new Error(`Invalid VK lead phone: ${rawPhone}`); const email = String(src.email ?? '').trim().toLowerCase(); const now = new Date().toISOString(); return [{ json: { row_key: `vk:${leadId}`, dedupe_phone_key: `phone:+${digits}`, lead_id: leadId, phone_raw: rawPhone, phone_normalized: `+${digits}`, name: String(src.name ?? src.first_name ?? 'Новый лид VK').trim(), email, group_id: String(src.group_id ?? ''), form_id: String(src.form_id ?? ''), campaign_id: String(src.campaign_id ?? ''), ad_id: String(src.ad_id ?? ''), utm_source: src.utm_source ?? 'vk', utm_medium: src.utm_medium ?? '', utm_campaign: src.utm_campaign ?? '', utm_content: src.utm_content ?? '', first_seen_at: src.created_at ?? now, updated_at: now, status: 'new' } }]; Какие колонки создать в Google Sheets Минимум: lead_id, row_key, phone_normalized, name, email, group_id, form_id, campaign_id, ad_id, utm_source, utm_medium, utm_campaign, utm_content, status, first_seen_at, updated_at, update_count. Готовый workflow JSON: скачать и импортировать ¶ Скачать готовый workflow JSON Скачать тестовый payload { "name": "Nodbot - VK Lead Forms to Google Sheets with UTM dedupe", "nodes": [ { "name": "VK Lead Webhook", "type": "n8n-nodes-base.webhook", "purpose": "Принять lead_id и поля формы" }, { "name": "Normalize VK lead", "type": "n8n-nodes-base.code", "purpose": "Нормализовать телефон, UTM и row_key" }, { "name": "Find row in Google Sheets", "type": "n8n-nodes-base.httpRequest", "purpose": "Найти строку по lead_id или phone_normalized" }, { "name": "Update or append row", "type": "n8n-nodes-base.httpRequest", "purpose": "Обновить существующую строку или добавить новую" }, { "name": "Notify manager", "type": "n8n-nodes-base.telegram", "purpose": "Сообщить о новой заявке без дублей" }, { "name": "Respond", "type": "n8n-nodes-base.respondToWebhook", "purpose": "Вернуть VK безопасный 200" } ], "connections": "VK Lead Webhook → Normalize VK lead → Find row in Google Sheets → Update or append row → Notify manager → Respond" } Пошаговая настройка VK webhook, n8n и Google Sheets ¶ Создайте лист Google Sheets с колонками lead_id, phone_normalized, UTM и status. Настройте VK Lead Forms webhook или API-забор lead_id в n8n. Импортируйте workflow и замените Google credential, spreadsheetId и sheet name. Выберите правило upsert: lead_id как основной ключ, телефон как дополнительная проверка дублей. Добавьте alert/DLQ для ошибок Google API и отсутствующих обязательных полей. Тесты перед production и проверка дублей ¶ curl -X POST "https://YOUR-N8N-DOMAIN/webhook/vk-lead-form-to-sheets" \ -H "Content-Type: application/json" \ --data @vk-lead-form-to-sheets-payload.json Отправьте один и тот же lead_id дважды: строка должна обновиться, а не добавиться. Отправьте тот же телефон с другим форматом `8 916...` и проверьте нормализацию. Проверьте заявку без email и с кириллицей в UTM. Удалите колонку в тестовом листе и убедитесь, что ошибка попадает в alert. Проверьте, что новый лид отправляет уведомление менеджеру только один раз. Production-риски VK Lead Ads и Google Sheets ¶ Append вместо upsert. Таблица быстро заполняется дублями и теряет управляемость. UTM лежат в комментарии. Маркетинг не сможет фильтровать заявки по кампании и объявлению. Поиск только по телефону. Один клиент с несколькими заявками может перезаписать нужные данные без lead_id. Секрет webhook не проверяется. В таблицу можно отправить мусорные заявки. Нет DLQ. Ошибка Google API теряет лид без следа. Полезные ссылки и смежные workflow ¶ См. также Google Sheets upsert по телефону , Tilda → amoCRM , retry/DLQ для HTTP Request и Google Sheets integrations . Официальные документы: VK Ads leads API , n8n Google Sheets node и Google Sheets API . Визуальная карточка показывает lead_id, нормализованный телефон, кампанию и действие со строкой. Критерии готовности ¶ Повторный lead_id не создаёт вторую строку. Телефон нормализуется для +7, 8, пробелов и скобок. UTM, form_id, campaign_id и ad_id записываются в отдельные колонки. Ошибки Google API уходят в alert/DLQ. Менеджер получает уведомление только по новым лидам. Нужно выгружать VK Lead Forms без дублей и ручной чистки? Nodbot настроит VK Lead Forms → n8n → Google Sheets: upsert, UTM, уведомления менеджерам, DLQ и проверку качества лидов. Настроить VK leads workflow

## Test payload

```json
{
  "lead_id": "vk-lead-77821",
  "group_id": "club123456",
  "form_id": "consultation-main",
  "created_at": "2026-05-30T10:00:00+03:00",
  "name": "Олег",
  "phone": "8 (916) 555-44-33",
  "email": "oleg@example.ru",
  "utm_source": "vk",
  "utm_medium": "cpc",
  "utm_campaign": "n8n_leads",
  "utm_content": "leadform_banner",
  "ad_id": "ad-987",
  "campaign_id": "camp-321"
}
```

## Key implementation snippet

```javascript
const src = $json.body ?? $json;
const leadId = String(src.lead_id ?? src.id ?? '').trim();
if (!leadId) throw new Error('Missing VK lead_id');

const rawPhone = String(src.phone ?? src.Phone ?? '').trim();
let digits = rawPhone.replace(/\D/g, '');
if (digits.length === 11 && digits.startsWith('8')) digits = `7${digits.slice(1)}`;
if (digits.length === 10) digits = `7${digits}`;
if (!/^7\d{10}$/.test(digits)) throw new Error(`Invalid VK lead phone: ${rawPhone}`);

const email = String(src.email ?? '').trim().toLowerCase();
const now = new Date().toISOString();

return [{
  json: {
    row_key: `vk:${leadId}`,
    dedupe_phone_key: `phone:+${digits}`,
    lead_id: leadId,
    phone_raw: rawPhone,
    phone_normalized: `+${digits}`,
    name: String(src.name ?? src.first_name ?? 'Новый лид VK').trim(),
    email,
    group_id: String(src.group_id ?? ''),
    form_id: String(src.form_id ?? ''),
    campaign_id: String(src.campaign_id ?? ''),
    ad_id: String(src.ad_id ?? ''),
    utm_source: src.utm_source ?? 'vk',
    utm_medium: src.utm_medium ?? '',
    utm_campaign: src.utm_campaign ?? '',
    utm_content: src.utm_content ?? '',
    first_seen_at: src.created_at ?? now,
    updated_at: now,
    status: 'new'
  }
}];
```

## Importable workflow structure

```json
{
  "name": "Nodbot - VK Lead Forms to Google Sheets with UTM dedupe",
  "nodes": [
    {
      "name": "VK Lead Webhook",
      "type": "n8n-nodes-base.webhook",
      "purpose": "Принять lead_id и поля формы"
    },
    {
      "name": "Normalize VK lead",
      "type": "n8n-nodes-base.code",
      "purpose": "Нормализовать телефон, UTM и row_key"
    },
    {
      "name": "Find row in Google Sheets",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Найти строку по lead_id или phone_normalized"
    },
    {
      "name": "Update or append row",
      "type": "n8n-nodes-base.httpRequest",
      "purpose": "Обновить существующую строку или добавить новую"
    },
    {
      "name": "Notify manager",
      "type": "n8n-nodes-base.telegram",
      "purpose": "Сообщить о новой заявке без дублей"
    },
    {
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "purpose": "Вернуть VK безопасный 200"
    }
  ],
  "connections": "VK Lead Webhook → Normalize VK lead → Find row in Google Sheets → Update or append row → Notify manager → Respond"
}
```

## Retrieval hints

- Использовать HTML как canonical source.
- Markdown удобен для LLM-ответов, извлечения workflow-контракта, кода и чеклистов.
- Для ссылок пользователю отдавать canonical URL.
