Подготавливаем страницу…
Подготавливаем страницу…
Самый простой случай: обычный HTML, статический сайт на Jekyll или Hugo, одностраничник, лендинг. Готовую форму и сниппет достаточно скопировать и вставить.
pk_ (publishable, можно публиковать в браузере) forms_scope=[id1, id2, …] , и в каждом запросе передаёте form_id в body.Ключ создаёт менеджер 1ОПД и передаёт вам один раз. Все endpoints → API Reference
Прочитайте один раз: дальше в инструкции эти слова уже не будут пугать.
Без ключа форма не запишет ни одного согласия.
Зайдите на lk.v2.1opd.ru/lk/integrations → найдите карточку своего сайта → скопируйте ключ pk_.
form_id формы, к которой подключаетесь.sk_, попросите менеджера выпустить publishable: серверный ключ в HTML скомпрометирован сразу, его видно через F12.1ОПД принимает запросы этого ключа только с указанных доменов.
В ЛК 1ОПД → ключ pk_ → раздел Origin-whitelist. Внесите все хосты, с которых открывается сайт.
https://example.com https://www.example.com https://staging.example.com *.example.com разрешает любые поддомены, но не сам example.com. Нужны оба, значит вносите оба явно.*», звёздочку без домена: защита исчезает полностью, и ключ достанется кому угодно. Для публичной формы запросите отдельный ключ с ограничением частоты запросов.Туда вставляют форму и сниппет.
Расположение HTML зависит от хостинга:
index.html или contact.html в корне._includes/ или layouts/. После правки нужен `npm run build` (или `hugo`).git push, через 1-2 минуты появится.Замените 3 места: ключ pk_, form_id, ссылки на документы.
Ниже полная рабочая форма: HTML и JS в одном фрагменте. Замените только выделенные значения.
<!-- Готовая форма + JS-сниппет для статичного HTML-сайта -->
<form id="lead-form"> <input name="email" type="email" required placeholder="Email" /> <input name="name" type="text" required placeholder="Имя" /> <input name="phone" type="tel" placeholder="Телефон" /> <!-- ОСНОВНОЙ чекбокс — согласие на обработку ПДн (ОБЯЗАТЕЛЬНЫЙ). --> <label style="display:flex;gap:8px;align-items:flex-start;font-size:13px"> <input type="checkbox" name="opd_consent" required style="margin-top:3px"> <span> Даю согласие на обработку персональных данных в соответствии с
<a href="https://app.1opd.ru/public/d/<slug>/<client-id>/privacy_policy" target="_blank">Политикой обработки персональных данных</a>.
</span> </label> <!-- ОПЦИОНАЛЬНО: второй чекбокс — маркетинговая рассылка. БЕЗ required. --> <label style="display:flex;gap:8px;align-items:flex-start;font-size:13px;margin-top:8px"> <input type="checkbox" name="opd_consent_marketing" style="margin-top:3px"> <span>Даю согласие на получение информационной и рекламной рассылки.</span> </label> <button type="submit">Отправить</button>
</form> <script>
// Один pk_ ключ обслуживает N форм согласия (multi-form) — для каждой
// поставленной галочки шлём отдельный POST со своим form_id из ЛК 1ОПД.
const OPD_KEY = 'pk_xxxxxxxxxxxxxxxxxxxx'; // ← ваш pk_ ключ
const OPD_API = 'https://app.1opd.ru/api/v2/create-agreement';
const FORM_IDS = {
opd_consent: 1, // основное «Согласие на обработку ПДн»
opd_consent_marketing: 2, // маркетинговая рассылка (опц.)
};
document.getElementById('lead-form').addEventListener('submit', async function (e) {
e.preventDefault();
const fd = new FormData(e.target);
const email = fd.get('email');
// Поля, которые шлём в 1ОПД — без самих чекбоксов (они служебные).
const fields = Array.from(fd.entries())
.filter(function (p) { return p[0] !== 'opd_consent' && p[0] !== 'opd_consent_marketing'; })
.map(function (p) { return { field: p[0], value: String(p[1]) }; });
async function sendConsent(formId) {
try {
const res = await fetch(OPD_API, {
method: 'POST',
headers: { 'API-KEY': OPD_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ form_id: formId, hash_field: email, fields: fields })
});
const data = await res.json();
console.log('1ОПД form_id=' + formId + ' hash:', data.hash);
} catch (err) {
console.warn('1ОПД error (form_id=' + formId + '):', err);
}
}
// На каждую ПОСТАВЛЕННУЮ галочку — свой запрос со своим form_id.
if (fd.get('opd_consent')) await sendConsent(FORM_IDS.opd_consent);
if (fd.get('opd_consent_marketing')) await sendConsent(FORM_IDS.opd_consent_marketing);
// Здесь — ваша основная отправка (Formspree, ваш backend, и т.д.)
// e.target.submit();
});
</script> pk_xxxxxxxx на свой ключ и проверьте, что он скопирован целиком.form_id: 1 на свой номер формы из ЛК.preventDefault(). Если на сайте уже работает AJAX-отправка на собственный бэкенд, раскомментируйте e.target.submit() в конце JS-кода.Вкладка Network в DevTools и раздел «Согласия» в ЛК 1ОПД.
Откройте опубликованную страницу с формой, нажмите F12 и перейдите на вкладку Network. Заполните и отправьте форму с тестовым адресом почты.
POST /api/v2/create-agreement со статусом 200 либо 202.1ОПД hash: ABC123….Самые частые проблемы и что с ними делать. Решает 95% случаев.
В ЛК 1ОПД → ключ pk_ → Origin-whitelist добавьте текущий домен, включая www-вариант, и подтвердите паролем.
Отклонённый Origin обычно указан в самом сообщении Console: копируйте его оттуда.
Уберите e.target.submit() из конца JS-сниппета либо поставьте await перед fetch, чтобы сначала записать согласие, а потом продолжить отправку.
Второй вариант: fetch().then() без await, тогда запрос уйдёт асинхронно ещё до перезагрузки.
Откройте F12 → Console: там будут красные ошибки JavaScript. Частая причина: getElementById не находит форму, потому что её id отличается от id="lead-form".
Сверьте атрибут id формы с тем, что стоит в JS.
Замените подстановки реальными значениями. Готовые URL лежат в ЛК 1ОПД → «Интеграция» → блок «HTML-чекбокс для формы»: скопируйте оттуда полный адрес.
Чтобы после отправки открыть собственную страницу благодарности, уберите e.preventDefault() в JS и оставьте action="/thanks.html" в форме.
Запрос в 1ОПД всё равно уйдёт до редиректа: fetch без await асинхронный.
_includes/footer.html или прямо в _layouts/default.html перед </body>.layouts/partials/footer.html.</body>.Сниппет обязан загружаться после формы: иначе document.getElementById вернёт null.
Откройте ЛК → «Интеграция»: персональные snippet'ы + готовый HTML-чекбокс с авто-ссылками на согласие и политику + кнопка «IP-whitelist» для каждого ключа.
Открыть ЛК →Запросите тестовый доступ: выдаём ключ под ваш домен и помогаем подключиться.
Связаться →Все endpoints, коды ошибок, форматы HMAC/Origin/IP. Таблица «какую защиту выбрать».
Открыть →Успехом считаются и 200, и 202. Проверка «строго 200» отметит ошибкой согласие, которое 1ОПД принял и доставит.
В массиве fields передавайте любые из 28 полей ниже, имя поля стоит в столбце field. Обязательное одно: email, он же идентификатор субъекта (hash_field). Остальные 27 опциональны, незаполненное поле не передавайте. Все значения 1ОПД шифрует на своей стороне (AES-256-GCM). Актуальный список полей конкретной формы отдаёт POST /api/v2/get-fields.
| field | Название | Примечание |
|---|---|---|
email | Электронная почта | обязательное · идентификатор (hash_field) |
first_name | Имя | опциональное |
last_name | Фамилия | опциональное |
sur_name | Отчество | опциональное |
birth_date | Дата рождения | опциональное |
phone_number | Номер телефона | опциональное |
birth_place | Место рождения | опциональное |
registration_address | Адрес регистрации | опциональное |
delivery_address | Адрес доставки | опциональное |
passport_details | Паспортные данные | опциональное |
inn | ИНН | опциональное |
snils | СНИЛС | опциональное |
bank_details | Банковские реквизиты | опциональное |
account_vk | Аккаунт VK | опциональное |
account_telegram | Аккаунт Telegram | опциональное |
account_instagram | Аккаунт Instagram | опциональное |
account_facebook | Аккаунт Facebook | опциональное |
account_viber | Аккаунт Viber | опциональное |
account_ok | Аккаунт OK | опциональное |
account_whatsapp | Аккаунт WhatsApp | опциональное |
job_title | Должность | опциональное |
organization_name | Название организации | опциональное |
field_of_activity | Сфера деятельности | опциональное |
city | Город | опциональное |
mattermost_account | Аккаунт Mattermost | опциональное |
slack_account | Аккаунт Slack | опциональное |
ms_teams_account | Аккаунт MS Teams | опциональное |
sex | Пол | значения male / female · в карточках: «мужчина» / «женщина» |
Набор одинаков для всех способов интеграции (Tilda, WordPress, Bitrix, браузерный JS, server-side API). Каждое значение приходит строкой длиной до 5000 символов.