# Framer

> Envie um formulário do Framer para o Ikiform pelo destino de webhook dele, sem código, ou renderize seu próprio formulário com um code component que envia do navegador.

Formulários do Framer não conseguem enviar para uma URL de action externa, mas conseguem mandar cada envio para um webhook. Isso abre dois caminhos: manter o formulário do Framer e adicionar o Ikiform como webhook dele, ou usar um pequeno code component que envia do navegador do visitante.

|   | Formulário do Framer com webhook | Code component |
| --- | --- | --- |
| Quem faz o envio | Os servidores do Framer | O navegador do visitante |
| Código | Nenhum | Um arquivo React |
| Domínios permitidos | Deixe vazio: envios de servidor não têm `Origin` | Comparados ao seu domínio do Framer |
| Honeypot | Não disponível | Incluso |
| Os limites de taxa contam | Os endereços dos servidores do Framer | Cada visitante |
| Verificação de spam do Ikiform | Deixe desativada | Deixe desativada |

## Formulário do Framer com webhook

### Passo 1: Dê nome aos inputs

O Framer envia JSON com o nome de cada input como chave, então os nomes que você dá aos inputs viram os nomes dos campos no Ikiform. Use ids em minúsculas como `email` e `message`, e siga a sua [definição de campos](https://ikiform.com/pt-br/docs/fields.md), se tiver uma.

### Passo 2: Adicione o Ikiform como webhook

Selecione o formulário no canvas. Ao lado de **Send To**, na barra lateral direita, escolha **Add…** > **Webhook** e cole o seu endpoint. O Framer exige uma URL `https://`, e o endpoint já é uma.

`URL do webhook`:

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

O Framer pode assinar as requisições com um segredo. O Ikiform não verifica o header `Framer-Signature`, então o segredo é opcional aqui.

### Passo 3: Ajuste as configurações do formulário no Ikiform

- Deixe **Allowed domains** vazio. O Framer envia dos servidores dele sem header `Origin`, então, com domínios definidos, todo envio é marcado como spam com `origin_mismatch`, ou recusado com **Reject**.
- Deixe a verificação de spam desativada. Um envio JSON sem token recebe `403 challenge_required`, e o Framer não tem como rodar a verificação.
- Escolha o [limite de taxa](https://ikiform.com/pt-br/docs/rate-limits.md) **Relaxed**. O Ikiform conta os envios por endereço IP e formulário, e todo envio vem dos servidores do Framer, não dos seus visitantes.

O Framer trata qualquer resposta que não seja `2xx` como falha e tenta de novo até 5 vezes. O Ikiform responde `201` assim que o envio é armazenado. Um envio que o Ikiform rejeita, como `422 validation_failed`, falha do mesmo jeito em toda nova tentativa, então corrija a causa em vez de esperar.

## Code component

Um code component renderiza um formulário de verdade na sua página, então o navegador o envia e o Ikiform vê o seu site como origem. No painel **Assets**, abra **Code**, crie um arquivo de código e cole:

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

- Arraste o componente para a página e defina **Form ID** no painel de propriedades. Estilize os inputs editando `field`, ou troque os elementos pelos seus.
- `Accept: application/json` faz o Ikiform responder com JSON, então o componente pode mostrar o resultado no lugar.
- O componente envia com `fetch`, então deixe a verificação de spam do formulário desativada. O honeypot e a pontuação de spam continuam rodando.

> Você também pode colar o [embed para criadores de sites](https://ikiform.com/pt-br/docs/guides/site-builders.md#embed) na seção **HTML** de um componente **Embed**. Se o Framer o colocar em um frame, as páginas de agradecimento e de erro do Ikiform não carregam dentro dele, e é por isso que o embed usa `target="_top"`. O code component evita frames por completo.

## Domínios permitidos

Isto vale só para o code component e o embed. Deixe os domínios permitidos vazios para o webhook.

| Onde o formulário roda | Adicione em Allowed domains |
| --- | --- |
| Subdomínio do Framer | `your-project.framer.app`, ou `your-project.framer.website` em projetos mais antigos |
| Domínio próprio | `example.com`, que também cobre `www.example.com` |
| O preview do editor do Framer | Nada. Teste no site publicado. |

- Nunca adicione `framer.app` ou `framer.website` sozinhos. Todo site naquele host corresponderia, inclusive os de outras pessoas.

## Checklist de teste

1. Publique o site. O Framer só envia webhooks de formulários do site publicado.
2. Envie o formulário e confira o envio no Ikiform. Com o webhook, os campos devem corresponder exatamente aos nomes dos inputs.
3. Para o code component, ative os domínios permitidos, envie a partir do domínio publicado e confirme que o envio não é marcado como spam.

## Solução de problemas

| O que você vê | Por quê | Correção |
| --- | --- | --- |
| Todo envio via webhook cai em spam com `origin_mismatch` | **Allowed domains** está definido, e os envios do servidor do Framer não têm origem | Limpe os domínios permitidos deste formulário, ou mude para o code component. |
| O Framer informa entregas de webhook com falha | O Ikiform recusou o envio: `403 challenge_required`, `403 origin_not_allowed` ou `422 validation_failed` | Desative a verificação de spam, limpe os domínios permitidos e faça os nomes dos inputs corresponderem aos seus campos. |
| `429 rate_limited` em um formulário movimentado | Os envios dos servidores do Framer compartilham poucos endereços IP | Escolha **Relaxed**, ou um limite Custom. |
| O componente diz que não conseguiu falar com o servidor | Um bloqueador de anúncios ou extensão de privacidade bloqueou a requisição, ou o **Form ID** está vazio | Teste em uma janela anônima e confira se a propriedade está definida. |
| Os envios chegam no filtro de spam com `origin_mismatch` | A página que enviou não está nos domínios permitidos do formulário | Adicione o host da tabela acima. Com **Reject** escolhido, os mesmos envios recebem `403 origin_not_allowed`. |

## Relacionados

- [React](https://ikiform.com/pt-br/docs/guides/react.md): Estados de carregamento, erro e sucesso.
- [Criadores de sites](https://ikiform.com/pt-br/docs/guides/site-builders.md): O embed que funciona em qualquer criador.
- [Limites de taxa](https://ikiform.com/pt-br/docs/rate-limits.md): Presets e como eles se recarregam.
- [Proteção contra spam](https://ikiform.com/pt-br/docs/spam.md): Honeypot, pontuação e a verificação humana.
