Подготавливаем страницу…
Подготавливаем страницу…
Два способа: готовый код из кабинета — без своего сервера, или Tilda Webhook с PHP-файлом на своём хостинге. Ниже оба, плюс особенности Тильды, на которых ломается наивное подключение.
*.tilda.ws для предпросмотра — прописаны автоматически. Ключ публикуемый (pk_), его видимость в исходниках — не утечка. Минус: при отключённом JavaScript у посетителя согласие не запишется, хотя форму Тильда отправит.proxy.php при каждой отправке формы, файл пересылает согласие в 1ОПД серверным ключом sk_. Не зависит от браузера посетителя, ведёт свой журнал opd-debug.log. Нужен любой хостинг с PHP — подойдёт самый простой. Требуется тариф Тильды с вебхуками (Business).submit нет. Форму отправляет обработчик Тильды. Перехват через addEventListener('submit') молчит: заявки идут, согласий нет, ошибок нет. Код из кабинета ловит успешную отправку по сетевому запросу Тильды и блоку «Спасибо».Content-Type: text/plain, ключ в теле, ни одного своего заголовка: свой заголовок вызвал бы preflight-запрос OPTIONS, и при малейшем расхождении CORS браузер молча отменил бы отправку.Email, Name, Phone; в форме согласия — email, first_name, phone_number. Сопоставление обязано быть полным: одно несопоставленное имя отбивает весь запрос с 400. Служебные поля Тильды (tildaspec…) отправлять не нужно.Checkbox и Checkbox_2 — Тильда нумерует их сама. Отмеченный чекбокс передаётся значением yes.Кабинет → «Интеграция» → карточка сайта. Код выдаётся уже с вашим ключом, формами и полями — копируйте целиком, править в нём ничего не нужно. Ключ виден в кабинете всегда, потерять его нельзя.
На одной странице: Настройки страницы → «Дополнительно» → «HTML-код для вставки внутрь HEAD». На всех: Настройки сайта → «Вставка кода» → HEAD. Затем — «Опубликовать все страницы»: без публикации код на сайт не попадёт. Поля «в BODY» у Тильды нет, и оно не нужно.
Отправьте форму с тестовой почтой и найдите запись: кабинет → «Согласия». Консоль браузера (F12) показывает и успех, и причину отказа; тишина в консоли означает, что код не подключился — проверьте вставку и публикацию.
Схема: посетитель отправляет форму → Тильда вызывает ваш proxy.php со всеми полями → файл смотрит, какие чекбоксы согласия отмечены, и шлёт в 1ОПД по запросу за каждый отмеченный. Все чекбоксы обслуживает один ключ с областью на нужные формы.
Кабинет → «Интеграция» → карточка сайта. Тип ключа — серверный sk_: он будет лежать в PHP-файле на вашем сервере и посетителю не виден. Область ключа — все формы согласия сайта. Там же запишите form_id каждой формы: например, 1 — обработка данных, 2 — рассылка.
Создайте папку opd/ в корне сайта, сохраните туда файл с кодом ниже, отредактировав четыре блока настроек. Права файла — 644, папки — 755. Открытый в браузере файл отвечает {"ok":true,"sent":0} — без данных пересылать нечего, это норма.
<?php
// proxy.php — приёмник Tilda Webhook: пересылает согласия в 1ОПД.
// Положите файл на свой хостинг (PHP 7.4+) и укажите его адрес
// в Тильде: Настройки сайта → Формы → Webhook.
//
// Один файл обслуживает все чекбоксы согласия формы через один ключ:
// у ключа в 1ОПД должна быть область на все нужные формы (задаётся
// при выпуске ключа в кабинете).
// ── Настройки: четыре блока ─────────────────────────────────────────
// 1. Ключ 1ОПД (sk_, выпускается в кабинете).
$api_key = 'sk_ваш_ключ';
// 2. Адрес приёма.
$endpoint = 'https://v2.1opd.ru/api/v2/create-agreement';
// 3. Какой чекбокс Тильды в какую форму 1ОПД пишет.
// Слева — name чекбокса в форме Тильды, справа — form_id из кабинета.
// Один чекбокс — оставьте одну строку.
$consent_form_ids = [
'Checkbox' => 1, // «Согласен на обработку персональных данных»
'Checkbox_2' => 2, // «Согласен на рассылку» (если есть)
];
// 4. Имена полей Тильды → имена полей формы в 1ОПД.
$field_mapping = [
'Name' => 'first_name',
'Email' => 'email',
'Phone' => 'phone_number',
];
// Поле Тильды, по которому 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} — субъект не идентифицируется.");
http_response_code(200);
exit;
}
$sent = 0;
foreach ($consent_form_ids as $checkbox => $form_id) {
// Согласие уходит только за отмеченный чекбокс — и мы прямо говорим
// платформе, что отметка проверена: consent_given = true.
if (($tilda_data[$checkbox] ?? '') !== 'yes') {
opd_log("SKIP form_id={$form_id} ({$checkbox}): чекбокс не отмечен.");
continue;
}
$payload = [
'form_id' => $form_id,
'hash_field' => $hash_value,
'consent_given' => true,
'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';
foreach ($http_response_header ?? [] as $h) {
if (strpos($h, 'HTTP/') === 0) { $code = $h; break; }
}
opd_log("SEND form_id={$form_id} ({$checkbox}) -> {$code} | {$response}");
$sent++;
}
opd_log("DONE: отправлено {$sent} согласий для {$hash_field}={$hash_value}.");
http_response_code(200);
echo json_encode(['ok' => true, 'sent' => $sent]);
Настройки сайта → «Формы» → «Webhook», в поле URL — полный адрес файла: https://ваш-домен/opd/proxy.php. Затем в блоке каждой формы с согласием: «Контент» → «Сервисы приёма данных» → галочка на Webhook. Опубликуйте сайт.
Отправьте форму с тестовой почтой, отметив чекбоксы, и откройте opd/opd-debug.log на сервере:
2026-09-09 13:42:01 SEND form_id=1 (Checkbox) -> HTTP/1.1 200 OK | {"hash":"..."}
2026-09-09 13:42:01 SEND form_id=2 (Checkbox_2) -> HTTP/1.1 200 OK | {"hash":"..."}
2026-09-09 13:42:01 DONE: отправлено 2 согласий для Email=test@example.ru.И 200, и 202 — приём. Затем — кабинет → «Согласия»: записей появится столько, сколько чекбоксов было отмечено. Пока записи в реестре нет, интеграция не считается работающей.
form_id (ч. 1 ст. 15 152-ФЗ, ч. 1 ст. 18 закона «О рекламе»).Политика — в двух местах. В подвале сайта на всех страницах (ч. 2 ст. 18.1 152-ФЗ — неограниченный доступ к политике) и рядом с каждым чекбоксом. Одно другое не заменяет. Оба готовых блока со вставленными ссылками лежат в кабинете, в карточке сайта.
Самый коварный случай. Тильда отправляет форму своим обработчиком и нативного события submit не порождает — код, подписанный на submit, не сработает ни разу, и ошибки не будет. Код из кабинета поэтому ловит не submit, а факт успешной отправки: сетевой запрос Тильды к её форм-процессору и появление блока «Спасибо». Если вы писали перехват сами — переделайте на этот принцип или возьмите код из кабинета.
Тильда впекает код из настроек в страницу в момент публикации. Пока не нажата «Опубликовать все страницы», на сайте живёт прежняя версия — даже если поле в настройках вы уже очистили. И наоборот: опубликованная страница может нести код, которого в настройках уже нет. Проверяйте исходник опубликованной страницы, а не поле в настройках.
Проверьте по порядку: в Настройках сайта → Формы есть добавленный Webhook; в блоке формы → «Контент» → «Сервисы приёма данных» стоит галочка на нём; сайт опубликован после изменений. В предпросмотре внутри tilda.cc вебхуки не вызываются — только на опубликованном сайте.
Ключ скопирован не целиком, отозван (выпуск нового отзывает прежний) или принадлежит другому юрлицу. В кабинете действующий ключ помечен «действует», отозванный — «прежний».
403 — form_id не входит в область ключа: сверьте числа в $consent_form_ids с номерами форм в кабинете; область задаётся при выпуске ключа, под новую форму выпустите ключ заново. 400 с «Unknown field» — в $field_mapping есть имя, которого нет в форме согласия.
Имена чекбоксов в Тильде разошлись с именами в PHP-файле. Откройте опубликованный сайт → правый клик на чекбоксе → «Посмотреть код» → атрибут name. Имя обязано совпадать с ключом массива буква в букву, включая регистр. Значение отмеченного чекбокса у Тильды — yes; если меняли, поправьте сравнение.
Это успех: согласие принято в очередь и запишется само, запись появится в реестре в течение минут. Повторять отправку «ради 200» нельзя — получится вторая версия согласия.