# Framer

> Sende ein Framer-Formular ohne Code über sein Webhook-Ziel an Ikiform oder rendere dein eigenes Formular mit einer Code-Komponente, die aus dem Browser sendet.

Framer-Formulare können nicht an eine externe Action-URL senden, aber jede Einsendung an einen Webhook schicken. Das ergibt zwei Wege: Du behältst das Framer-Formular und fügst Ikiform als Webhook hinzu, oder du setzt eine kleine Code-Komponente ein, die aus dem Browser des Besuchers sendet.

|   | Framer-Formular mit Webhook | Code-Komponente |
| --- | --- | --- |
| Wer den Request sendet | Die Server von Framer | Der Browser des Besuchers |
| Code | Keiner | Eine React-Datei |
| Erlaubte Domains | Leer lassen: Server-Requests haben keinen `Origin` | Wird mit deiner Framer-Domain abgeglichen |
| Honeypot | Nicht verfügbar | Enthalten |
| Rate-Limits zählen | Die Serveradressen von Framer | Jeden Besucher |
| Ikiform-Spamprüfung | Ausgeschaltet lassen | Ausgeschaltet lassen |

## Framer-Formular mit Webhook

### Schritt 1: Inputs benennen

Framer sendet JSON mit dem Namen jedes Inputs als Schlüssel, daher werden die Namen, die du den Inputs gibst, zu den Feldnamen in Ikiform. Nutze kleingeschriebene IDs wie `email` und `message` und halte dich an deine [Felddefinition](https://ikiform.com/de/docs/fields.md), falls du eine hast.

### Schritt 2: Ikiform als Webhook hinzufügen

Wähle das Formular auf der Arbeitsfläche aus. Wähle in der rechten Seitenleiste neben **Send To** die Option **Add…** > **Webhook** und füge deinen Endpunkt ein. Framer verlangt eine `https://`-URL, und das ist der Endpunkt bereits.

`Webhook-URL`:

```text
https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx
```

Framer kann Requests mit einem Secret signieren. Ikiform prüft den Header `Framer-Signature` nicht, daher ist das Secret hier optional.

### Schritt 3: Einstellungen des Ikiform-Formulars anpassen

- Lass **Allowed domains** leer. Framer sendet von seinen Servern ohne `Origin`-Header, daher wird bei gesetzten Domains jeder Request mit `origin_mismatch` als Spam markiert oder mit **Reject** abgelehnt.
- Lass die Spamprüfung ausgeschaltet. Ein JSON-Request ohne Token bekommt `403 challenge_required`, und Framer hat keine Möglichkeit, die Prüfung auszuführen.
- Wähle das [Rate-Limit](https://ikiform.com/de/docs/rate-limits.md) **Relaxed**. Ikiform zählt Requests pro IP-Adresse und Formular, und jeder Request kommt von den Servern von Framer statt von deinen Besuchern.

Framer behandelt jede Antwort außer `2xx` als Fehler und versucht es bis zu 5-mal erneut. Ikiform antwortet mit `201`, sobald die Einsendung gespeichert ist. Ein Request, den Ikiform ablehnt, etwa mit `422 validation_failed`, schlägt bei jedem erneuten Versuch genauso fehl, also behebe die Ursache, statt zu warten.

## Code-Komponente

Eine Code-Komponente rendert ein echtes Formular auf deiner Seite, daher sendet der Browser es und Ikiform sieht deine Site als Origin. Öffne im Panel **Assets** den Bereich **Code**, erstelle eine Code-Datei und füge Folgendes ein:

`IkiformContact.tsx`:

```tsx
import { addPropertyControls, ControlType } from "framer";
import { type CSSProperties, type FormEvent, useState } from "react";

const field: CSSProperties = {
  font: "inherit",
  padding: "10px 12px",
  borderRadius: 8,
  border: "1px solid rgba(0, 0, 0, 0.15)",
};

export default function IkiformContact({ formId, successText }: { formId: string; successText: string }) {
  const [status, setStatus] = useState<"idle" | "sending" | "sent" | "error">("idle");
  const [message, setMessage] = useState("");

  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setStatus("sending");
    try {
      const response = await fetch(`https://ikiform.com/f/${formId}`, {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(event.currentTarget),
      });
      const result = await response.json();
      if (result.ok) return setStatus("sent");
      setMessage(result.error.message);
    } catch {
      setMessage("Couldn't reach the server. Try again.");
    }
    setStatus("error");
  }

  if (status === "sent") return <p>{successText}</p>;

  return (
    <form onSubmit={onSubmit} style={{ display: "grid", gap: 12, width: "100%" }}>
      <input name="email" type="email" placeholder="Email" autoComplete="email" required style={field} />
      <textarea name="message" placeholder="Message" rows={4} style={field} />
      <input name="_gotcha" type="text" tabIndex={-1} autoComplete="off" hidden />
      {status === "error" ? <p role="alert">{message}</p> : null}
      <button type="submit" disabled={status === "sending"} style={field}>
        {status === "sending" ? "Sending" : "Send"}
      </button>
    </form>
  );
}

