Разработка формы с предзаполнением данных (через URL/API) на сайте
Предзаполненные формы повышают конверсию и снижают трение. Пользователь, перешедший по ссылке из email или CRM, видит уже заполненные поля — ему остаётся только проверить и отправить. Форма с предзаполнением из API экономит время при повторных обращениях.
Источники предзаполнения
URL-параметры — простейший вариант. Ссылка вида /apply?name=Иван&[email protected]&plan=pro заполняет соответствующие поля при загрузке страницы.
JWT-токен в URL — данные зашифрованы, не редактируются пользователем напрямую, можно передавать чувствительные значения.
API-запрос — форма загружает данные пользователя по его авторизационному токену или по ID сущности (заказ, заявка, профиль).
SessionStorage / Cookie — данные из предыдущей сессии или из другой страницы того же сайта.
Предзаполнение из URL-параметров
function prefillFromURL() {
const params = new URLSearchParams(window.location.search);
// Белый список — никогда не заполнять скрытые/системные поля из URL
const allowed = ['name', 'email', 'phone', 'company', 'plan', 'promo'];
for (const field of allowed) {
const value = params.get(field);
if (!value) continue;
const el = document.querySelector(`[name="${field}"]`);
if (!el) continue;
// Sanitize — только текст, без HTML
el.value = DOMPurify.sanitize(value, { ALLOWED_TAGS: [] });
el.dispatchEvent(new Event('input', { bubbles: true }));
}
}
document.addEventListener('DOMContentLoaded', prefillFromURL);
Предзаполнение через JWT
Безопаснее, чем открытые параметры — данные подписаны, нельзя подменить без знания секрета:
// Ссылка вида: /form?token=eyJhbGci...
async function prefillFromToken() {
const token = new URLSearchParams(window.location.search).get('token');
if (!token) return;
const res = await fetch('/api/form-prefill', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token }),
});
if (!res.ok) return;
const data = await res.json();
applyFormData(data);
}
На сервере Laravel:
public function decodePrefillToken(Request $request)
{
try {
$payload = JWT::decode($request->token, new Key(config('app.key'), 'HS256'));
return response()->json((array) $payload->form_data);
} catch (\Exception $e) {
return response()->json(['error' => 'Invalid token'], 422);
}
}
Генерация токена (например, при отправке email):
$payload = [
'form_data' => [
'name' => $user->name,
'email' => $user->email,
'plan' => 'pro',
],
'exp' => now()->addHours(24)->timestamp,
];
$token = JWT::encode($payload, config('app.key'), 'HS256');
$link = route('form') . '?token=' . $token;
Предзаполнение из API (для авторизованных пользователей)
async function prefillFromProfile() {
const res = await fetch('/api/user/profile');
if (!res.ok) return;
const profile = await res.json();
const mapping = {
'contact[name]': profile.full_name,
'contact[email]': profile.email,
'contact[phone]': profile.phone,
'address[city]': profile.city,
'address[street]': profile.address,
};
for (const [fieldName, value] of Object.entries(mapping)) {
if (value == null) continue;
const el = document.querySelector(`[name="${fieldName}"]`);
if (el) el.value = value;
}
}
React Hook Form + предзаполнение
function ApplicationForm({ userId }) {
const { register, reset, handleSubmit } = useForm();
useEffect(() => {
async function load() {
const res = await fetch(`/api/users/${userId}/prefill`);
const data = await res.json();
reset(data); // заполняет все поля формы
}
if (userId) load();
}, [userId, reset]);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} placeholder="Имя" />
<input {...register('email')} placeholder="Email" />
{/* ... */}
</form>
);
}
Безопасность
-
Никогда не предзаполнять из URL поля типа
role,is_admin,price,discount - Все значения из URL санитизировать перед вставкой (XSS через
value) - Данные из токена проверять на сервере — не доверять фронту
- Использовать
rel="noopener noreferrer"при генерации ссылок во внешних системах
Визуальная индикация
Предзаполненные поля стоит визуально выделить, чтобы пользователь понял, что данные уже вставлены, и мог их проверить:
.field--prefilled {
background: #f0f9ff;
border-color: #38bdf8;
}
.field--prefilled::after {
content: '✓ предзаполнено';
font-size: 0.75rem;
color: #0369a1;
}
Сроки
Предзаполнение из URL с санитизацией — 1 рабочий день. JWT-токены + серверный API с маппингом полей и индикацией — 3–4 дня.







