# Menambahkan formulir kontak ke situs GitHub Pages

> GitHub Pages tidak bisa menjalankan kode server, jadi POST formulir mendapat 405 Not Allowed; kirim ke form backend dan atur redirect project site dengan benar.

Terbit 2026-10-25 · https://ikiform.com/id/guides/contact-form-static-site/github-pages

GitHub Pages hanya menyajikan file statis, jadi formulir yang mengirim ke situs Anda sendiri mendapat `405 Not Allowed` dan pesannya hilang. Atur `action` formulir ke endpoint Ikiform, tambahkan `username.github.io` dan domain kustom apa pun ke **Allowed domains**, lalu redirect ke halaman terima kasih yang menyertakan path project site Anda. Tidak ada yang berubah di repository atau pengaturan Pages, dan tidak ada rahasia yang masuk ke repo publik.

## Apa yang berbeda di GitHub Pages

GitHub Pages menerbitkan apa yang dibangun repository atau workflow Actions Anda, tidak lebih. Jekyll berjalan saat build jika Anda memakainya, lalu hasilnya berupa file. Tidak ada request handler, jadi `mail()` PHP, skrip Node, atau formulir CGI Python tidak akan berjalan, apa pun yang Anda commit.

Anda bisa melihat kegagalannya dari terminal. POST ke halaman mana pun di situs Pages mendapat ini:

`Terminal`:

```bash
curl -i -X POST -d "message=hello" https://ada.github.io/notebook/contact.html
```

`Respons`:

```http
HTTP/2 405
server: Varnish
content-length: 131

<html>
<head><title>405 Not Allowed</title></head>
```

Empat hal lain membedakan Pages dari host statis lain, dan masing-masing menyentuh formulir kontak:

| Ciri Pages | Artinya bagi formulir |
| --- | --- |
| Project site berada di bawah sebuah path, `username.github.io/repo/` | URL terima kasih `/thanks.html` mengarah ke user site, bukan project Anda. Setiap URL butuh bagian `/repo/` |
| Tidak ada pengaturan untuk header respons kustom | Content-Security-Policy hanya bisa berasal dari tag `<meta>` di halaman |
| Repository sering kali publik | Apa pun di dalamnya bersifat publik. ID formulir tidak masalah di sana; secret API key atau password email tidak boleh |
| GitHub menyatakan situs Pages tidak boleh dipakai untuk transaksi sensitif seperti mengirim password atau nomor kartu kredit | Biarkan formulir kontak tetap sebagai formulir kontak. Jangan kumpulkan data kartu atau password akun lewat formulir itu |

Diagram: Apa yang dijalankan GitHub Pages, dan ke mana kiriman formulir kontak harus pergi

1. Anda push ke branch yang diterbitkan Pages.
2. Jekyll atau workflow Actions Anda membangun situs sekali.
3. Pages menyajikan hasilnya sebagai file statis di github.io atau domain kustom Anda.
4. Pengunjung mengirim formulir kontak. Jika action-nya mengarah ke situs Anda sendiri, Pages menjawab 405 Not Allowed.
5. Dengan action diatur ke endpoint Ikiform Anda, Ikiform menyimpan pesan dan mengirimi Anda email.
6. Ikiform me-redirect browser ke halaman terima kasih, yang disajikan Pages seperti file lainnya.

Kode berjalan di GitHub sekali per push. Tidak ada kode Anda yang berjalan saat pengunjung menekan Kirim, itulah sebabnya kiriman harus keluar dari github.io.

## Formulirnya

Untuk situs yang ditulis manual, tambahkan `contact.html` di samping `index.html`. Contoh ini untuk project site di `ada.github.io/notebook`, jadi redirect-nya menyertakan `/notebook/`:

`contact.html`:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
    />
    <title>Contact</title>
  </head>
  <body>
    <h1>Get in touch</h1>
    <form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
      <label for="name">Name</label>
      <input id="name" name="name" autocomplete="name" required />

      <label for="email">Email</label>
      <input id="email" name="email" type="email" autocomplete="email" required />

      <label for="about">What is it about?</label>
      <select id="about" name="about">
        <option value="question">A question about the project</option>
        <option value="hire">Work together</option>
        <option value="other">Something else</option>
      </select>

      <label for="message">Message</label>
      <textarea id="message" name="message" rows="6" minlength="10" required></textarea>

      <input type="hidden" name="page" value="docs-home" />
      <input type="hidden" name="_redirect" value="https://ada.github.io/notebook/thanks.html" />
      <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
      <button type="submit">Send</button>
    </form>
  </body>
