Formularz kontaktowy AJAX
Te same pola kontaktu, wysłane przez fetch jako JSON. Odwiedzający zostaje na stronie i widzi krótki status.
Co kopiujesz
Ten szablon wysyła te same pola kontaktowe przez fetch, więc odwiedzający zostaje na twojej stronie i czyta krótki status.
Formularz i tak ma akcję oraz metodę POST. Gdy JavaScript się nie wykona, przeglądarka robi zwykłe wysłanie.
Ta ścieżka zapasowa ma znaczenie dla starszych przeglądarek i dla osób, które blokują skrypty. Nie utrzymujesz dwóch formularzy.
Główny fragment wysyła JSON. Ustawia Content-Type na application/json i Accept na application/json.
Sukces to wartość logiczna success w JSON. Gdy jest true, fragment pokazuje komunikat odpowiedzi albo krótkie podziękowanie i czyści formularz.
Gdy jest false, fragment pokazuje komunikat odpowiedzi. Formgong pisze ten komunikat w języku z pola _lang.
JSON i FormData
Treść JSON musi wymienić pola, które chcesz wysłać. Fragment zawiera access_key, _lang, name, email, phone, message i botcheck.
Jeśli później odkomentujesz Turnstile, ścieżka JSON kopiuje też cf-turnstile-response, gdy to pole ma wartość.
Dodatkowy fragment używa FormData zamiast JSON. Typ treści, razem z boundary, ustawia przeglądarka. Sam nie ustawiaj Content-Type.
FormData zbiera każde pole formularza, także token Turnstile, jeśli widżet stoi wewnątrz formularza.
Obie ścieżki wysyłają Accept: application/json. Bez tego nagłówka zwykłe wysłanie z przeglądarki dostaje stronę podziękowania, a nie JSON.
Nie wysyłaj naraz treści JSON i treści multipart. Wybierz jedno. Dwa fragmenty to alternatywy, a nie warstwy.
Spam, Telegram i limity
Zostaw honeypot o nazwie botcheck pusty i poza ekranem, z tabindex -1. Wypełniony honeypot jest zapisywany jako spam i nie jest dostarczany.
Nazwy pól zostaw krótkie, żeby Telegram mógł wypisać je pogrubieniem. Nie zmieniaj email na długie zdanie.
Klucz dostępu zostaje na stronie. Przeniesienie go do sekretu na serwerze nie czyni formularza bezpieczniejszym, a ten fragment nie ma serwera.
W darmowym planie Telegram przychodzi od razu, a e-mail jest dziennym przeglądem. Skrzynka trzyma zgłoszenia przez 30 dni.
Darmowy plan obejmuje 300 zgłoszeń miesięcznie. Zgłoszenie ze spamem nie zużywa jednego z nich.
Ten podgląd nic nie wysyła. Podepnij fragment na swojej stronie, a potem wyślij test z tamtej strony.
Usługę prowadzi Formgong. W sprawie produktu napisz na support@formgong.com.
Podgląd
Kod formularza
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="pl">
<label>Imię <input type="text" name="name" autocomplete="name" required></label>
<label>E-mail <input type="email" name="email" autocomplete="email" required></label>
<label>Telefon <input type="tel" name="phone" autocomplete="tel"></label>
<label>Wiadomość <textarea name="message" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Pozostaw to pole puste <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<!--
Opcjonalnie. Włącz Turnstile dla tego formularza, usuń te znaczniki komentarza i wklej klucz witryny.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="pl"></div>
-->
<button type="submit">Wyślij</button>
<p data-status role="status"></p>
</form>
<script>
(function () {
var form = document.getElementById("fg-ajax");
if (!form) return;
var status = form.querySelector("[data-status]");
form.addEventListener("submit", function (event) {
event.preventDefault();
var data = {
access_key: form.access_key.value,
_lang: form._lang.value,
name: form.name.value,
email: form.email.value,
phone: form.phone.value,
message: form.message.value,
botcheck: form.botcheck.value
};
var token = form.querySelector('[name="cf-turnstile-response"]');
if (token && token.value) data["cf-turnstile-response"] = token.value;
var body = JSON.stringify(data);
fetch("https://formgong.com/submit", {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: body
}).then(function (res) { return res.json(); }).then(function (result) {
if (status) status.textContent = result && result.success ? (result.message || "Wysłano. Dziękujemy!") : ((result && result.message) || "Nie udało się wysłać. Spróbuj ponownie.");
if (result && result.success) form.reset();
}).catch(function () {
if (status) status.textContent = "Nie udało się wysłać. Spróbuj ponownie.";
});
});
})();
</script>Ten sam formularz z FormData zamiast JSON
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="pl">
<label>Imię <input type="text" name="name" autocomplete="name" required></label>
<label>E-mail <input type="email" name="email" autocomplete="email" required></label>
<label>Telefon <input type="tel" name="phone" autocomplete="tel"></label>
<label>Wiadomość <textarea name="message" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>Pozostaw to pole puste <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<!--
Opcjonalnie. Włącz Turnstile dla tego formularza, usuń te znaczniki komentarza i wklej klucz witryny.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="pl"></div>
-->
<button type="submit">Wyślij</button>
<p data-status role="status"></p>
</form>
<script>
(function () {
var form = document.getElementById("fg-ajax");
if (!form) return;
var status = form.querySelector("[data-status]");
form.addEventListener("submit", function (event) {
event.preventDefault();
var body = new FormData(form);
fetch("https://formgong.com/submit", {
method: "POST",
headers: { Accept: "application/json" },
body: body
}).then(function (res) { return res.json(); }).then(function (result) {
if (status) status.textContent = result && result.success ? (result.message || "Wysłano. Dziękujemy!") : ((result && result.message) || "Nie udało się wysłać. Spróbuj ponownie.");
if (result && result.success) form.reset();
}).catch(function () {
if (status) status.textContent = "Nie udało się wysłać. Spróbuj ponownie.";
});
});
})();
</script>Pytania i odpowiedzi
Dlaczego formularz nadal ma adres akcji?
Żeby wysłanie działało, gdy JavaScript jest wyłączony. Skrypt wywołuje preventDefault tylko wtedy, gdy sam się wykonuje.
Wysyłać JSON czy FormData?
Oba warianty są poprawne. JSON wprost wymienia każde pole. FormData jest krótszy, gdy później dodajesz pola, bo czyta formularz.
Linia statusu zostaje pusta. Co zawiodło?
Sprawdź, czy Accept ma wartość application/json, czy klucz dostępu pasuje do twojego formularza i czy strona jest serwowana przez http albo https, a nie jako plik lokalny.
Czy ten formularz może wysłać plik?
W tym szablonie nie. Pola plików wymagają włączonych załączników i ważnego tokenu Turnstile. To ustawienie jest opisane w dokumentacji panelu.