Cara kerja form Adopt-Assessment di /book
Halaman /book punya satu form lead — Adopt Assessment. Tapi situs ini statis (SSG): tiap halaman adalah HTML yang sudah jadi, disajikan dari CDN, tanpa server kami sendiri. Jadi ke mana submit-nya pergi? Berikut cara kerjanya, sampai ke detailnya.
Masalahnya: situs statis tak punya server
Situs ini di-prerender saat build lalu disajikan sebagai file statis dari edge Cloudflare. Cepat
dan murah — tapi artinya tak ada endpoint backend yang bisa menerima POST dari form. Cara
klasik (form mengirim ke skrip server) tak tersedia. Kami butuh tempat lain untuk menampung
submission.
Solusinya: Web3Forms (form-backend sebagai layanan)
Form-nya POST langsung dari browser ke Web3Forms, sebuah layanan yang menerima submission
lalu meneruskannya ke inbox Anda. Tak ada server kami di tengah — hanya fetch dari sisi klien:
const res = await fetch('https://api.web3forms.com/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({
access_key: WEB3FORMS_KEY, // publik — hanya merutekan ke inbox, tak membaca apa pun
name, email, phone, company, about,
botcheck: false, // honeypot (lihat di bawah)
...attribution, // utm_*, referrer, landing_page — tanpa cookie
}),
})
const data = await res.json()
if (data.success) {
// tampilkan "terkirim", reset form, kirim event generate_lead
}
Access key-nya publik — dan itu memang aman
access_key-nya di-commit ke repo, terlihat di bundle. Itu bukan kebocoran: access key
Web3Forms cuma merutekan submission ke inbox yang dikonfigurasi. Ia tak bisa membaca data, tak
memberi akses ke akun, tak menandatangani apa pun — paling jauh, orang lain bisa mengirim submission
ke inbox yang sama (dan untuk itu ada honeypot + rate limit Web3Forms; kalau disalahgunakan, tinggal
rotasi key-nya). Ini perbedaan penting: bukan tiap string panjang itu rahasia. Yang rahasia
adalah yang bisa membaca atau mengubah sesuatu.
Anti-spam: honeypot
Tanpa server, kami tak bisa menjalankan cek khusus — jadi form memasang honeypot: satu field
tersembunyi (botcheck) yang diposisikan di luar layar dan disembunyikan dari screen reader. Manusia
tak pernah melihatnya, jadi tak pernah mengisinya; banyak bot mengisi tiap field yang ditemukan.
Web3Forms menolak submission yang field honeypot-nya terisi.
{/* honeypot — manusia tak melihatnya; bot yang mengisi → ditolak */}
<input type="text" name="botcheck" tabIndex={-1} aria-hidden="true"
style={{ position: 'absolute', left: '-9999px', opacity: 0 }} />
Atribusi tanpa cookie
Saat pengunjung pertama mendarat, form menyimpan first-touch attribution — utm_*, referrer,
dan landing page — ke sessionStorage, lalu menempelkannya ke tiap submission. Ini berjalan
tanpa cookie dan tanpa persetujuan: sessionStorage bukan cookie, hanya hidup selama tab, dan
tak melacak Anda lintas situs. Jadi lead datang dengan sumbernya melekat — dari mana kampanye, dari
referrer mana — tanpa menyentuh consent.
Sinyal konversi: generate_lead
Saat Web3Forms mengembalikan success, form mengirim event GA4 generate_lead (lewat gtag)
membawa utm_* first-touch. Kalau VITE_GA_ID tak diset, track() jadi no-op — jadi tanpa GA pun
form tetap bekerja. Dan di bawah Consent Mode v2 'denied', GA4 tetap mengirim event itu
cookieless (tanpa client-id), jadi kami menghormati consent tanpa kehilangan sinyal agregat.
State & aksesibilitas
Form punya empat state — idle · sending · sent · error. Tombol berganti label dan
dinonaktifkan saat sending (mencegah double-submit). Hasilnya diumumkan ke teknologi bantu:
sukses pakai role="status", error dan error validasi telepon pakai role="alert". Tiap field punya
<label htmlFor>, dan input telepon mengikat error-nya lewat aria-invalid + aria-describedby.
Validasi nomor dilakukan di klien (^\d{6,15}$) sebelum apa pun terkirim.
CSP: kenapa fetch, bukan action form
Situs ini mengunci Content-Security-Policy tanpa 'unsafe-inline'. Dua arahan menentukan ke mana
form boleh bicara:
Pertanyaan umum
Apakah access key Web3Forms itu rahasia?
Bukan — ia publik secara desain dan aman untuk di-commit. Access key cuma merutekan submission ke inbox yang dikonfigurasi; ia tak bisa membaca data, mengakses akun, atau menandatangani apa pun. Paling jauh orang lain bisa mengirim submission ke inbox yang sama — yang ditangani honeypot plus rate limit Web3Forms, dan key-nya bisa dirotasi kalau disalahgunakan.
Bagaimana spam ditangani tanpa CAPTCHA?
Dengan honeypot: satu field tersembunyi (botcheck) yang manusia tak pernah lihat atau isi, tapi banyak bot mengisinya secara otomatis. Submission yang field-nya terisi ditolak. Web3Forms juga menjalankan cek spam dan rate limit di sisi server. Untuk volume lebih tinggi, CAPTCHA tanpa-friksi seperti Cloudflare Turnstile bisa ditambahkan.
Apakah pelacakan UTM/referrer butuh persetujuan cookie?
Tidak. Atribusi disimpan di sessionStorage (bukan cookie, hanya hidup selama tab, tak lintas situs) lalu ditempelkan ke submission — jadi tak butuh consent. Event generate_lead GA4 juga dikirim cookieless di bawah Consent Mode 'denied', jadi sinyal konversi tetap menghormati pilihan pengguna.
Tempatnya di mana
Pola ini bersandar pada hosting statis dari CI/CD: GitHub Actions → Cloudflare Pages
dan baseline keamanan dari SSL & keamanan di edge (CSP-nya
mengizinkan connect-src ini). Form-nya sendiri hidup di /book.
Sources