</html>
```

- Content-Security-Policy lewat `<meta>` bersifat opsional. Pertahankan jika Anda sudah punya, dan pastikan `form-action` dan `connect-src` menyertakan `https://ikiform.com`. Pages tidak bisa mengirim header itu untuk Anda.
- Select `about` memberi tahu alasan seseorang menulis sebelum Anda membuka pesannya. Ubah opsinya sesuai hal yang benar-benar sering ditanyakan orang kepada Anda.
- Input tersembunyi `page` mencatat di halaman mana formulir berada, yang berguna jika formulir yang sama ada di beberapa halaman dokumentasi.
- Pertahankan `email` sebagai nama field. Email notifikasi memakainya sebagai alamat reply-to.

Jika HTML yang sama di-deploy di beberapa path, atau Anda belum yakin path akhirnya, buat redirect di browser dari alamat halaman itu sendiri. Taruh ini setelah formulir:

`contact.html`:

```html
<script>
  document.querySelectorAll('input[name="_redirect"]').forEach((input) => {
    input.value = new URL("thanks.html", document.baseURI).href;
  });
</script>
```

Memakai Jekyll? Jangan tulis URL secara hard-code sama sekali. [Panduan Jekyll](https://ikiform.com/id/docs/guides/jekyll.md) punya include yang membuatnya dengan `absolute_url`, yang menambahkan `baseurl` Anda untuk project site. Build dengan Astro, Vite, atau Hugo lewat workflow Actions? Atur base path framework ke `/repo/` agar aset formulir termuat, dan pakai panduan [Hugo](https://ikiform.com/id/docs/guides/hugo.md) atau framework Anda untuk formulirnya.

## Domain yang diizinkan di github.io

Tambahkan `ada.github.io`, dengan username Anda sendiri. Domain ini mencakup user site dan setiap project site Anda, karena project site berbagi host yang sama. Tambahkan juga domain kustom jika Anda memakainya; `example.com` juga mencakup `www.example.com`.

Jangan pernah menambahkan `github.io` begitu saja. Setiap situs Pages akan cocok, termasuk salinan formulir Anda di situs orang lain. Dengan domain yang diizinkan diatur, `_redirect` ke `https://ada.github.io/notebook/thanks.html` diikuti; tanpanya, Ikiform mengabaikannya dan menampilkan halaman terima kasih hosted.

> Aktifkan **Enforce HTTPS** di pengaturan Pages repository. Ikiform hanya mengikuti nilai `_redirect` yang diawali `https:`, dan domain kustom yang belum punya sertifikat menyajikan halaman `http:`.

## Mengganti link mailto:

Banyak situs Pages berawal dengan link `mailto:` di footer. Menggantinya dengan formulir mencegah scraper baru membaca alamat Anda dari halaman, dan pengunjung tanpa aplikasi email akhirnya bisa menghubungi Anda. Dua hal yang perlu diketahui sebelum menghapusnya:

- Alamat itu tetap ada di riwayat repository, dan di fork atau arsip halaman lama mana pun. Formulir membantu mulai sekarang; ia tidak membuat alamat yang sudah publik bertahun-tahun kembali privat.
- Balasan dikirim dari inbox Anda sendiri. Email notifikasi menjadikan pengirim sebagai alamat reply-to, jadi menekan **Reply** bekerja seperti link `mailto:`, hanya dari arah sebaliknya.

Ikiform tidak pernah mengirim email ke pengunjung, jadi sebutkan di halaman terima kasih kapan mereka bisa mengharapkan jawaban. Jika pesan yang masuk lebih banyak dari yang bisa Anda jawab lewat email, webhook bisa memasukkan setiap pesan ke [Slack](https://ikiform.com/blog/form-submissions-to-slack.md) atau [Discord](https://ikiform.com/blog/form-submissions-to-discord.md).

## Pastikan berfungsi

Jalankan ini di alamat `github.io` yang live. Pages tidak punya deploy preview, jadi uji dulu secara lokal dengan server lokal.

1. Tambahkan `localhost` dan `username.github.io` di **Allowed domains**, ditambah domain kustom Anda jika ada.
2. Commit `contact.html` dan `thanks.html`, tunggu deployment Pages selesai di tab **Actions** repository, lalu buka halaman live.
3. Kirim formulirnya. Anda seharusnya mendarat di `thanks.html` milik Anda, dengan path project di address bar.
4. Buka **Submissions** di dashboard. Kiriman baru ada di sana dengan setiap field yang Anda kirim.
5. Cek inbox setiap penerima notifikasi. Masing-masing mendapat email berisi field, dan **Reply** terkirim ke pengirim formulir jika formulir punya field `email`.
6. Tidak ada yang masuk? Ubah filter status di dashboard ke **Spam**. Spam mendapat jawaban sukses yang sama dengan kiriman asli.

## Hal yang sering menjebak

| Masalah | Yang harus dilakukan |
| --- | --- |
| `405 Not Allowed` setelah menekan Kirim | Formulir yang di-deploy masih mengirim ke situs Anda sendiri. Lihat source halaman di github.io dan cek `action`-nya; build lama yang ter-cache mungkin masih live selama beberapa menit. |
| Halaman terima kasih Ikiform, bukan milik Anda | Nilai `_redirect` tidak menyertakan path repository, berupa `http:`, atau formulir tidak punya domain yang diizinkan. Tambahkan `username.github.io` dan pakai URL `https:` lengkap. |
| `403 origin_not_allowed`, atau setiap kiriman masuk ke spam | Domain halaman tidak ada di **Allowed domains** formulir. Tambahkan, ditambah `localhost` untuk uji lokal. Subdomain dari domain yang terdaftar diizinkan. |
| Kiriman formulir berfungsi di lokal tetapi console menampilkan error CSP di github.io | Content-Security-Policy `<meta>` di layout Anda tidak menyertakan `https://ikiform.com` di `form-action` atau `connect-src`. |

## Pertanyaan

### Bisakah GitHub Pages memproses kiriman formulir?

Tidak. GitHub Pages menyajikan file statis dan tidak menjalankan kode saat pengunjung mengirim formulir, jadi POST ke URL Pages mendapat 405 Not Allowed. Arahkan action formulir ke form backend.

### Apakah aman meng-commit endpoint formulir ke repository publik?

Aman. ID formulir toh akan ada di HTML publik Anda. Lindungi formulir dengan domain yang diizinkan dan pemeriksaan spam, dan jangan pernah meng-commit secret API key, karena situs statis tidak punya tempat aman untuk menyimpannya.

### Mengapa redirect terima kasih saya mengarah ke halaman yang salah di project site?

Path seperti /thanks.html mengarah ke root username.github.io, bukan ke project Anda. Pakai URL lengkap dengan path repository, atau buat dari document.baseURI di browser.

### Apakah formulir tetap berfungsi setelah saya menambahkan domain kustom ke GitHub Pages?

Ya. Formulir mengirim ke Ikiform apa pun domain yang menyajikan halaman. Tambahkan domain kustom di Allowed domains di samping username.github.io, dan perbarui nilai _redirect agar memakai domain kustom setelah HTTPS diterapkan.

### Apakah Ikiform gratis?

Tidak, tidak ada paket gratis. Pengujian gratis: Anda bisa mengirim 50 kiriman uji per bulan dari localhost sebelum membayar. Untuk go live, Pro mulai $6/bln untuk 500 kiriman, atau Anda bisa bayar sekali untuk 10.000 kiriman seharga $49 atau 50.000 kiriman seharga $149, dengan kredit yang tidak pernah kedaluwarsa.

## Panduan lainnya

- [Formulir kontak di situs statis](https://ikiform.com/id/guides/contact-form-static-site.md): Pasang formulir kontak yang berfungsi di situs statis tanpa server: ke mana POST dikirim, spam, balasan lewat email, dan kode untuk setiap host dan framework.
- [Netlify](https://ikiform.com/id/guides/contact-form-static-site/netlify.md): Jalankan formulir kontak di situs Netlify tanpa Netlify Forms: tanpa deteksi saat build, kiriman JSON dari React, dan formulir terpisah untuk deploy preview.
- [Cloudflare Pages](https://ikiform.com/id/guides/contact-form-static-site/cloudflare-pages.md): Tambahkan formulir kontak ke Cloudflare Pages tanpa menulis Function: kirim ke form backend, atur header di _headers, dan pakai key Turnstile Anda sendiri.
- [Website portofolio](https://ikiform.com/id/guides/contact-form-static-site/portfolio-website.md): Formulir kontak portofolio yang menanyakan hal yang biasa Anda tanyakan di panggilan pertama: proyek, budget, waktu, dan link, tanpa server dan dengan balasan dari inbox Anda.
- [Vercel](https://ikiform.com/id/guides/contact-form-static-site/vercel.md): Halaman statis di Vercel menjawab POST formulir dengan 405 Method Not Allowed; ini penyebabnya, dan cara mengirim formulir ke backend.
- [Amazon S3](https://ikiform.com/id/guides/contact-form-static-site/aws-s3.md): Endpoint website S3 hanya menerima GET dan HEAD lewat HTTP biasa, jadi kirim formulir kontak ke form backend dan atur redirect dengan benar lewat CloudFront.
