Инструкция: Согласие на обработку персональных данных (РФ)

Trigger: лендинг рассчитан на аудиторию РФ и содержит форму, собирающую любые данные физлица (имя, email, телефон, Telegram, сообщение). Также — если на странице стоит счётчик (Яндекс.Метрика, GA) или другие cookies аналитики.

Uses: instructions/landing_lead_form, instructions/landing_checklist, instructions/create_landing_page

Зачем

152-ФЗ «О персональных данных» требует от оператора получить согласие до начала обработки. Для веб-формы практика — два обязательных артефакта:

  1. Чекбокс согласия рядом с кнопкой отправки (обязательный, не предустановленный)
  2. Отдельная страница с полным текстом согласия, ссылка на неё — из чекбокса

Без них форма работает «вне закона»: жалоба в Роскомнадзор → штраф оператору. Это не «бумажка для галочки» — это минимум, который защищает и пользователя, и владельца сайта.

Архитектура в школе

  • Одна общая страница на vault: legal/personal_data_consent.md → доступна по URL /legal/personal_data_consent
  • Все лид-формы лендингов ссылаются на неё
  • Реквизиты оператора (ФИО, статус, контакты для отзыва) — заполняются один раз и едины для всех лендингов
  • Если для конкретного лендинга оператор/состав данных отличается — делается отдельная страница legal/<slug>_consent.md и форма ссылается на неё

Шаги

Шаг 1 — Проверить что страница согласия уже есть

ls legal/personal_data_consent.md 2>/dev/null && echo "есть" || echo "надо создать"

Если есть — переходи к шагу 3.

Шаг 2 — Создать общую страницу согласия

Спроси у пользователя реквизиты оператора (один раз на vault):

  • ФИО полностью (как в паспорте) — кому даётся согласие
  • Юридический статус — самозанятый / ИП / физлицо (если ИП — попроси ИНН и ОГРНИП; если самозанятый — попроси ИНН)
  • Email для отзыва согласия — куда писать «удалите мои данные»
  • Telegram / телефон для отзыва — опционально, второй канал

Создай legal/personal_data_consent.md по шаблону ниже, подставив реквизиты.

Шаблон страницы

# Согласие на обработку персональных данных

Нажимая кнопку отправки заявки на этом сайте, я даю согласие {ФИО оператора}{, ИНН {ИНН}, если есть} на обработку персональных данных, которые я указываю в форме обратной связи.

## Какие данные могут обрабатываться

- имя;
- email;
- телефон;
- Telegram;
- текст сообщения и любые сведения, которые я сам(а) указываю в заявке.

## Цель обработки

Данные используются только для того, чтобы связаться со мной, уточнить запрос, ответить на заявку и предложить следующий шаг.

## Что можно делать с данными

Я согласен(на) на сбор, запись, систематизацию, хранение, уточнение, использование и удаление указанных данных в пределах цели, описанной выше.

## Передача третьим лицам

Данные не публикуются и не передаются третьим лицам без необходимости для ответа на заявку, исполнения договорённостей или требований закона.

## Cookies и аналитика

Сайт может использовать cookie-файлы и счётчики веб-аналитики (например, Яндекс.Метрика) для статистики посещений и улучшения работы сайта. Эти данные обрабатываются обезличенно. Управлять cookies можно через настройки браузера или плашку согласия на сайте.

## Срок действия согласия

Согласие действует до достижения цели обработки или до его отзыва.

## Отзыв согласия

Я могу отозвать согласие, написав на email: {email оператора}{ или в Telegram: {@username}, если есть}.

После получения отзыва данные будут удалены, если их дальнейшее хранение не требуется по закону или для подтверждения уже состоявшегося обращения.

Что нельзя:

  • Оставлять плейсхолдеры {...} в опубликованной версии — без реквизитов согласие юридически пустое
  • Писать «согласие действует бессрочно» — должно быть «до отзыва»
  • Прятать ссылку отзыва — она должна быть рабочая

Шаг 3 — Добавить чекбокс в форму лендинга

В frontmatter заметки лендинга добавь поле consent:

form:
  can_submit: guest
  success_url: /thanks
  fields:
    - name: name
      type: text
      required: true
    - name: email
      type: email
      required: true
    # ... другие поля
    - name: consent
      type: bool
      required: true
      enum: [true]   # принимать только true — нельзя снять галку

enum: [true] гарантирует, что submit без галки будет отклонён сервером — даже если фронт обойдут.

Шаг 4 — Отрендерить чекбокс рядом с кнопкой

В layout формы (адаптированный example.html из instructions/landing_lead_form) — для поля consent рендерим не дефолтный чекбокс, а специальный с ссылкой:

<label class="lead-consent">
  <input type="checkbox" name="consent" value="true" required>
  <span>Я согласен(на) на <a href="/legal/personal_data_consent" target="_blank" rel="noopener">обработку персональных данных</a></span>
</label>

JS-обвязка (если форма строится из form-spec динамически):

