Инструкция: Лид-форма на лендинге
Trigger: лендинг содержит форму для сбора заявок / контактов
Uses: instructions/create_landing_page, instructions/landing_brief
Зачем
Добавить форму на лендинг, написать HTML/JS для кастомного рендера, поставить cron на уведомление о необработанных заявках.
Шаг 1 — Уточнить у пользователя
Перед созданием формы — спросить:
- Какие поля нужны? (имя, email, телефон, сообщение, Telegram username)
- Нужен ли редирект после отправки? Куда? (
success_url) - Кто может отправлять?
guest(все) /admin(только авторизованные) - Куда уведомлять о заявках? Telegram username?
Шаг 2 — Определить форму в frontmatter заметки
---
title: Название лендинга
layout: html-page # или кастомный layout
form:
can_submit: guest
success_url: /thanks
fields:
- name: name
type: text
required: true
max_length: 200
- name: email
type: email
required: true
- name: phone
type: text
required: false
max_length: 20
- name: message
type: text
required: false
max_length: 2000
---
trip2g встроит <script id="form-spec" type="application/json"> в страницу автоматически.
Шаг 3 — Написать layout с формой
Основа — готовый пример: docs/_layouts/forms/example.html в репозитории trip2g.
Пример уже содержит:
- Динамический рендер полей из
form-specJSON (все типы: text, email, int, bool, textarea для длинных полей) - Полный GraphQL submit с обработкой всех ответов (
SubmitFormPayload,FormSubmitDeniedPayload,ErrorPayload) - BEM-классы
form-card__*, disabled-состояние кнопки,aria-liveдля доступности - Редирект по
success_urlпосле успеха
Как адаптировать для лендинга:
- Скопировать
example.html→ в_layouts/лендинга - Встроить форму в нужное место страницы (не в конце, а в CTA-секцию)
- Поменять CSS-переменные под стиль бренда (цвета, шрифты)
- Перевести лейблы и сообщения на русский:
'Send a message'→ нужный заголовок'Submit'→ текст кнопки'Thanks — submission #...'→ сообщение об успехе- Сообщения об ошибках в объекте
messages
- Добавить
<script id="form-spec">{{ note.FormSpecJSON() | unsafe }}</script>в layout
Ключевые строки из примера (не менять):
const spec = JSON.parse(document.getElementById('form-spec').textContent);
const definition = (spec.forms || {})[formId]; // formId = '' для одиночной формы
// ...
variables: { input: { noteVersionId: spec.note_version_id, formId, fields } }
Шаг 4 — Объяснить пользователю про токен
Перед настройкой cron — обязательно сообщить:
"Чтобы я мог проверять заявки автоматически, нужно создать личный токен в админке trip2g:
Настройки → API → Создать токен (personal admin token, начинается сt2g_)
Пришли мне этот токен — я сохраню его и поставлю автопроверку."
После получения токена — сохранить в ~/.env или extra_creds.md:
TRIP2G_ADMIN_TOKEN=t2g_...
Шаг 5 — Узнать notePathId формы
curl -sS https://$TRIP2G_URL/_system/graphql \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $TRIP2G_ADMIN_TOKEN" \
-d '{"query": "query { admin { formNotes { notePathId path title submitCount } } }"}'
Найти нужную заметку по path → запомнить notePathId.
Шаг 6 — Поставить cron на проверку каждые 4 часа
/cron create "Проверь заявки формы.
Выполни GraphQL запрос:
curl -sS https://$TRIP2G_URL/_system/graphql \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer $TRIP2G_ADMIN_TOKEN' \
-d '{\"query\": \"query($p: Int64!) { admin { formSubmits(notePathId: $p) { nodes { id createdAt status fields { ... on AdminFormStringValue { name value } } } } } }\", \"variables\": {\"p\": NOTE_PATH_ID}}'
Если есть записи со status != processed — посчитай их и сообщи пользователю:
'У тебя N необработанных заявок. Смотри: $TRIP2G_URL/admin/forms'"
--schedule "0 */4 * * *"
Шаг 7 — Отметить заявку как обработанную
Агент может пометить заявку обработанной по запросу пользователя:
mutation Mark($input: MarkFormSubmitProcessedInput!) {
markFormSubmitProcessed(input: $input) {
... on MarkFormSubmitProcessedPayload { submit { id processedAt } }
... on ErrorPayload { message }
}
}
Variables: { "input": { "submitId": "ID_из_заявки" } }
Типы полей для справки
type |
Используй для | В JS поле |
|---|---|---|
text |
имя, телефон, Telegram, сообщение | stringValue |
email |
stringValue |
|
int |
рейтинг, количество | intValue |
bool |
чекбокс согласия | boolValue |
Кейсы
Кейс 1: Простая форма "перезвоните мне"
form:
fields:
- name: phone
type: text
required: true
Кейс 2: Форма с согласием на обработку данных
form:
fields:
- name: email
type: email
required: true
- name: agree
type: bool
required: true
enum: [true]
Кейс 3: Форма только для залогиненных
form:
can_submit: admin
fields:
- name: message
type: text
required: true