# HTML-Formulare

> Sende ein beliebiges HTML-Formular ohne JavaScript an Ikiform: Weiterleitungen, reservierte Felder, Arrays und der Honeypot.

Ein einfaches HTML-Formular ist die ganze Integration. Kein Skript, kein iframe und kein Embed: Setze `action` auf den Endpunkt deines Formulars und behalte dein eigenes Markup und CSS. Das funktioniert auch in Website-Baukästen, in die du eigenes HTML einfügen kannst; siehe [Website-Baukästen](https://ikiform.com/de/docs/guides/site-builders.md).

## Ein einfaches Formular

`contact.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label>
    Name
    <input name="name" autocomplete="name" required />
  </label>
  <label>
    Email
    <input name="email" type="email" autocomplete="email" required />
  </label>
  <label>
    Message
    <textarea name="message" rows="5"></textarea>
  </label>
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>
```

- `method` muss `post` sein. Der Browser sendet `application/x-www-form-urlencoded` oder `multipart/form-data`, wenn du `enctype` setzt. Beides funktioniert.
- Jedes Steuerelement mit einem `name` wird zu einem Feld. Steuerelemente ohne Namen und deaktivierte Steuerelemente sendet der Browser nicht.
- Werte werden als UTF-8-Text gespeichert, nach NFC normalisiert, wobei CRLF-Zeilenenden zu LF werden und Steuerzeichen entfernt werden.
- Browser-Validierung wie `required` und `type="email"` hilft Menschen, ist aber keine Sicherheitsprüfung. Definiere [Felder](https://ikiform.com/de/docs/fields.md), damit Ikiform Regeln auf dem Server durchsetzt.

## Nach dem Absenden

Ein erfolgreicher Browser-Post wird mit einer `303`-Weiterleitung beantwortet. Ikiform wählt das Ziel in dieser Reihenfolge:

1. Die Einstellung **Redirect after submit** des Formulars im Dashboard. Hier funktioniert jede `http:`- oder `https:`-URL, weil nur Workspace-Mitglieder sie setzen können.
2. Ein `_redirect`- (oder `_next`-)Feld im Post, wenn es die Regeln unten erfüllt.
3. Andernfalls die gehostete Dankeseite von Ikiform unter `/f/<formId>/thanks`. Wenn das Formular erlaubte Domains hat und der Post von einer `https:`-Seite auf einer davon kam, verlinkt die Seite dorthin zurück.

### Regeln für _redirect

Ein `_redirect`-Wert kommt aus dem Browser des Besuchers, deshalb folgt Ikiform ihm nur, wenn er eine `https:`-URL ohne Benutzername, Passwort oder eigenen Port ist und auf einer der erlaubten Domains des Formulars oder einer ihrer Subdomains liegt. Formulare ohne erlaubte Domains ignorieren `_redirect` komplett. Mit erlaubten Domains auf `example.com` gesetzt:

| _redirect | Gefolgt | Warum |
| --- | --- | --- |
| `https://example.com/thanks` | Ja | Erlaubte Domain |
| `https://app.example.com/done` | Ja | Subdomain einer erlaubten Domain |
| `http://example.com/thanks` | Nein | Nicht `https:` |
| `https://example.com:8443/thanks` | Nein | Eigener Port |
| `https://user@example.com/` | Nein | Enthält einen Benutzernamen |
| `https://example.com.evil.dev/` | Nein | Weder die Domain noch eine ihrer Subdomains |

Ein `_redirect`, dem nicht gefolgt wird, fällt auf die gehostete Dankeseite zurück; er verursacht nie einen Fehler. JSON-Anfragen ignorieren Weiterleitungen und bekommen `201` mit der Einsendungs-ID.

### Wenn ein Post abgelehnt wird

Wird ein Post abgelehnt, etwa weil ein Pflichtfeld fehlt, sieht der Browser eine gehostete Fehlerseite mit dem HTTP-Status des Fehlers. Sie listet die Probleme nach Feld-Label auf und verlinkt zurück zum Formular. Alle Codes findest du unter [Fehler](https://ikiform.com/de/docs/errors.md).

## Feldnamen und Arrays

Wiederholte Namen und Namen, die auf `[]` enden, werden zu Arrays. Verwende `[]` für Checkbox-Gruppen und `<select multiple>`, damit auch eine einzelne Auswahl als Array gespeichert wird.

`fields.html`:

```html
<fieldset>
  <legend>Topics</legend>
  <label><input type="checkbox" name="topics[]" value="billing" /> Billing</label>
  <label><input type="checkbox" name="topics[]" value="api" /> API</label>
</fieldset>

<select name="plan">
  <option value="starter">Starter</option>
  <option value="team">Team</option>
</select>

<label><input type="checkbox" name="newsletter" /> Send me product news</label>
```

Wenn beide Themen und die Newsletter-Checkbox angehakt sind, wird Folgendes gespeichert:

`Gespeicherte Felder`:

```json
{
  "topics": ["billing", "api"],
  "plan": "team",
  "newsletter": "on"
}
```

- Namen mit Klammern wie `address[city]` bleiben wörtlich erhalten; sie werden nicht in verschachtelte Objekte umgewandelt. Sende JSON, wenn du verschachtelte Werte willst.
- Eine nicht angehakte Checkbox wird gar nicht gesendet. Mit einem definierten `checkbox`-[Feld](https://ikiform.com/de/docs/fields.md#types) wird eine fehlende Box als `false` und eine angehakte als `true` gespeichert.
- Eine Einsendung kann bis zu 100 Felder haben, Namen bis zu 128 Zeichen und Werte bis zu 16 KB. Siehe [Limits](https://ikiform.com/de/docs/limits.md).

> Datei-Uploads gibt es noch nicht. Ein leeres Dateifeld wird ignoriert; ein Post mit einer echten Datei wird mit `422 files_not_supported` abgelehnt.

## Reservierte Felder

Namen, die mit `_` beginnen, sind Anweisungen für Ikiform. Sie werden nie als Antworten gespeichert.

| Feld | Wirkung |
| --- | --- |
| `_gotcha` | Honeypot. Lass es leer und versteckt; ein ausgefüllter Wert erhöht den Spam-Score um 5, was reicht, um den Post als Spam zu speichern. Der Name lässt sich pro Formular ändern. |
| `_redirect`, `_next` | Wohin der Browser nach einem erfolgreichen Post geschickt wird. Siehe [Regeln für _redirect](#redirect-rules). |
| `_subject` | Ein Label für die Einsendung, gespeichert als `meta.subject` und an Webhooks und die API weitergegeben. Den Betreff der Benachrichtigungs-E-Mail ändert es nicht. Leerraum wird zusammengefasst und auf 200 Zeichen gekürzt. |
| `_replyto` | Reply-To-Adresse für Benachrichtigungs-E-Mails. Wird ignoriert, wenn es nicht genau eine gültige E-Mail-Adresse ist. |
| `_idempotency` | Idempotenzschlüssel, wie der `Idempotency-Key`-Header. Siehe [Idempotenz](https://ikiform.com/de/docs/frameworks.md#idempotency). |
| `_ikiform_ts` | Signierte Renderzeit, gesetzt vom SDK und der shadcn/ui-Komponente. Ein Post, der weniger als 2 Sekunden nach dem Rendern gesendet wird, gilt als Spam. |
| `cf-turnstile-response` | Das Turnstile-Token, hinzugefügt vom Turnstile-Widget oder vom SDK. |
| `_ikiform_via` | Wird von Ikiforms eigener Prüfseite gesetzt. Sende es nicht selbst. |

Jedes andere Feld, das mit `_` beginnt, wird ebenfalls verworfen, sodass du Namen wie `_source` für eigene versteckte Markierungen nutzen kannst, ohne sie zu speichern.

`demo.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <input type="hidden" name="_redirect" value="https://example.com/thanks" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Request a demo</button>
</form>
```

## Der Honeypot

Der Standardname des Honeypots ist `_gotcha`. Du kannst ihn pro Formular unter **Honeypot field** in den Einstellungen des Formulars ändern; welchen Namen du auch wählst, er gilt als reserviert und wird nie gespeichert. Ein einfaches `hidden`-Attribut reicht für die meisten Bots. Wenn Spam durchkommt, verschiebe das Eingabefeld stattdessen aus dem sichtbaren Bereich, weil manche Bots als `hidden` markierte Felder überspringen:

`honeypot.html`:

```html
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
  <label>
    Leave this empty
    <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </label>
</div>
```

Behalte `tabindex="-1"` und `autocomplete="off"` bei, damit Tastaturnutzer und Passwortmanager es nie ausfüllen.

## Menschlichkeitsprüfung hinzufügen

Formulare mit der Spamprüfung auf **Ikiform** brauchen keine Änderung an deinem HTML. Wenn ein Browser ohne Token sendet, antwortet Ikiform mit einer kurzen Seite „Prüfung, ob du ein Mensch bist“ auf ikiform.com. Sie führt Cloudflare Turnstile aus und sendet dann die ursprünglichen Felder mit dem Token erneut. Dein Besucher landet auf derselben Dankeseite wie zuvor. Den vollständigen Ablauf findest du unter [Spamschutz](https://ikiform.com/de/docs/spam.md#human-check).

### Mit eigenen Turnstile-Schlüsseln

Wenn das Formular **Your own Turnstile keys** verwendet, renderst du das Widget selbst. Es fügt dem Post das Feld `cf-turnstile-response` hinzu. Posts ohne gültiges Token werden mit `403 captcha_failed` abgelehnt.

`turnstile.html`:

```html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
  <button>Send</button>
</form>
```
