# Twój formularz na własnej stronie

> Wstaw formularz zapisu Zanfii na dowolną stronę (WordPress, Webflow, zwykły HTML) z własnym kodem i stylami: kontrakt natywnego formularza, skrypt, payload i kody błędów.

Source: https://zanfia.com/pl/help/developer-api/forms-embed · Updated: 2026-09-23 · Id: developer-api.forms-embed

Formularz zapisu Zanfii nie musi być na stronie w Zanfii ani w iframe. Ten sam natywny formularz, którego używają strony Zanfii, działa na każdej stronie, którą hostujesz sam: Ty piszesz HTML i style, jeden skrypt podpina formularz do Twojego workspace'u, a tagi, tryb opt-in i przekierowanie na stronę podziękowania biorą się z ustawień formularza.

### 1. Pobierz snippet

Najszybciej przez CLI, które drukuje gotowy kod dla formularza:

```bash
zanfia forms snippet <formId> --lang pl --first-name
```

Albo napisz go ręcznie. Minimum to formularz oznaczony id workspace'u i id formularza, pole e-mail, przycisk wysyłki i skrypt:

```html
<form data-zanfia-form="{workspaceId}/{formId}">
  <label>Adres e-mail<br /><input name="email" type="email" required autocomplete="email" /></label>
  <input name="website" type="text" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px;opacity:0" />
  <button type="submit">Zapisuję się</button>
  <div data-zanfia-success hidden>Dziękujemy! Sprawdź skrzynkę i potwierdź zapis.</div>
  <div data-zanfia-error hidden>Nie udało się wysłać. Spróbuj ponownie.</div>
</form>
<script src="https://zanfia.co/zanfia-page-forms.js" defer></script>
```

Id workspace'u znajdziesz w `GET /workspace` (albo `zanfia workspace get`), id formularza w `GET /forms` (albo `zanfia forms list`).

### 2. Kontrakt

Skrypt szuka na stronie każdego `form[data-zanfia-form]` i przejmuje jego wysyłkę. Cała reszta formularza należy do Ciebie: znaczniki, klasy, układ, CSS.

| Element                                   | Wymagany | Co robi                                                                                                                                  |
| ----------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `data-zanfia-form="{workspaceId}/{formId}"` | tak      | Który formularz przyjmuje zapis.                                                                                                         |
| `input[name="email"]`                     | tak      | Adres. Pusty adres = formularz nic nie robi.                                                                                             |
| `input[name="firstName"]`                 | nie      | Zapisywane na kliencie.                                                                                                                  |
| `input[name="trackingConsent"]` (checkbox) | nie      | Zgoda na śledzenie zaangażowania. Tylko zaznaczony checkbox ją nadaje.                                                                   |
| `input[name="website"]`                   | nie      | Honeypot. Trzymaj go ukrytego wizualnie; wypełniona wartość oznacza bota i nic nie jest wysyłane.                                        |
| `button[type="submit"]`                   | tak      | Dostaje `aria-busy="true"` i jest wyłączony na czas żądania.                                                                             |
| `[data-zanfia-success]`                   | nie      | Pokazywany po udanym zapisie, gdy nie ma przekierowania; pola są wyłączane, przycisk ukrywany.                                           |
| `[data-zanfia-error]`                     | nie      | Pokazywany, gdy żądanie się nie uda; przycisk wraca do użycia.                                                                           |
| `data-zanfia-redirect="url"` (na formularzu) | nie      | Po udanym zapisie przenosi na ten adres zamiast pokazywać stan sukcesu. Bez atrybutu `redirectUrl` z ustawień formularza NIE jest tu stosowany; dodaj atrybut, gdy chcesz przekierowania. |

Skrypt wysyła na origin, z którego został załadowany (`https://zanfia.co`), nigdy na Twoją domenę, więc niczego nie trzeba proxować. Endpoint odpowiada na preflight przeglądarki i przyjmuje każdy origin: wywołanie jest anonimowe, nie niesie ciasteczek, a id w kodzie strony i tak są publiczne. Nadużycia ogranicza limit na IP po stronie platformy.

### 3. Co jest wysyłane

`POST https://zanfia.co/api/submitForm` z ciałem JSON:

```json
{
  "workspaceId": "work_…",
  "formId": "form_…",
  "email": "czytelnik@example.com",
  "firstName": "Anna",
  "trackingConsent": false,
  "language": "pl"
}
```

`language` to `<html lang>` strony (albo język przeglądarki) i wybiera język e-maila potwierdzającego. `200` oznacza zapisane zgłoszenie. Przy double opt-in subskrypcja, tagi i zgoda zaczynają obowiązywać dopiero po potwierdzeniu z e-maila; single opt-in subskrybuje od razu.

Inne odpowiedzi: `400` niepoprawny payload (format e-maila, nieznany formularz), `404` brak formularza, `429` za dużo żądań z jednego IP, `5xx` błąd platformy. Skrypt traktuje wszystko poza `2xx` jako błąd.

### 4. Po zapisie

- **Strona podziękowania.** Dodaj `data-zanfia-redirect` na formularzu, żeby przenieść czytelnika na własną stronę. Skrypt zapisuje też adres w `sessionStorage`, więc druga strona z `data-zanfia-phone-form` (krok z przypomnieniem SMS) może dopiąć numer telefonu do tego samego zapisu.
- **Piksele.** Po udanym zapisie skrypt wysyła na `window` zdarzenie `zanfia:form-submitted` z `{ workspaceId, formId }`, więc własne śledzenie może odpalić lead.
- **E-mail potwierdzający.** Nazwa nadawcy i temat biorą się z ustawień e-maila potwierdzającego formularza (`forms update --confirmation-subject …` albo pełna treść przez `confirmationEmailOverride`).

### 5. Sesje webinaru

Formularz podpięty do pokoju na żywo z cyklicznymi sesjami może pokazać wybór terminu. Dodaj `data-zanfia-sessions="{workspaceId}/{roomId}"` na formularzu; skrypt pobierze najbliższe sesje z platformy i wstawi select przed przyciskiem wysyłki.
