# Framer-Formulare: wann ein Formular-Backend sinnvoll ist und wie

> Framer-Formulare senden bereits an E-Mail, Sheets oder einen Webhook; ergänze Ikiform als Webhook für gespeicherte, gefilterte Einsendungen, Team-Benachrichtigungen und weitere Ziele.

Veröffentlicht am 2026-10-25 · https://ikiform.com/de/guides/website-builder-forms/framer-forms

Die nativen Formulare von Framer senden jede Einsendung an E-Mail, Google Sheets oder einen Webhook, mit eingebautem Spamschutz. Für einen Posteingang oder eine Tabelle brauchst du also vielleicht nichts weiter. Ergänze Ikiform als Webhook-Ziel, wenn du jede Einsendung mit Spam-Status gespeichert, gegen deine Felder validiert, ans Team gemailt und an mehrere signierte Webhooks weitergeleitet haben willst. Da Framer von seinen Servern sendet, lockere entweder die Origin-Prüfungen des Formulars oder setze ein kleines Relay dazwischen, das Framers Signatur prüft.

## Was auf Framer anders ist

Framer ist der einzige Builder in dieser Anleitung ohne Limit, dem man entkommen müsste. Seine Formulare können an E-Mail, Google Sheets oder jeden Webhook senden, und Framer hat eingebauten Spamschutz, der verdächtige Einsendungen markiert oder blockiert. Seine Webhooks sind signiert: Jeder Request trägt einen Header `Framer-Signature`, ein HMAC-SHA256 über Body und Einsendungs-ID, und einen `Framer-Webhook-Submission-Id`. Framer wiederholt bis zu fünfmal, wenn dein Endpunkt nicht mit `2xx` antwortet, und folgt keinen Weiterleitungen.

Sei also ehrlich, warum du ein Formular-Backend ergänzen würdest. Das deckt jede Seite ab:

| Du willst | Nur Framer | Mit Ikiform als Webhook |
| --- | --- | --- |
| Einsendungen in einem Posteingang oder einer Tabelle | Ja | Ja, plus das Dashboard |
| Ein durchsuchbares Archiv mit markiertem Spam und CSV-Export | Dein Posteingang oder deine Tabelle ist das Archiv | Ja |
| Serverseitige Prüfung von Typen, Längen und Optionen | Nein | Ja, mit einer Felddefinition |
| Benachrichtigungen an mehrere Personen, wobei Antworten an den Absender gehen | E-Mail-Ziel | Bis zu 10 Empfänger, mit Reply-to |
| Mehrere Tools aus einem Formular gespeist, jedes mit Wiederholungen | Ein Webhook pro hinzugefügtem Ziel | Bis zu 3 signierte Endpunkte, wiederholt, mit Zustellungsprotokoll |
| Dasselbe Backend für Framer, Webflow und selbst programmierte Sites | Nein | Ja |

Reicht dir die erste Zeile, bleib bei den Zielen von Framer. Der Rest dieser Seite ist für den Fall, dass sie nicht reicht.

## Der Haken: Framer sendet von seinen Servern

Ein Webhook-Ziel heißt, dass die Server von Framer den Post senden, nicht der Browser des Besuchers. Auf der Seite von Ikiform ändern sich drei Dinge:

- **Kein Origin.** Server-Posts tragen keinen `Origin`-Header, also wird bei gesetzten **Allowed domains** jeder Post so behandelt, als käme er von der falschen Site.
- **Geteilte IP-Adressen.** Ikiform zählt Rate-Limits pro IP-Adresse, und jeder Post kommt von wenigen Framer-Adressen statt von denen deiner Besucher.
- **Kein Honeypot.** Framer sendet die Inputs, die du gebaut hast, und sonst nichts, und sein Formular kann Ikiforms Menschlichkeitsprüfung nicht ausführen.

Du kannst das hinnehmen oder es mit einem Relay beheben. Beide Wege stehen unten.

Diagramm: Ein Framer-Formular, das direkt und über ein signiertes Relay an Ikiform sendet

