Подготавливаем страницу…
Подготавливаем страницу…
Готовый PHP-файл-прокси, один API-ключ обслуживает все чекбоксы согласия в форме (обработка ПДн + маркетинг). Это тот же production-паттерн, что используем мы сами на 1opd.ru и наши клиенты. Время — ~30 минут.
Tilda не умеет напрямую отправлять данные в произвольный API — но она умеет звать Webhook (ваш URL). Поэтому схема получается из четырёх шагов:
Пользователь → Tilda-форма → Tilda Webhook → ВАШ proxy.php → 1ОПД (галочка (forms_scope[] (POST согласия) в форме) /api/v2/ create- agreement)
Один proxy.php на вашем сервере смотрит — какие чекбоксы в форме пользователь поставил, и шлёт в 1ОПД столько POST-запросов, сколько чекбоксов активно (обычно: один на «согласие на обработку ПДн» и опционально второй на «маркетинг»). Один API-ключ 1ОПД обслуживает все чекбоксы сайта — это называется multi-form ключ (см. Шаг 02).
sk_ (secret — только server-side) forms_scope=[id1, id2, …] — и в каждом запросе передаёте form_id в body.Ключ создаёт менеджер 1ОПД и передаёт вам один раз. Все endpoints → API Reference
Прочитайте один раз — дальше в инструкции эти слова уже не будут пугать.
Здесь живут ваши формы согласия и их form_id.
Зайдите на lk.v2.1opd.ru под аккаунтом, который вам выдал менеджер 1ОПД.
Один ключ — все чекбоксы сайта. Полный ключ показывается ОДИН раз при создании.
API-ключ создаёт менеджер 1ОПД. Важно попросить именно multi-form ключ — он умеет писать сразу в несколько форм согласия (например в «обработка ПДн» и «маркетинг» одновременно). Если у ключа forms_scope=[1, 2] — он работает с формами 1 и 2, на одну форму ключ выпускать не нужно.
[1, 2] IP вашего хостинга (опц) sk_) для сайта mydomain.ru, с forms_scope на все мои формы согласия (обработка ПДн + маркетинг)».sk_. Сохраните её сразу — повторно мы её показать не сможем (в БД хранится только хэш).form_id, которые ключ обслуживает (например: 1 — «Согласие на обработку ПДн», 2 — «Маркетинговые коммуникации»). Они вам понадобятся в Шаге 04.forms_scope=[1]. Файл PHP в Шаге 04 настраивается аналогично.sk_abc12…, а не полный ключ. Это нормально — секрет хранится у вас в proxy.php. Если потеряли — менеджер выпустит новый и отзовёт старый. sk_abc1234567... и список form_id (например: 1 = обработка, 2 = маркетинг).В ЛК → раздел «Интеграция» → Формы → form_id.
В ЛК 1ОПД перейдите в раздел Интеграция → слева сбоку нажмите на раздел «Интеграция» → найдите список Форм → в отношении каждой из форм в названии указан соответствующий ей form_id=N. Это и есть номер формы, который вы передаёте в form_id в body POST-запроса.
form_id соответствует какой цели обработки. Например: 1 = основное согласие на обработку ПДн, 2 = маркетинг.sk_… и таблица «чекбокс → form_id». Можно собирать proxy.php.Один файл — приёмник Tilda Webhook. Отредактируйте только переменные сверху.
Скопируйте код ниже целиком, отредактируйте 4 блока «НАСТРОЙКИ» (API-ключ, чекбоксы→form_id, маппинг полей, hash-поле) и загрузите файл на ваш веб-сервер по адресу типа https://mydomain.ru/opd/proxy.php.
opd/ в корне сайта. Положите туда файл proxy.php с кодом ниже.opd/ — 755. <?php
// proxy.php — приёмник Tilda Webhook для отправки согласий в 1ОПД (152-ФЗ).
// Положите этот файл на ваш веб-сервер (PHP 7.4+) и пропишите URL
// в Tilda → Настройки сайта → Формы → Сервис «Webhook».
//
// ОДИН файл обслуживает ВСЕ чекбоксы согласия в форме Tilda через ОДИН
// API-ключ. Главное — чтобы у ключа в 1ОПД в forms_scope были все нужные
// form_id (это делает менеджер 1ОПД при создании ключа).
// ── НАСТРОЙКИ — отредактируйте эти 4 блока ───────────────────────────────
// 1. API-ключ 1ОПД. Получите у менеджера ОДИН раз — в ЛК виден только префикс.
$api_key = 'pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// 2. Endpoint 1ОПД (можно оставить как есть).
$endpoint = 'https://app.1opd.ru/api/v2/create-agreement';
// 3. Какой чекбокс Tilda какой form_id 1ОПД соответствует.
// Имена слева ('Checkbox', 'Checkbox_2') — это поле name=... у чекбокса
// в форме Tilda (см. Шаг 06). Числа справа — form_id из ЛК 1ОПД (см.
// Шаг 03). Если у вас один чекбокс — оставьте только первую строку.
$consent_form_ids = [
'Checkbox' => 1, // основной чекбокс «Согласен с обработкой ПДн»
'Checkbox_2' => 2, // дополнительный «Маркетинговая рассылка» (опц)
];
// 4. Маппинг полей Tilda → имена в 1ОПД (как заведены в «Реестре процессов»).
$field_mapping = [
'Name' => 'first_name',
'Email' => 'email',
'Phone' => 'phone_number',
// 'Company' => 'company_name', // раскомментируйте при необходимости
];
// Какое поле Tilda — главный идентификатор субъекта (для дедупа в 1ОПД).
$hash_field = 'Email';
// ── ЛОГИКА (обычно править не нужно) ─────────────────────────────────────
$tilda_data = $_POST;
if (empty($tilda_data)) {
$tilda_data = json_decode(file_get_contents('php://input'), true) ?? [];
}
$log_file = __DIR__ . '/opd-debug.log';
function opd_log(string $line): void {
global $log_file;
file_put_contents($log_file, date('Y-m-d H:i:s') . ' ' . $line . "\n", FILE_APPEND);
}
$formatted_fields = [];
foreach ($tilda_data as $key => $value) {
if (!isset($field_mapping[$key])) continue;
if (is_array($value)) $value = implode(', ', $value);
$formatted_fields[] = ['field' => $field_mapping[$key], 'value' => (string)$value];
}
$hash_value = (string)($tilda_data[$hash_field] ?? '');
if ($hash_value === '') {
opd_log("SKIP: пустой hash_field ({$hash_field}) — субъект не идентифицируется.");
http_response_code(200);
exit;
}
$sent_count = 0;
foreach ($consent_form_ids as $checkbox_name => $form_id) {
if (($tilda_data[$checkbox_name] ?? '') !== 'yes') {
opd_log("SKIP form_id={$form_id} ({$checkbox_name}): чекбокс не активен.");
continue;
}
$payload = [
'form_id' => $form_id,
'hash_field' => $hash_value,
'fields' => $formatted_fields,
];
$ctx = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nAPI-KEY: {$api_key}\r\n",
'content' => json_encode($payload, JSON_UNESCAPED_UNICODE),
'ignore_errors' => true,
'timeout' => 10,
],
]);
$response = @file_get_contents($endpoint, false, $ctx);
$code = 'no-response';
if (isset($http_response_header)) {
foreach ($http_response_header as $h) {
if (strpos($h, 'HTTP/') === 0) { $code = $h; break; }
}
}
opd_log("SEND form_id={$form_id} ({$checkbox_name}) -> {$code} | response: {$response}");
$sent_count++;
}
opd_log("DONE: отправлено {$sent_count} согласий для {$hash_field}={$hash_value}.");
http_response_code(200);
echo json_encode(['ok' => true, 'sent' => $sent_count]);
$consent_form_ids только первую строку и попросите у менеджера ключ с forms_scope=[1]. Остальное в файле менять не нужно.proxy.php доступен по URL https://mydomain.ru/opd/proxy.php. Если открыть в браузере — должен вернуть JSON {"ok":true,"sent":0} (потому что без данных ничего не пересылается).Tilda → Настройки сайта → Формы → «Добавить сервис» → «Webhook».
Tilda → откройте ваш сайт → «Настройки сайта» (вверху справа) → «Формы» → блок «Подключение к сервисам приёма данных» → нажмите «Webhook».
proxy.php (полный URL с https://).Один обязательный чекбокс «Согласие на обработку ПДн» + опциональный «Маркетинг».
В Tilda откройте блок с формой → «Контент» → раздел «Поля». Добавьте поле типа «Checkbox». Имя автоматически станет Checkbox. В текст поля впишите формулировку согласия — она должна точно совпадать с тем, что записано в PDF-документе у вас в 1ОПД.
① Основной чекбокс — согласие на обработку ПДн (обязательный)
Checkbox (имя по умолчанию) «Даю согласие на обработку персональных данных в соответствии с Политикой обработки персональных данных».
Required = Да. Без галочки форма не отправляется — это требование 152-ФЗ.
② Опциональный чекбокс — маркетинговая рассылка (добровольный)
Checkbox_2 (Tilda сама нумерует второй чекбокс) «Даю согласие на получение информационной и рекламной рассылки».
Required = Нет. Пользователь сам решает, подписываться ли на маркетинг.
proxy.php должны совпадать буква в букву (включая регистр). Если в Tilda назвали поле СогласиеПДн — в PHP тоже должно быть СогласиеПДн в массиве $consent_form_ids.Checkbox, Checkbox_2 (или ваши, но тогда поправьте PHP).required, маркетинговый — нет.Заполните форму с тестовым email. Проверьте debug.log и ЛК 1ОПД.
Откройте опубликованную страницу с формой. Заполните Name / Email / Phone, поставьте обе галочки и нажмите «Отправить».
opd/opd-debug.log. Там должны быть строки:2026-05-21 13:42:01 SEND form_id=1 (Checkbox) -> HTTP/1.1 200 OK | response: {"hash":"..."}
2026-05-21 13:42:01 SEND form_id=2 (Checkbox_2) -> HTTP/1.1 200 OK | response: {"hash":"..."}
2026-05-21 13:42:01 DONE: отправлено 2 согласий для Email=test@example.ru. test@example.ru.debug.log есть строка «SEND form_id=… → 200 OK».Это самый частый вопрос менеджеров: «как одним ключом обслуживать и обработку ПДн, и маркетинг, и обратную связь?». Объясняем.
Один ключ = одна форма согласия. Так, в рамках формы с двумя чекбоксами ранее требовалось два ключа + 2 PHP-файла или сложный JS.
Один ключ с forms_scope=[1, 2, 5] = несколько форм. В каждом POST-запросе указываете form_id явно, и ключ маршрутизирует запись в нужную форму. PHP-файл — один на весь сайт.
Сценарий 1: одно согласие закрывает несколько форм сбора. На сайте есть «Заказать звонок», «Обратная связь» и ещё пара форм — у всех совпадает цель обработки (например, «обработка обращений субъектов»). Привязка идёт к согласию, а не к кнопке. Достаточно одного multi-form ключа со scope=[этого согласия], в каждом запросе проставляется один и тот же form_id.
Сценарий 2: в одной форме два чекбокса под разные согласия. Обработка ПДн и маркетинг — разные цели обработки. Один multi-form ключ с forms_scope=[1, 2] покрывает обе формы; в каждом запросе передаёте свой form_id (1 для обработки, 2 для маркетинга), и backend по scope маршрутизирует запись в нужный реестр.
Зачем тогда «выбранные формы» (per-form scope)? Для изоляции конкретных точек сбора, когда вы НЕ хотите, чтобы один и тот же ключ мог писать сразу в несколько форм. Например, на лендинге партнёрской кампании — отдельный ключ с forms_scope=[5], чтобы при его утечке не пострадали данные основной формы. Передавать form_id в body всё равно обязательно — backend проверит, что он входит в scope ключа, иначе вернёт 409 form_not_in_scope. Это можно увидеть в журнале audit_log ЛК клиента.
form_id.proxy.php добавляете новую строку в $consent_form_ids, например 'Checkbox_3' => 5.Checkbox_3 и нужным текстом.Когда нужен второй ключ: только если речь о разных юр.лицах в одном кабинете 1ОПД. Один ключ = одно юр.лицо. Если у вас холдинг и формы на сайте для разных компаний — обратитесь к менеджеру, он подскажет архитектуру.
Если у вас нет возможности поставить PHP-файл на сервер — есть упрощённый JS-вариант, который перехватывает submit формы и шлёт fetch напрямую в 1ОПД из браузера. Минусы:
pk_-ключ — его видно в исходниках страницы. Защита только через allowed_origins (CORS).debug.log).Этот код вставляется в Tilda → Настройки сайта → «Ещё» → HTML-блок:
<script>
// Запасной вариант — если у вас НЕТ собственного PHP-сервера для прокси.
// Работает только с pk_ ключом + Origin whitelist по вашему домену.
// ВАЖНО: основная production-схема — это PHP-прокси через Tilda Webhook
// (см. Шаги 04–07). JS-снiпет ниже годится для прототипа/демо.
document.addEventListener('submit', function (e) {
if (!e.target.matches('form[name="form12345"]')) return; // имя вашей формы
var fd = new FormData(e.target);
var fields = Array.from(fd.entries())
.filter(function (p) { return ['Name','Email','Phone'].indexOf(p[0]) >= 0; })
.map(function (p) { return { field: p[0].toLowerCase(), value: String(p[1]) }; });
function sendAgreement(formId) {
return fetch('https://app.1opd.ru/api/v2/create-agreement', {
method: 'POST',
headers: {
'API-KEY': 'pk_xxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
form_id: formId,
hash_field: fd.get('Email') || '',
fields: fields
})
});
}
if ((fd.get('Checkbox') || '') === 'yes') sendAgreement(1); // основное согласие
if ((fd.get('Checkbox_2') || '') === 'yes') sendAgreement(2); // маркетинг
});
</script> Перед использованием — попросите менеджера 1ОПД ключ с типом pk_ (publishable) и добавьте в allowed_origins ваш домен + https://*.tilda.ws для предпросмотра.
Самые частые проблемы и что с ними делать. Решает 95% случаев.
Проверьте по порядку:
Проверьте 3 пункта:
proxy.php в $api_key скопирован ПОЛНЫЙ ключ (длина 70+ символов, начинается с sk_).API-KEY: и ключом в HTTP-заголовке нет лишних пробелов или переносов (в нашем шаблоне это уже корректно). Откройте proxy.php → $consent_form_ids → проверьте, что справа стоят те же числа, что у форм в ЛК 1ОПД → раздел «Согласия». Если форма новая — попросите менеджера добавить её form_id в forms_scope существующего ключа.
Откройте опубликованный сайт → правый клик на чекбоксе → «Посмотреть код». В коде найдите атрибут name="…". Это имя — оно должно ТОЧНО совпадать с ключом в массиве $consent_form_ids вашего PHP-файла.
Также проверьте — у Tilda поле «значение чекбокса» по умолчанию yes. Если вы его меняли — поправьте в PHP сравнение (=== 'yes').
В $field_mapping укажите соответствие имён Tilda → имён в 1ОПД (как заведены в «Реестре процессов»). Например: 'Name' => 'first_name', 'Phone' => 'phone_number'.
Опубликуйте сайт через «Опубликовать». Webhook'и работают только на опубликованном (custom) домене, а не в превью *.tilda.cc.
chmod 644 proxy.php и chmod 755 opd/.Откройте ЛК → «Интеграция»: персональные snippet'ы + готовый HTML-чекбокс с авто-ссылками на согласие и политику + кнопка «IP-whitelist» для каждого ключа.
Открыть ЛК →Запросите тестовый доступ — выдаём ключ под ваш домен и помогаем подключиться.
Связаться →Все endpoints, коды ошибок, форматы HMAC/Origin/IP. Таблица «какую защиту выбрать».
Открыть →