if (field.type === 'bool' && field.name === 'consent') {
  const wrap = document.createElement('label');
  wrap.className = 'lead-consent';
  const input = document.createElement('input');
  input.name = field.name;
  input.type = 'checkbox';
  input.required = !!field.required;
  input.value = 'true';
  const cap = document.createElement('span');
  cap.innerHTML = 'Я согласен(на) на <a href="/legal/personal_data_consent" target="_blank" rel="noopener">обработку персональных данных</a>';
  wrap.append(input, cap);
  // ... в форму
}

Правила размещения:

  • Чекбокс — сразу над кнопкой submit, не в подвале страницы
  • Галка не предустановлена (checked не ставить) — пользователь должен сам её поставить
  • Кнопка submit может быть disabled пока галка снята (UX), но серверная валидация (enum: [true]) обязательна
  • Ссылка открывается в новой вкладке (target="_blank") — чтобы не потерять заполненную форму

Минимальная плашка (показывается один раз, выбор сохраняется в localStorage):

<div id="cookie-banner" hidden style="position:fixed;bottom:16px;left:16px;right:16px;max-width:640px;margin:0 auto;padding:14px 18px;background:#1c1a16;color:#f5f1e8;border-radius:14px;font-size:13px;line-height:1.5;display:flex;gap:12px;align-items:center;z-index:1000">
  <span>Сайт использует cookies для статистики. Подробнее — в <a href="/legal/personal_data_consent" style="color:#c8ff5a">согласии на обработку данных</a>.</span>
  <button id="cookie-ok" style="padding:8px 14px;background:#c8ff5a;color:#1c1a16;border:0;border-radius:8px;font-weight:600;cursor:pointer">Ок</button>
</div>
<script>
  (function(){
    if (localStorage.getItem('cookie-consent') === 'ok') return;
    var b = document.getElementById('cookie-banner');
    b.hidden = false;
    document.getElementById('cookie-ok').onclick = function(){
      localStorage.setItem('cookie-consent', 'ok');
      b.hidden = true;
    };
  })();
</script>

Когда плашка обязательна: счётчик Метрики/GA, пиксели рекламных сетей, любые трекеры через cookies.
Когда не нужна: статичная страница без аналитики и форм с подпиской на cookies.

Шаг 6 — Проверить по чеклисту

Сверь с instructions/landing_checklist — раздел про согласие:

  • Чекбокс есть, обязательный, не предустановлен
  • Ссылка из чекбокса ведёт на рабочий /legal/personal_data_consent
  • На странице согласия заполнены реальные реквизиты оператора (нет {...})
  • Указан рабочий канал отзыва (email/Telegram отвечает)
  • Если на странице метрика — плашка cookies показывается
  • Серверная валидация enum: [true] отклоняет submit без галки

Проверка результата

  1. Открой лендинг в браузере, попробуй отправить форму без галки — должна быть ошибка
  2. Поставь галку, нажми ссылку → откроется страница согласия в новой вкладке, форма не теряется
  3. На странице согласия нет плейсхолдеров {ФИО}, {email} и т.п.
  4. Напиши на email отзыва тестовое сообщение — оно должно дойти

Когда остановиться

  • Страница /legal/personal_data_consent опубликована, открывается, реквизиты реальные
  • Все формы на vault, собирающие персданные, имеют поле consent с required: true, enum: [true]
  • Если есть метрика — плашка cookies работает

Типичные ошибки

  • Галка по умолчанию стоит — нарушает требование «активного согласия». Снять.
  • Ссылка ведёт на 404 — забыли создать страницу или поменяли путь. Чинить.
  • Реквизиты «Иванов Иван Иванович» или пустые {ФИО} — согласие юридически ничтожно. Заменить на реальные.
  • Согласие в подвале мелким шрифтом без чекбокса — не работает, нужен явный клик пользователя.
  • Нет серверной валидации — фронт можно обойти. enum: [true] обязательно.
  • Метрика стоит, плашки нет — отдельное нарушение по cookies. Добавить плашку.
  • На каждом лендинге своя копия согласия — рассинхронизация реквизитов. Использовать одну общую страницу.

Кейсы

Кейс 1: новый лендинг, согласие на vault уже есть
→ Шаг 1 показал «есть» → сразу шаг 3 (чекбокс в форму) → шаг 4 (рендер) → шаг 6 (чеклист).

Кейс 2: первый лендинг на vault
→ Шаг 2: спросить реквизиты → создать страницу → дальше как в кейсе 1.

Кейс 3: на лендинге стоит Яндекс.Метрика
→ + Шаг 5 (плашка cookies) + проверка что в шаблоне согласия включён раздел «Cookies и аналитика».

Кейс 4: оператор для этого лендинга — другое юрлицо
→ Сделать legal/<slug>_consent.md по тому же шаблону, в форме ссылка на него. Общую страницу не трогать.

Связано: instructions/landing_lead_form, instructions/landing_checklist, instructions/create_landing_page, behaviors/risky_actions

Источник: sources/_index (пример реализации — https://olgakuznetsova.pro/ и /legal/personal_data_consent)