1. Direkt: Ein Besucher sendet das Framer-Formular ab, die Server von Framer senden es als JSON ohne Origin-Header, und Ikiform nimmt es mit leeren Allowed domains und einem Relaxed-Rate-Limit an.
2. Relay: Die Server von Framer signieren jeden Post mit deinem Secret und senden ihn an einen Worker, den du deployst.
3. Der Worker berechnet die Signatur von Framer neu. Ein Post ohne gültige Signatur bekommt 401 und geht nicht weiter.
4. Ein gültiger Post wird mit deinem Secret Key und der Einsendungs-ID von Framer als Idempotency Key an Ikiform weitergeleitet, sodass eine Wiederholung von Framer nie eine zweite Kopie speichert.

Das Relay besteht aus einem Dutzend Zeilen echter Logik. Dafür kann das Formular strenge erlaubte Domains behalten, weil nur dein Worker den Secret Key hat.

## Option 1: Ikiform als Webhook

1. Gib in Framer jedem Input einen kleingeschriebenen Namen: `name`, `work_email`, `company`, `team_size`. Framer nutzt die Namen als JSON-Keys.
2. Wähle das Formular und neben **Send To** dann **Add…** > **Webhook**. Füge deinen Endpunkt ein. Lass das Secret leer; Ikiform prüft `Framer-Signature` nicht.
3. Lass in den Einstellungen des Ikiform-Formulars **Allowed domains** leer, lass **Spam check** aus und setze **Rate limit** auf **Relaxed**.
4. Veröffentliche. Framer sendet Webhooks nur von der veröffentlichten Site.

`Webhook-URL`:

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

Ikiform antwortet mit `201`, sobald die Einsendung gespeichert ist, was Framer als zugestellt zählt. Ein `422 validation_failed` scheitert bei allen fünf Wiederholungen gleich, also korrigiere die Input-Namen, statt zu warten. Der Spam-Score läuft trotzdem bei jedem Post: Links, Spam-Phrasen, Wegwerfadressen und Wiederholungen.

## Option 2: ein signiertes Relay

Deploye einen Cloudflare Worker, der die Signatur von Framer prüft und gültige Posts mit deinem Secret Key weiterleitet. Dann kann das Ikiform-Formular deine Framer-Domain unter **Allowed domains** mit **Reject** listen, sodass alles abgewiesen wird, was weder ein Browser auf deiner Site noch dein Worker ist.

`src/index.ts`:

