Newsletter signup form

Collect email subscribers with a clear opt-in. Only the email is required.

Using Tilda? Paste into a T123 block (paid plan) or use the no-code webhook.

What this form is for

A signup form should ask for as little as possible. Every extra field costs you subscribers, so only the email is required here. A first name lets you greet people, and a topic choice tells you what they want to read.

In the EU you need a clear opt-in for marketing email. The template has its own unticked checkbox for the newsletter, separate from the storage consent, so you can show what each person agreed to.

The fields that matter

Email
The only required field. Use the email input type so phones show the right keyboard.
First name
Optional. Useful for a friendly greeting, but a required name lowers signups.
Topics
Product news, offers or tips. People who pick a topic open more of the emails they get.
Newsletter opt-in
A separate checkbox the person ticks. It is your record of consent.

Preview

Subscription

Consent

Form code

HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Newsletter signup form</title>
<style>
  body { font-family: "Segoe UI", sans-serif; color: #12263a; margin: 0; background: #fff; }
  main { max-width: 640px; margin: 0 auto; padding: 32px 20px 64px; }
  h1 { font-size: 28px; font-weight: 650; letter-spacing: -0.02em; line-height: 1.2; }
  h2 { font-size: 18px; margin: 18px 0 0; }
  p { line-height: 1.5; }
  form { display: grid; gap: 14px; position: relative; }
  .field { display: grid; gap: 6px; }
  label span, .check span { font-size: 14px; }
  input, select, textarea { font: inherit; color: inherit; padding: 10px 12px; border: 1px solid #b4bdce; border-radius: 8px; width: 100%; box-sizing: border-box; background: #fff; }
  textarea { min-height: 96px; }
  .check { display: flex; gap: 8px; align-items: flex-start; }
  .check input { width: auto; margin-top: 4px; }
  button { background: #3c4ad8; color: #fff; border: 0; border-radius: 8px; padding: 12px 18px; font: inherit; cursor: pointer; }
  .note { background: #fff6eb; padding: 12px 14px; border-radius: 8px; }
  form [data-show-if] { display: none; }
</style>
</head>
<body>
<main>
<h1 data-i18n="title">Newsletter signup form</h1>
<p data-i18n="lede">Collect email subscribers with a clear opt-in. Only the email is required.</p>


<form id="fg-form" action="https://formgong.com/submit" method="POST" enctype="multipart/form-data" data-sitekey="" data-lang="en">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="en">
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)"><label>Leave this field empty<input name="botcheck" tabindex="-1" autocomplete="off"></label></div>
<section><h2 data-i18n="section.subscribe">Subscription</h2>
<div class="field"><label for="fg-email"><span data-i18n="email">Email</span></label><input id="fg-email" name="email" type="email" required maxlength="120" autocomplete="email"></div>
<div class="field"><label for="fg-first_name"><span data-i18n="first_name">First name</span></label><input id="fg-first_name" name="first_name" type="text" maxlength="60" autocomplete="name"></div>
<div class="field"><label for="fg-interests"><span data-i18n="interests">What would you like to get?</span></label><select id="fg-interests" name="interests"><option value="">—</option><option value="product_news" data-i18n="interests.product_news">Product news</option><option value="offers" data-i18n="interests.offers">Offers and discounts</option><option value="tips" data-i18n="interests.tips">Tips and guides</option></select></div></section>
<section><h2 data-i18n="section.consent">Consent</h2>
<div class="field"><label class="check"><input id="fg-consent_newsletter" name="consent_newsletter" type="checkbox" value="yes"><span data-i18n="consent_newsletter">Yes, send me the newsletter. I can unsubscribe at any time.</span></label></div></section>
<!-- Set data-sitekey on this form to YOUR_TURNSTILE_SITE_KEY. Required for attachments. -->
<div data-turnstile></div>
<button type="submit" data-i18n="submit">Send</button>
<p data-status role="status"></p>
</form>
</main>
<script type="application/json" id="fg-labels">{"uk":{"title":"Форма підписки на розсилку","lede":"Збирайте підписників з чіткою згодою. Обов’язковий лише email.","submit":"Надіслати","thanks":"Надіслано. Дякуємо.","file_too_big":"До 3 файлів, по 5 MiB, разом до 10 MiB.","error":"Не вдалося надіслати. Спробуйте ще раз.","section.subscribe":"Підписка","email":"Електронна пошта","first_name":"Ім’я","interests":"Що ви хочете отримувати?","interests.product_news":"Новини продукту","interests.offers":"Пропозиції та знижки","interests.tips":"Поради та інструкції","section.consent":"Згода","consent_newsletter":"Так, надсилайте мені розсилку. Я можу відписатися будь-коли."},"en":{"title":"Newsletter signup form","lede":"Collect email subscribers with a clear opt-in. Only the email is required.","submit":"Send","thanks":"Sent. Thank you.","file_too_big":"Up to 3 files, 5 MiB each and 10 MiB combined.","error":"Could not send. Please try again.","section.subscribe":"Subscription","email":"Email","first_name":"First name","interests":"What would you like to get?","interests.product_news":"Product news","interests.offers":"Offers and discounts","interests.tips":"Tips and guides","section.consent":"Consent","consent_newsletter":"Yes, send me the newsletter. I can unsubscribe at any time."},"pl":{"title":"Formularz zapisu do newslettera","lede":"Zbieraj subskrybentów z wyraźną zgodą. Wymagany jest tylko e-mail.","submit":"Wyślij","thanks":"Wysłano. Dziękujemy.","file_too_big":"Do 3 plików, po 5 MiB, łącznie 10 MiB.","error":"Nie udało się wysłać. Spróbuj ponownie.","section.subscribe":"Subskrypcja","email":"E-mail","first_name":"Imię","interests":"Co chcesz otrzymywać?","interests.product_news":"Nowości o produkcie","interests.offers":"Oferty i rabaty","interests.tips":"Porady i poradniki","section.consent":"Zgoda","consent_newsletter":"Tak, wysyłajcie mi newsletter. Mogę się wypisać w każdej chwili."},"tr":{"title":"Bülten kayıt formu","lede":"Açık onayla e-posta abonesi toplayın. Yalnızca e-posta zorunludur.","submit":"Gönder","thanks":"Gönderildi. Teşekkürler.","file_too_big":"En fazla 3 dosya, dosya başına 5 MiB, toplam 10 MiB.","error":"Gönderilemedi. Lütfen tekrar deneyin.","section.subscribe":"Abonelik","email":"E-posta","first_name":"Ad","interests":"Ne almak istersiniz?","interests.product_news":"Ürün haberleri","interests.offers":"Teklifler ve indirimler","interests.tips":"İpuçları ve rehberler","section.consent":"Onay","consent_newsletter":"Evet, bülteni bana gönderin. İstediğim zaman abonelikten çıkabilirim."},"ar":{"title":"نموذج الاشتراك في النشرة البريدية","lede":"اجمع المشتركين بموافقة واضحة. البريد الإلكتروني وحده مطلوب.","submit":"إرسال","thanks":"تم الإرسال. شكرًا لك.","file_too_big":"حتى 3 ملفات، 5 MiB لكل ملف و10 MiB إجمالًا.","error":"تعذّر الإرسال. يُرجى المحاولة مرة أخرى.","section.subscribe":"الاشتراك","email":"البريد الإلكتروني","first_name":"الاسم الأول","interests":"ما الذي تود تلقيه؟","interests.product_news":"أخبار المنتج","interests.offers":"العروض والخصومات","interests.tips":"نصائح وأدلة","section.consent":"الموافقة","consent_newsletter":"نعم، أرسلوا لي النشرة البريدية. يمكنني إلغاء الاشتراك في أي وقت."},"he":{"title":"טופס הרשמה לניוזלטר","lede":"אספו מנויים בהסכמה ברורה. רק האימייל הוא חובה.","submit":"שליחה","thanks":"נשלח. תודה.","file_too_big":"עד 3 קבצים, 5 MiB לכל קובץ ו-10 MiB בסך הכול.","error":"השליחה נכשלה. נסו שוב.","section.subscribe":"מינוי","email":"אימייל","first_name":"שם פרטי","interests":"מה תרצו לקבל?","interests.product_news":"חדשות מוצר","interests.offers":"מבצעים והנחות","interests.tips":"טיפים ומדריכים","section.consent":"הסכמה","consent_newsletter":"כן, שלחו לי את הניוזלטר. אפשר לבטל בכל עת."},"es":{"title":"Formulario de suscripción al boletín","lede":"Reúne suscriptores con un consentimiento claro. Solo el email es obligatorio.","submit":"Enviar","thanks":"Enviado. Gracias.","file_too_big":"Hasta 3 archivos, 5 MiB cada uno y 10 MiB en total.","error":"No se pudo enviar. Inténtalo de nuevo.","section.subscribe":"Suscripción","email":"Correo electrónico","first_name":"Nombre","interests":"¿Qué te gustaría recibir?","interests.product_news":"Novedades del producto","interests.offers":"Ofertas y descuentos","interests.tips":"Consejos y guías","section.consent":"Consentimiento","consent_newsletter":"Sí, envíame el boletín. Puedo darme de baja cuando quiera."},"fr":{"title":"Formulaire d’inscription à la newsletter","lede":"Recueillez des abonnés avec un consentement clair. Seul l’e-mail est obligatoire.","submit":"Envoyer","thanks":"Envoyé. Merci.","file_too_big":"Jusqu’à 3 fichiers, 5 Mio chacun et 10 Mio au total.","error":"Envoi impossible. Veuillez réessayer.","section.subscribe":"Abonnement","email":"E-mail","first_name":"Prénom","interests":"Que souhaitez-vous recevoir ?","interests.product_news":"Actualités produit","interests.offers":"Offres et réductions","interests.tips":"Conseils et guides","section.consent":"Consentement","consent_newsletter":"Oui, envoyez-moi la newsletter. Je peux me désinscrire à tout moment."},"pt":{"title":"Formulário de subscrição da newsletter","lede":"Recolha subscritores com um consentimento claro. Só o email é obrigatório.","submit":"Enviar","thanks":"Enviado. Obrigado.","file_too_big":"Até 3 ficheiros, 5 MiB cada e 10 MiB no total.","error":"Não foi possível enviar. Tente novamente.","section.subscribe":"Subscrição","email":"Email","first_name":"Nome próprio","interests":"O que gostaria de receber?","interests.product_news":"Novidades do produto","interests.offers":"Ofertas e descontos","interests.tips":"Dicas e guias","section.consent":"Consentimento","consent_newsletter":"Sim, enviem-me a newsletter. Posso cancelar a subscrição a qualquer momento."},"hi":{"title":"न्यूज़लेटर साइन-अप फ़ॉर्म","lede":"साफ़ सहमति के साथ ईमेल सब्सक्राइबर जुटाएँ। सिर्फ़ ईमेल ज़रूरी है।","submit":"भेजें","thanks":"भेज दिया गया। धन्यवाद।","file_too_big":"अधिकतम 3 फ़ाइलें, हर फ़ाइल 5 MiB तक और कुल 10 MiB।","error":"भेजा नहीं जा सका। कृपया फिर से कोशिश करें।","section.subscribe":"सब्सक्रिप्शन","email":"ईमेल","first_name":"पहला नाम","interests":"आप क्या पाना चाहेंगे?","interests.product_news":"प्रोडक्ट की ख़बरें","interests.offers":"ऑफ़र और छूट","interests.tips":"टिप्स और गाइड","section.consent":"सहमति","consent_newsletter":"हाँ, मुझे न्यूज़लेटर भेजें। मैं कभी भी अनसब्सक्राइब कर सकता/सकती हूँ।"},"ja":{"title":"ニュースレター登録フォーム","lede":"はっきりした同意のもとで購読者を集めます。必須はメールアドレスだけです。","submit":"送信","thanks":"送信しました。ありがとうございます。","file_too_big":"ファイルは3つまで、1つ5 MiB、合計10 MiBまでです。","error":"送信できませんでした。もう一度お試しください。","section.subscribe":"購読","email":"メールアドレス","first_name":"名","interests":"どんな内容を受け取りたいですか?","interests.product_news":"製品ニュース","interests.offers":"セール・割引情報","interests.tips":"ヒントとガイド","section.consent":"同意","consent_newsletter":"はい、ニュースレターを受け取ります。いつでも配信停止できます。"},"de":{"title":"Newsletter-Anmeldeformular","lede":"Sammeln Sie Abonnenten mit klarer Einwilligung. Nur die E-Mail-Adresse ist Pflicht.","submit":"Senden","thanks":"Gesendet. Vielen Dank.","file_too_big":"Bis zu 3 Dateien, je 5 MiB und insgesamt 10 MiB.","error":"Senden fehlgeschlagen. Bitte versuchen Sie es erneut.","section.subscribe":"Abonnement","email":"E-Mail","first_name":"Vorname","interests":"Was möchten Sie erhalten?","interests.product_news":"Produktneuigkeiten","interests.offers":"Angebote und Rabatte","interests.tips":"Tipps und Anleitungen","section.consent":"Einwilligung","consent_newsletter":"Ja, senden Sie mir den Newsletter. Ich kann mich jederzeit abmelden."}}</script>
<script>
function mountCaptcha(node, siteKey) {
  if (!node || !siteKey) return () => {};
  let disposed = false;
  let widget;
  function render() {
    if (disposed || !window.turnstile) return;
    window.turnstile.ready(() => {
      if (disposed) return;
      widget = window.turnstile.render(node, { sitekey: siteKey, language: node.dataset.language || document.documentElement.lang || "auto" });
      node.dataset.widgetId = widget;
    });
  }
  if (window.turnstile) render();
  else {
    let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
    if (!script) {
      script = document.createElement("script");
      script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
      script.async = true;
      document.head.appendChild(script);
    }
    script.addEventListener("load", render, { once: true });
  }
  return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
  const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
  if (widget !== undefined) window.turnstile?.reset(widget);
}
(function () {
  var MAX = 5242880;
  var form = document.getElementById("fg-form");
  var packNode = document.getElementById("fg-labels");
  if (!form || !packNode) return;
  var pack = JSON.parse(packNode.textContent);
  function code() {
    var q = new URLSearchParams(location.search).get("lang") || "";
    // ?lang= preview override, then the form language chosen when copying, then the page and browser.
    var raw = (q || form.getAttribute("data-lang") || document.documentElement.lang || (navigator.language || "en")).slice(0, 2).toLowerCase();
    return pack[raw] ? raw : "en";
  }
  function apply() {
    var dict = pack[code()];
    document.querySelectorAll("[data-i18n]").forEach(function (node) {
      var key = node.getAttribute("data-i18n");
      if (key && typeof dict[key] === "string") node.textContent = dict[key];
    });
  }
  apply();
  var status = form.querySelector("[data-status]");
  form.addEventListener("submit", function (event) {
    event.preventDefault();
    var dict = pack[code()];
    var body = new FormData(form);
    var files = Array.from(body.values()).filter(function (value) { return value instanceof File && value.size; });
    if (files.length > 3 || files.some(function (file) { return file.size > MAX; }) || files.reduce(function (sum,file) { return sum + file.size; },0) > 10 * 1024 * 1024) {
      if (status) status.textContent = dict.file_too_big;
      return;
    }
    var button = form.querySelector("button[type=submit]");
    if (button) button.disabled = true;
    fetch(form.action, { method: "POST", headers: { Accept: "application/json" }, body: body })
      .then(function (response) { return response.json(); }).then(function (result) {
        if (status) status.textContent = result && result.success ? dict.thanks : ((result && result.message) || dict.error);
      }).catch(function () { if (status) status.textContent = dict.error; })
      .finally(function () { if (button) button.disabled = false; resetCaptcha(form); });
  });
  mountCaptcha(form.querySelector("[data-turnstile]"), form.dataset.sitekey);

})();
</script>
</body>
</html>

Code for other frameworks

React
Vue
Svelte

How to get more requests

  • Say what people get and how often, for example “one email a month with new templates”.
  • Put the form at the end of a useful article, where readers already trust you.
  • Send a welcome email soon after signup, while people still remember you.
  • Keep the unsubscribe promise: every email needs a working unsubscribe link.

Answer every request

Formgong collects the signups and sends each one to your email or Telegram. It does not send newsletters. To add people to Mailchimp, Brevo or another list, send each signup there with a webhook through Make, n8n or Zapier, or export a CSV.

Questions and answers

Does Formgong send the newsletter?

No. Formgong collects signups and delivers them. Use your email service to send the newsletter, and connect it with a webhook or a CSV export.

Do I need double opt-in?

Not by EU law, but it is good practice. Your email service can send the confirmation email when a new contact arrives.

How do I stop fake signups?

A honeypot and cookie-free checks run on every form. You can also turn on Cloudflare Turnstile and block throwaway email addresses in the form settings.