# Framer

> Envoyez un formulaire Framer vers Ikiform via sa destination webhook sans code, ou affichez votre propre formulaire avec un code component qui envoie depuis le navigateur.

Les formulaires Framer ne peuvent pas envoyer vers une URL d'action externe, mais ils peuvent envoyer chaque soumission à un webhook. Cela donne deux options : garder le formulaire de Framer et ajouter Ikiform comme webhook, ou ajouter un petit code component qui envoie depuis le navigateur du visiteur.

|   | Formulaire Framer avec un webhook | Code component |
| --- | --- | --- |
| Qui envoie | Les serveurs de Framer | Le navigateur du visiteur |
| Code | Aucun | Un fichier React |
| Domaines autorisés | À laisser vide : les envois serveur n'ont pas d'`Origin` | Comparés à votre domaine Framer |
| Honeypot | Non disponible | Inclus |
| Limites de débit comptées par | Les adresses des serveurs de Framer | Chaque visiteur |
| Contrôle anti-spam Ikiform | À laisser désactivé | À laisser désactivé |

## Formulaire Framer avec un webhook

### Étape 1 : Nommez les inputs

Framer envoie du JSON avec le nom de chaque input comme clé, donc les noms donnés aux inputs deviennent les noms de champs dans Ikiform. Utilisez des ids en minuscules comme `email` et `message`, et faites-les correspondre à votre [définition de champs](https://ikiform.com/fr/docs/fields.md) si vous en avez une.

### Étape 2 : Ajoutez Ikiform comme webhook

Sélectionnez le formulaire sur le canevas. À côté de **Send To** dans la barre latérale droite, choisissez **Add…** > **Webhook** et collez votre endpoint. Framer exige une URL `https://`, ce qu'est déjà l'endpoint.

`URL du webhook`:

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

Framer peut signer les requêtes avec un secret. Ikiform ne vérifie pas l'en-tête `Framer-Signature`, donc le secret est facultatif ici.

### Étape 3 : Ajustez les paramètres du formulaire Ikiform

- Laissez **Allowed domains** vide. Framer envoie depuis ses serveurs sans en-tête `Origin`, donc avec des domaines définis, chaque envoi est marqué comme spam avec `origin_mismatch`, ou refusé avec **Reject**.
- Laissez le contrôle anti-spam désactivé. Un envoi JSON sans token reçoit `403 challenge_required`, et Framer n'a aucun moyen d'exécuter la vérification.
- Choisissez la [limite de débit](https://ikiform.com/fr/docs/rate-limits.md) **Relaxed**. Ikiform compte les envois par adresse IP et par formulaire, et chaque envoi vient des serveurs de Framer plutôt que de vos visiteurs.

Framer considère toute réponse autre que `2xx` comme un échec et réessaie jusqu'à 5 fois. Ikiform répond `201` une fois la soumission stockée. Un envoi refusé par Ikiform, comme `422 validation_failed`, échoue de la même façon à chaque tentative : corrigez la cause au lieu d'attendre.

## Code component

Un code component affiche un vrai formulaire sur votre page : c'est donc le navigateur qui l'envoie, et Ikiform voit votre site comme origine. Dans le panneau **Assets**, ouvrez **Code**, créez un fichier de code et collez :

`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." },
});
```

- Faites glisser le composant sur la page et renseignez **Form ID** dans le panneau des propriétés. Stylez les inputs en modifiant `field`, ou remplacez les éléments par les vôtres.
- `Accept: application/json` fait répondre Ikiform en JSON, pour que le composant puisse afficher le résultat sur place.
- Le composant envoie avec `fetch`, alors laissez le contrôle anti-spam du formulaire désactivé. Le honeypot et le score de spam restent actifs.

> Vous pouvez aussi coller l'[intégration pour créateurs de sites](https://ikiform.com/fr/docs/guides/site-builders.md#embed) dans la section **HTML** d'un composant **Embed**. Si Framer la place dans une frame, les pages de remerciement et d'erreur d'Ikiform ne s'y chargeront pas, c'est pourquoi l'intégration utilise `target="_top"`. Le code component évite complètement les frames.

## Domaines autorisés

Ceci ne concerne que le code component et l'intégration. Laissez les domaines autorisés vides pour le webhook.

| Où tourne le formulaire | À ajouter aux domaines autorisés |
| --- | --- |
| Sous-domaine Framer | `your-project.framer.app`, ou `your-project.framer.website` pour les projets plus anciens |
| Domaine personnalisé | `example.com`, qui couvre aussi `www.example.com` |
| L'aperçu de l'éditeur Framer | Rien. Testez plutôt sur le site publié. |

- N'ajoutez jamais `framer.app` ou `framer.website` seul. Tous les sites de cet hébergeur correspondraient, y compris ceux des autres.

## Checklist de test

1. Publiez le site. Framer n'envoie de webhooks que pour les formulaires du site publié.
2. Envoyez le formulaire et vérifiez la soumission dans Ikiform. Avec le webhook, les champs doivent correspondre exactement aux noms de vos inputs.
3. Pour le code component, activez les domaines autorisés, envoyez depuis le domaine publié et vérifiez que l'envoi n'est pas marqué comme spam.

## Dépannage

| Ce que vous voyez | Pourquoi | Solution |
| --- | --- | --- |
| Chaque soumission par webhook est dans le spam avec `origin_mismatch` | **Allowed domains** est défini, et les envois serveur de Framer n'ont pas d'origine | Videz les domaines autorisés de ce formulaire, ou passez au code component. |
| Framer signale des livraisons de webhook échouées | Ikiform a refusé l'envoi : `403 challenge_required`, `403 origin_not_allowed` ou `422 validation_failed` | Désactivez le contrôle anti-spam, videz les domaines autorisés et faites correspondre les noms des inputs à vos champs. |
| `429 rate_limited` sur un formulaire très actif | Les envois depuis les serveurs de Framer partagent un petit nombre d'adresses IP | Choisissez **Relaxed**, ou une limite Custom. |
| Le composant indique qu'il n'a pas pu joindre le serveur | Un bloqueur de publicités ou une extension de confidentialité a bloqué la requête, ou **Form ID** est vide | Essayez une fenêtre de navigation privée et vérifiez que la propriété est renseignée. |
| Les soumissions arrivent dans le filtre spam avec `origin_mismatch` | La page qui a envoyé ne fait pas partie des domaines autorisés du formulaire | Ajoutez l'hôte du tableau ci-dessus. Avec **Reject**, les mêmes envois reçoivent plutôt `403 origin_not_allowed`. |

## Voir aussi

- [React](https://ikiform.com/fr/docs/guides/react.md): États d'attente, d'erreur et de succès.
- [Créateurs de sites](https://ikiform.com/fr/docs/guides/site-builders.md): L'intégration qui fonctionne dans n'importe quel créateur de sites.
- [Limites de débit](https://ikiform.com/fr/docs/rate-limits.md): Les préréglages et leur recharge.
- [Protection anti-spam](https://ikiform.com/fr/docs/spam.md): Honeypot, score et vérification humaine.
