# Webflow

> 커스텀 action으로 Webflow Form Block을 Ikiform에 보내고, 짧은 스크립트로 Webflow의 성공 및 오류 상태를 유지하고, webflow.io 스테이징 사이트를 허용하세요.

Webflow의 Form Block은 어떤 URL로든 POST할 수 있습니다. action을 Ikiform 엔드포인트로 지정하면, Designer에서 만든 레이아웃과 스타일은 그대로 유지되고 Ikiform이 검증, 스팸 필터링, 저장, 이메일, 웹훅 전송을 맡습니다.

## 커스텀 action으로 달라지는 점

- Webflow는 자신이 목적지일 때만 폼을 처리합니다. 커스텀 action을 쓰면 브라우저가 Ikiform으로 바로 POST하므로, 제출이 Webflow의 폼 제출 목록에 나타나지 않고 Webflow는 알림 이메일을 보내지 않습니다.
- Webflow 자체 목적지는 커스텀 action과 함께 실행할 수 없습니다. Ikiform을 추가하기 전에 **Send to**에서 제거하세요.
- Webflow가 결과를 알 수 없으므로 Webflow의 성공 및 오류 블록(`.w-form-done`, `.w-form-fail`)과 폼 자체의 리디렉션 설정은 작동하지 않습니다. 방문자는 Ikiform의 감사 페이지나 **Redirect after submit** URL로 이동합니다. [4단계](#keep-success-state)에서 Webflow의 블록을 되살립니다.

## 폼 설정하기

### 1단계: 폼을 Ikiform으로 연결하기

Form Block 안의 폼을 선택하고 **Settings** 패널을 여세요. **Send to**에서 커스텀 action을 고르고, **Action**에 엔드포인트를 붙여 넣고, **Method**를 **POST**로 설정하세요.

`Action`:

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

메서드를 GET으로 두면 브라우저가 엔드포인트를 페이지로 열어 `404 not_found`로 응답합니다. Ikiform은 POST만 받습니다.

### 2단계: 필드 이름 정하기

각 입력의 **Name** 설정이 Ikiform의 필드 이름이 됩니다. Webflow는 레이블로 이 값을 채우므로 `Name`, `Email`, `Field 2` 같은 이름이 생깁니다. `name`, `email`, `message`처럼 원하는 ID로 바꾸세요.

- Ikiform 폼에 [필드](https://ikiform.com/ko/docs/fields.md)를 정의했다면 이름이 ID와 정확히 일치해야 합니다. ID는 소문자 snake_case이므로 `Email`과 `email`은 서로 다른 필드입니다.
- 폼에서 reCAPTCHA 요소를 모두 제거하세요. Ikiform은 이를 검증하지 않으며, `g-recaptcha-response` 값이 추가 필드로 도착합니다. 대신 Ikiform의 [스팸 검사](https://ikiform.com/ko/docs/spam.md#human-check)를 사용하세요.

### 3단계: 허니팟 추가하기

폼에 Input을 추가하고 **Name**을 `_gotcha`로 설정한 뒤, Style 패널에서 **Display: none**으로 숨기세요. **Custom attributes**에 `tabindex`를 `-1`로, `autocomplete`를 `off`로 추가하면 키보드와 비밀번호 관리자가 건너뜁니다. 유료 사이트 플랜이라면 대신 폼 안의 Code Embed에 다음을 붙여 넣을 수 있습니다.

`Code Embed`:

```html
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
```

### 4단계: 제출 후 동작 정하기

가장 간단한 방법은 감사 페이지입니다. Webflow에서 페이지를 만들어 게시하고, 그 전체 URL을 Ikiform 폼 설정의 **Redirect after submit**에 붙여 넣으세요.

### Webflow의 성공 및 오류 블록 유지하기

페이지에 머물려면 `fetch`로 POST하고 Webflow의 블록을 직접 전환하세요. 다음 코드를 **Page settings** > **Custom code** > **Before </body> tag**에 붙여 넣거나, 모든 폼에 적용하려면 사이트의 푸터 코드에 붙여 넣으세요. 오류 블록 안에 Ikiform의 오류 메시지를 보여 주고, 보내는 동안 버튼의 **Waiting text**를 사용합니다.

`Before </body> tag`:

```html
<script>
  document.querySelectorAll('form[action^="https://ikiform.com/f/"]').forEach((form) => {
    const wrapper = form.closest(".w-form");
    const done = wrapper?.querySelector(".w-form-done");
    const fail = wrapper?.querySelector(".w-form-fail");
    const button = form.querySelector('[type="submit"]');

    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const label = button?.value;
      if (button) {
        button.disabled = true;
        button.value = button.dataset.wait || label;
      }
      try {
        const response = await fetch(form.action, {
          method: "POST",
          headers: { Accept: "application/json" },
          body: new FormData(form),
        });
        const result = await response.json();
        if (result.ok) {
          form.style.display = "none";
          if (fail) fail.style.display = "none";
          if (done) done.style.display = "block";
          return;
        }
        const text = fail?.querySelector("div") ?? fail;
        if (text) text.textContent = result.error.message;
        if (fail) fail.style.display = "block";
      } catch {
        if (fail) fail.style.display = "block";
      } finally {
        if (button) {
          button.disabled = false;
          button.value = label;
        }
      }
    });
  });
</script>
```

> 커스텀 코드와 Code Embed 요소에는 유료 사이트 플랜이나 Workspace 플랜이 필요하며, 둘 다 Designer에서는 실행되지 않습니다. 게시해서 작동을 확인하세요.

스크립트는 `fetch`로 POST하므로, 스팸 검사가 **Ikiform**으로 설정된 폼은 확인 페이지를 보여 주는 대신 `403 challenge_required`로 응답합니다. 확인을 끈 상태에서 스크립트를 쓰거나, 스크립트 없이 브라우저가 평소처럼 POST하게 두세요. 그러면 추가 코드 없이 확인이 실행됩니다.

## 허용 도메인

허용 도메인을 설정한다면 폼이 게시되는 모든 주소를 등록하세요. 등록한 도메인의 하위 도메인은 이미 일치합니다.

| 폼이 실행되는 곳 | Allowed domains에 추가할 값 |
| --- | --- |
| 여러분의 커스텀 도메인 | `example.com`, `www.example.com`도 포함 |
| Webflow 스테이징 | `your-site.webflow.io` |
| Designer 캔버스 | 없음. 커스텀 action과 커스텀 코드는 그곳에서 실행되지 않습니다. |

- `webflow.io`만 단독으로 추가하지 마세요. 다른 사람의 사이트를 포함해 그 호스트의 모든 사이트가 일치하게 됩니다.

## 테스트 체크리스트

1. `webflow.io` 스테이징 도메인에 게시하세요. 커스텀 action을 쓰는 폼은 게시된 사이트에서만 POST합니다.
2. 폼을 제출하고 Ikiform에서 폼의 제출을 여세요. 새 제출이 스팸이 아니라 수신 목록에 있어야 합니다.
3. 필드 이름이 2단계에서 설정한 것과 일치하는지, 허니팟이 목록에 없는지 확인하세요. `_`로 시작하는 이름은 저장되지 않습니다.
4. 감사 페이지로 이동하는지, 또는 스크립트를 추가했다면 Webflow의 성공 블록이 보이는지 확인하세요.
5. 커스텀 도메인에 게시하고 그곳에서 한 번 더 제출하세요.

## 문제 해결

| 증상 | 원인 | 해결 |
| --- | --- | --- |
| 제출 후 `404 not_found` 페이지 | **Method**가 GET이라 브라우저가 엔드포인트를 링크처럼 엶 | **Method**를 **POST**로 설정하고 다시 게시하세요. |
| Webflow의 성공 메시지 대신 Ikiform의 감사 페이지가 나옴 | Webflow의 성공 블록은 Webflow가 폼을 처리할 때만 실행됨 | **Redirect after submit**을 설정하거나 4단계의 스크립트를 추가하세요. |
| 제출이 `origin_mismatch`와 함께 스팸 필터에 들어감 | POST한 페이지가 폼의 허용 도메인에 없음 | 위 표의 호스트를 추가하세요. **Reject**를 골랐다면 같은 POST가 대신 `403 origin_not_allowed`를 받습니다. |
| Unknown field가 표시된 `422 validation_failed` | `Email`이나 `g-recaptcha-response` 같은 필드 이름이 폼의 필드 정의에 없음 | 입력 이름을 필드 ID로 바꾸거나 reCAPTCHA 요소를 제거하세요. |
| 스크립트가 아무것도 하지 않음 | Designer에서 테스트 중이거나, 사이트에 유료 플랜이 없거나, action이 `https://ikiform.com/f/`로 시작하지 않음 | 게시된 사이트에서 테스트하고 **Action**에 공백이 없는지 확인하세요. |
| 오류 블록에 `Complete the human check, then send the form again.`가 표시됨 | 스팸 검사가 **Ikiform**으로 설정되어 있고 스크립트가 `fetch`로 POST함 | 이 폼의 확인을 끄거나 스크립트를 제거하세요. |

## 관련 문서

- [사이트 빌더](https://ikiform.com/ko/docs/guides/site-builders.md): 어떤 빌더에서든 작동하는 임베드.
- [HTML 폼](https://ikiform.com/ko/docs/html.md): 리디렉션, 예약 필드, 허니팟.
- [허용 도메인](https://ikiform.com/ko/docs/spam.md#allowed-domains): 출처를 비교하는 방식과 불일치 시 동작.
- [오류](https://ikiform.com/ko/docs/errors.md): 모든 오류 코드와 원인, 해결 방법.