```ts
interface Env {
  FRAMER_SECRET: string;
  IKIFORM_SECRET_KEY: string;
}

const ENDPOINT = "https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx";
const encoder = new TextEncoder();

async function signatureFor(secret: string, body: ArrayBuffer, submissionId: string) {
  const key = await crypto.subtle.importKey(
    "raw",
    encoder.encode(secret),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"],
  );
  const id = encoder.encode(submissionId);
  const message = new Uint8Array(body.byteLength + id.byteLength);
  message.set(new Uint8Array(body), 0);
  message.set(id, body.byteLength);
  const digest = new Uint8Array(await crypto.subtle.sign("HMAC", key, message));
  return `sha256=${[...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
}

function sameText(a: string, b: string) {
  const left = encoder.encode(a);
  const right = encoder.encode(b);
  return left.byteLength === right.byteLength && crypto.subtle.timingSafeEqual(left, right);
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== "POST") return new Response(null, { status: 405 });
    const signature = request.headers.get("framer-signature") ?? "";
    const submissionId = request.headers.get("framer-webhook-submission-id") ?? "";
    const body = await request.arrayBuffer();
    if (!submissionId || !sameText(signature, await signatureFor(env.FRAMER_SECRET, body, submissionId))) {
      return new Response("Bad signature", { status: 401 });
    }

    const response = await fetch(ENDPOINT, {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: `Bearer ${env.IKIFORM_SECRET_KEY}`,
        "Idempotency-Key": submissionId,
      },
      body,
    });
    if (response.ok) return new Response(null, { status: 204 });
    return new Response(await response.text(), { status: response.status });
  },
};
```

### Deployen

`Terminal`:

```bash
npx wrangler secret put FRAMER_SECRET
npx wrangler secret put IKIFORM_SECRET_KEY
npx wrangler deploy
```

- `FRAMER_SECRET` ist das Secret, das du am Webhook-Ziel von Framer setzt. Framer verlangt mindestens 32 Zeichen und zeigt es nicht erneut an, also erzeuge es, speichere es und füge es an beiden Stellen ein.
- `IKIFORM_SECRET_KEY` ist ein geheimer API-Key aus dem Ikiform-Dashboard. Leg ihn nie in Framer ab.
- Die Signatur ist `sha256=` plus das Hex-HMAC über den rohen Body, gefolgt von der Einsendungs-ID. Lies den Body einmal als Bytes und nutze genau diese Bytes für die Prüfung und die Weiterleitung.
- `Idempotency-Key` sorgt dafür, dass eine Wiederholung von Framer die erste Antwort von Ikiform wiedergibt, statt ein Duplikat zu speichern. Keys werden 24 Stunden aufbewahrt.
- Der Worker reicht den Status von Ikiform durch. Framer wiederholt jede Antwort außerhalb von `2xx` bis zu fünfmal, also bekommt ein `429` oder `5xx` eine weitere Chance, während ein `422` jedes Mal gleich scheitert, bis du die Input-Namen korrigierst.

Richte den Webhook von Framer dann auf die URL des Workers statt auf den Endpunkt, mit eingetragenem Secret.

> Jeder Post kommt jetzt von deinem Worker. Die serverseitigen Versionen senden mit einem Secret Key, also überspringt Ikiform **Allowed domains** und seine Menschlichkeitsprüfung. Jeder Post kommt dann von der IP deines Servers, und das Standard-Limit von 5 pro Minute pro Besucher zählt alle deine Besucher zusammen. Wähle für ein Formular, das du über einen Server sendest, das [Rate-Limit](https://ikiform.com/de/docs/rate-limits.md) Relaxed oder Custom und halte `IKIFORM_SECRET_KEY` in Umgebungsvariablen, die nur der Server sieht.

## Option 3: das Formular von Framer weglassen

Eine Code-Komponente rendert ein echtes Formular und sendet aus dem Browser des Besuchers, sodass Origin-Prüfungen, der Honeypot und Rate-Limits pro Besucher wie auf jeder Site funktionieren. Du verlierst für dieses Formular die visuelle Formularbearbeitung von Framer. Die [Framer-Anleitung der Doku](https://ikiform.com/de/docs/guides/framer.md#code-component) enthält die Komponente.

## Prüfen, dass es auf Framer funktioniert

1. Veröffentliche die Framer-Site und sende das Formular dort ab, nicht in der Vorschau des Editors.
2. Öffne **Submissions** im Dashboard. Die neue Einsendung ist da, mit jedem Feld, das du gesendet hast.
3. Prüfe, dass die Feldnamen genau zu deinen Input-Namen passen, ohne von Framer ergänzte Keys.
4. Für das Relay: Sende einen Request mit einer erfundenen `Framer-Signature` an den Worker und prüfe, dass er mit `401` antwortet.
5. Für das Relay: In den Details der Einsendung ist der Origin leer und der Status received, nicht spam.
6. Prüfe das Postfach jedes Benachrichtigungsempfängers. Jeder bekommt eine E-Mail mit den Feldern, und **Reply** geht an den Absender, wenn das Formular ein `email`-Feld hat.
7. Wenn du einen Webhook hinzugefügt hast, öffne den Endpunkt unter **Webhooks**. Die Zustellung zeigt `succeeded` mit der Antwort deines Servers.

## Stolperfallen

| Problem | Was zu tun ist |
| --- | --- |
| Jeder Webhook-Post liegt mit `origin_mismatch` im Spam | **Allowed domains** ist gesetzt, während Framer direkt sendet. Leere die Liste oder setze das Relay dazwischen. |
| Der Worker antwortet auf echte Posts mit `401` | Das Secret unterscheidet sich zwischen Framer und Worker, oder etwas hat den Body als Text gelesen und verändert. Füge das Secret erneut ein und hashe die rohen Bytes. |
| `429 rate_limited` während eines Launches | Alle Posts teilen sich die Adressen von Framer oder Cloudflare. Wähle **Relaxed** oder ein Custom-Limit. |
| `422 validation_failed` | Der Post passt nicht zur Felddefinition des Formulars. `error.fields` nennt jedes Feld und den Grund. Gleiche den `name` des Eingabefelds an die Feld-ID an. |
| `403 challenge_required` | Die Spamprüfung des Formulars steht auf **Ikiform**, und ein `fetch`-Post hatte kein Token. Hol dir vor jedem Absenden eins mit `challenge(formId)` aus `@ikiform/sdk` oder schalte die Prüfung aus. |

## Fragen

### Brauche ich ein Formular-Backend für Framer-Formulare?

Nicht immer. Framer sendet Einsendungen selbst an E-Mail, Google Sheets oder einen Webhook. Ergänze Ikiform, wenn du ein gespeichertes, gefiltertes Archiv, serverseitige Validierung, Team-Benachrichtigungen mit Reply-to oder mehrere wiederholte Webhooks aus einem Formular willst.

### Verifiziert Ikiform die Webhook-Signatur von Framer?

Nein. Ikiform authentifiziert Posts über den Origin oder deinen geheimen API-Key, nicht über den Header von Framer. Um Framer-Signature zu prüfen, setze ein kleines Relay zwischen Framer und Ikiform, das sie verifiziert und mit deinem Secret Key weiterleitet.

### Warum werden meine Framer-Einsendungen als Spam markiert?

Meist, weil Allowed domains gesetzt ist. Die Webhook-Posts von Framer kommen von seinen Servern ohne Origin-Header, passen also zu keiner Domain. Leere die Liste oder nutze ein Relay, das mit deinem Secret Key sendet.

### Erzeugen die Wiederholungen von Framer doppelte Einsendungen?

Beim direkten Senden schon, wenn eine Zustellung wiederholt wird, nachdem Ikiform sie gespeichert hat. Das Relay sendet die Einsendungs-ID von Framer als Idempotency Key, sodass eine Wiederholung stattdessen die erste Antwort wiedergibt.

### Kann das Formular Datei-Uploads annehmen?

Noch nicht. Ein Post mit einer Datei wird mit 422 files_not_supported abgelehnt. Bitte stattdessen um einen Link zur Datei, etwa die URL eines geteilten Laufwerks.

## Weitere Anleitungen

- [Grenzen von Baukasten-Formularen](https://ikiform.com/de/guides/website-builder-forms.md): Wenn Formulare in Webflow, Netlify, Carrd oder Framer an ein Limit oder eine fehlende Funktion stoßen, behalte dein Formular und richte es auf ein Formular-Backend aus.
- [Webflow-Einsendungslimit](https://ikiform.com/de/guides/website-builder-forms/webflow-submission-limit.md): Der kostenlose Starter-Tarif von Webflow hört nach 50 Formulareinsendungen pro Site auf zu sammeln, und exportierte Sites bekommen gar keine. Richte den Form Block deshalb auf Ikiform aus.
- [Carrd-Formulare](https://ikiform.com/de/guides/website-builder-forms/carrd-forms.md): Das Kontaktformular von Carrd schickt dir nur E-Mails, und eigene Formulare brauchen Pro Plus. Nutze deshalb Send to URL in Plus oder ein HTML-Embed in Standard, um jede Einsendung zu speichern.
- [Netlify-Forms-Limit](https://ikiform.com/de/guides/website-builder-forms/netlify-forms-limit.md): Legacy-Tarife von Netlify messen Formulareinsendungen pro Site und stufen dich automatisch hoch, und Credit-Tarife können die Site pausieren. Verlege das Formular deshalb auf ein Backend.