addPropertyControls(IkiformContact, {
  formId: { type: ControlType.String, title: "Form ID", defaultValue: "frm_xxxxxxxxxxxxxxxx" },
  successText: { type: ControlType.String, title: "Success text", defaultValue: "Thanks, we got it." },
});
```

- Zieh die Komponente auf die Seite und setze **Form ID** im Eigenschaften-Panel. Style die Inputs, indem du `field` bearbeitest, oder ersetze die Elemente durch deine eigenen.
- `Accept: application/json` sorgt dafür, dass Ikiform mit JSON antwortet, sodass die Komponente das Ergebnis direkt an Ort und Stelle anzeigen kann.
- Die Komponente sendet mit `fetch`, also lass die Spamprüfung des Formulars ausgeschaltet. Honeypot und Spam-Scoring laufen trotzdem.

> Du kannst auch das [Site-Builder-Embed](https://ikiform.com/de/docs/guides/site-builders.md#embed) in den Bereich **HTML** einer **Embed**-Komponente einfügen. Wenn Framer es in einen Frame setzt, laden die Danke- und Fehlerseiten von Ikiform darin nicht, deshalb nutzt das Embed `target="_top"`. Die Code-Komponente vermeidet Frames ganz.

## Erlaubte Domains

Das gilt nur für die Code-Komponente und das Embed. Lass die erlaubten Domains für den Webhook leer.

| Wo das Formular läuft | Zu Allowed domains hinzufügen |
| --- | --- |
| Framer-Subdomain | `your-project.framer.app` oder `your-project.framer.website` bei älteren Projekten |
| Eigene Domain | `example.com`, was auch `www.example.com` abdeckt |
| Editor-Vorschau von Framer | Nichts. Teste stattdessen auf der veröffentlichten Site. |

- Füge niemals `framer.app` oder `framer.website` allein hinzu. Jede Site auf diesem Host würde passen, auch die anderer Leute.

## Test-Checkliste

1. Veröffentliche die Site. Framer sendet Webhooks nur für Formulare auf der veröffentlichten Site.
2. Sende das Formular ab und prüfe die Einsendung in Ikiform. Beim Webhook sollten die Felder exakt deinen Input-Namen entsprechen.
3. Schalte für die Code-Komponente die erlaubten Domains ein, sende von der veröffentlichten Domain ab und prüfe, dass die Einsendung nicht als Spam markiert ist.

## Fehlerbehebung

| Was du siehst | Warum | Lösung |
| --- | --- | --- |
| Jede Webhook-Einsendung landet unter Spam mit `origin_mismatch` | **Allowed domains** ist gesetzt, und die Server-Requests von Framer haben keinen Origin | Leere die erlaubten Domains für dieses Formular oder wechsle zur Code-Komponente. |
| Framer meldet fehlgeschlagene Webhook-Zustellungen | Ikiform hat den Request abgelehnt: `403 challenge_required`, `403 origin_not_allowed` oder `422 validation_failed` | Schalte die Spamprüfung aus, leere die erlaubten Domains und passe die Input-Namen an deine Felder an. |
| `429 rate_limited` bei einem stark genutzten Formular | Requests von den Servern von Framer teilen sich wenige IP-Adressen | Wähle **Relaxed** oder ein eigenes Limit. |
| Die Komponente meldet, dass sie den Server nicht erreichen konnte | Ein Adblocker oder eine Privacy-Erweiterung hat den Request blockiert, oder die **Form ID** ist leer | Probier es in einem privaten Fenster und prüfe, ob die Eigenschaft gesetzt ist. |
| Einsendungen landen im Spamfilter mit `origin_mismatch` | Die sendende Seite steht nicht in den erlaubten Domains des Formulars | Füge den Host aus der Tabelle oben hinzu. Mit **Reject** bekommen dieselben Requests stattdessen `403 origin_not_allowed`. |

## Verwandte Themen

- [React](https://ikiform.com/de/docs/guides/react.md): Lade-, Fehler- und Erfolgszustände.
- [Website-Baukästen](https://ikiform.com/de/docs/guides/site-builders.md): Das Embed, das in jedem Builder funktioniert.
- [Rate-Limits](https://ikiform.com/de/docs/rate-limits.md): Presets und wie sie sich wieder auffüllen.
- [Spamschutz](https://ikiform.com/de/docs/spam.md): Honeypot, Scoring und die Menschlichkeitsprüfung.
