Praxisanleitung

HTML-Formular in Google Sheets: 2 kostenlose Wege

Zwei kostenlose Wege, Formulareinträge in Google Tabellen zu schreiben, mit fertigem Apps-Script-Code. Einer direkt, einer mit Benachrichtigung und Spamfilter davor.

Die kurze Antwort. Öffnen Sie die Tabelle und legen Sie ein Apps Script mit einer doPost-Funktion an, die eine Zeile anhängt. Stellen Sie es als Web-App mit Zugriff für alle bereit und senden Sie das Formular an deren URL. Sie wollen zusätzlich E-Mail- oder Telegram-Benachrichtigungen und einen Spamfilter? Dann senden Sie das Formular an ein Form-Backend, dessen Webhook das gleiche Skript aufruft. Beide Wege sind kostenlos.

Formgong

HTML-Formular in Google Sheets: 2 kostenlose Wege
HTML-Formular in Google Sheets: 2 kostenlose Wege

Die zwei Wege im Überblick

  • Weg 1: Formular → Apps Script. Das Formular sendet direkt an ein kleines Skript in Ihrer Tabelle. Mehr braucht es nicht. Sie bekommen Zeilen, aber keine Benachrichtigung, keinen Spamfilter außer dem, den Sie selbst schreiben, und das Formular braucht JavaScript.
  • Weg 2: Formular → Form-Backend → Apps Script. Das Formular geht an ein Backend. Es filtert Spam, benachrichtigt Sie und schickt dann jeden echten Eintrag per Webhook an Ihr Skript.

Brauchen Sie nur eine Liste, starten Sie mit Weg 1. Muss jemand schnell auf Anfragen reagieren, nehmen Sie Weg 2.

Weg 1: das Formular direkt an Apps Script senden

Die Menünamen stehen hier wie in der englischen Google-Oberfläche. Auf Deutsch heißen sie anders, sitzen aber an derselben Stelle.

  1. Legen Sie eine Tabelle an, nennen Sie ein Blatt Anfragen und schreiben Sie in Zeile 1: Datum, Name, E-Mail, Nachricht.
  2. Öffnen Sie Extensions → Apps Script, löschen Sie den Beispielcode und fügen Sie das Skript unten ein.
  3. Klicken Sie auf Deploy → New deployment und wählen Sie Web app. Setzen Sie Execute as auf Me und Who has access auf Anyone.
  4. Bestätigen Sie die Berechtigungen und kopieren Sie die URL der Web-App. Sie endet auf /exec.
  5. Tragen Sie die URL in den Formularcode aus dem nächsten Kasten ein und veröffentlichen Sie die Seite.

Das Skript überspringt Einträge mit ausgefülltem Honeypot. Es setzt außerdem eine Sperre, damit sich zwei gleichzeitige Einträge nicht überschreiben. Der Schritt clean() verhindert, dass ein Wert wie =IMPORTXML(…) als Formel läuft.

Apps Script
// In der Tabelle: Extensions > Apps Script. Zeile 1 des Blatts "Anfragen" enthält die Spaltennamen.
function doPost(e) {
  const p = e.parameter;
  if (p.botcheck) return json({ ok: true }); // Honeypot: Bots füllen es aus, Menschen sehen es nie
  const lock = LockService.getScriptLock();
  lock.waitLock(20000); // immer nur ein Schreibvorgang, damit sich Zeilen nicht überschreiben
  try {
    SpreadsheetApp.getActive().getSheetByName("Anfragen").appendRow([
      new Date(), clean(p.name), clean(p.email), clean(p.message),
    ]);
  } finally {
    lock.releaseLock();
  }
  return json({ ok: true });
}

// Ein Wert, der mit = + - oder @ beginnt, liefe als Formel. Das Hochkomma hält ihn als Text.
function clean(value) {
  const text = String(value || "");
  return /^[=+\-@]/.test(text) ? "'" + text : text;
}

function json(data) {
  return ContentService.createTextOutput(JSON.stringify(data))
    .setMimeType(ContentService.MimeType.JSON);
}
Das HTML-Formular, das an die Web-App sendet
HTML
<form id="lead-form">
  <label>Name <input type="text" name="name" required autocomplete="name"></label>
  <label>E-Mail <input type="email" name="email" required autocomplete="email"></label>
  <label>Nachricht <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%)">
    <input type="text" name="botcheck" tabindex="-1" autocomplete="off">
  </div>
  <button type="submit">Senden</button>
  <p id="lead-status" role="status"></p>
</form>
<script>
  const form = document.getElementById("lead-form");
  const status = document.getElementById("lead-status");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    status.textContent = "Wird gesendet…";
    try {
      // Ein Body im Formularformat bleibt ein einfacher Request, der Browser schickt keinen Preflight.
      const response = await fetch("https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec", {
        method: "POST",
        body: new URLSearchParams(new FormData(form)),
      });
      if (!response.ok) throw new Error(String(response.status));
      form.reset();
      status.textContent = "Danke, Ihre Nachricht ist angekommen.";
    } catch {
      status.textContent = "Senden fehlgeschlagen. Bitte erneut versuchen oder uns per E-Mail schreiben.";
    }
  });
</script>

Was Weg 1 nicht kann

  • Keine Benachrichtigung. Zeilen erscheinen still. Neue Anfragen sehen Sie nur, wenn Sie die Tabelle öffnen.
  • Wenig Spamschutz. Die URL ist öffentlich, jeder, der sie findet, kann senden. Ein Honeypot stoppt nur einfache Bots.
  • JavaScript nötig. Das Formular nutzt fetch, weil ein normales Absenden die Besucher auf einer Google-Seite zurücklässt.
  • Änderungen brauchen eine neue Version. Öffnen Sie nach einer Änderung Manage deployments, bearbeiten Sie die Bereitstellung und wählen Sie eine neue Version. Die URL bleibt gleich.
  • Kontingente. Google begrenzt Apps Script pro Nutzer, zum Beispiel auf 30 gleichzeitige Ausführungen und 6 Minuten pro Lauf (Stand 05.10.2026). Eine kleine Website merkt davon nichts.

Weg 2: Webhook eines Form-Backends in Ihre Tabelle

Hier ist das Formular ein normales HTML-Formular, das an Formgong sendet. Es funktioniert ohne JavaScript und zeigt eine Danke-Seite. Formgong filtert Spam, schickt die Anfrage per E-Mail oder an Telegram und sendet dann JSON an Ihr Skript. Der Free-Tarif enthält einen Webhook pro Formular.

  1. Legen Sie die Tabelle und das Blatt Anfragen mit diesen Spalten an: ID, Datum, Name, E-Mail, Nachricht.
  2. Fügen Sie das Webhook-Skript unten ein, ändern Sie SECRET und stellen Sie es wie bei Weg 1 als Web-App bereit.
  3. Öffnen Sie in Formgong die Formular-Einstellungen und fügen Sie einen Webhook hinzu. Nutzen Sie die URL der Web-App plus ?key= und Ihr Geheimnis.
  4. Klicken Sie im Dashboard auf den Webhook-Test und senden Sie dann eine echte Anfrage von Ihrer Website.
Apps Script für den Formgong-Webhook
Apps Script
// Webhook-URL in Formgong: URL der Web-App + "?key=" + dasselbe SECRET.
// Apps Script kann keine Request-Header lesen, deshalb ersetzt der Schlüssel in der URL die Signaturprüfung.
const SECRET = "change-me";

function doPost(e) {
  if (e.parameter.key !== SECRET) return reply();
  const body = JSON.parse(e.postData.contents);
  if (body.event !== "submission.created") return reply(); // der Test im Dashboard sendet "webhook.test"
  const lock = LockService.getScriptLock();
  lock.waitLock(20000);
  try {
    const sheet = SpreadsheetApp.getActive().getSheetByName("Anfragen");
    const id = body.submission.id;
    // Ein Wiederholungsversuch hat dieselbe id: überspringen, wenn die Zeile schon da ist.
    if (!sheet.getRange("A:A").createTextFinder(id).matchEntireCell(true).findNext()) {
      const f = body.submission.fields;
      sheet.appendRow([id, body.submission.created_at, clean(f.name), clean(f.email), clean(f.message)]);
    }
  } finally {
    lock.releaseLock();
  }
  return reply();
}

function clean(value) {
  const text = String(value || "");
  return /^[=+\-@]/.test(text) ? "'" + text : text;
}

// HtmlService statt ContentService: ContentService antwortet mit einer Weiterleitung,
// und ein Webhook-Absender, der Weiterleitungen nicht folgt, wertet das als Fehler.
function reply() {
  return HtmlService.createHtmlOutput("ok");
}

Die Redirect-Falle, die doppelte Zeilen erzeugt

Laut Google antwortet ein Skript mit ContentService mit einer Weiterleitung auf eine Einmal-Adresse unter script.googleusercontent.com. Ein Browser folgt ihr, für Weg 1 ist das also kein Problem. Ein Webhook-Absender, der Weiterleitungen nicht folgt, sieht dagegen einen Fehler, obwohl die Zeile schon geschrieben ist.

Formgong folgt bei Webhooks aus Sicherheitsgründen keinen Weiterleitungen. Es wertet sie als fehlgeschlagene Zustellung und versucht es später erneut, bis zu fünfmal. Jeder Versuch startet Ihr Skript, eine Anfrage kann also fünfmal auftauchen. Das Webhook-Skript verhindert das auf zwei Arten:

  • Es antwortet mit HtmlService. Entwickler berichten, dass diese Ausgabe direkt zurückkommt, ohne Weiterleitung.
  • Es schreibt die ID der Anfrage in Spalte A und überspringt IDs, die schon da sind. Selbst bei einem erneuten Versuch bleibt es bei einer Zeile.

Öffnen Sie nach der Einrichtung das Webhook-Protokoll im Dashboard. Eine echte Anfrage sollte beim ersten Versuch Status 200 zeigen.

Ohne Code: Make, n8n oder Zapier

Sie möchten Apps Script nicht anfassen? Dann schicken Sie den Webhook an ein Automatisierungstool und fügen dort einen Google-Sheets-Schritt hinzu. Anleitungen gibt es für Make und das selbst gehostete n8n. Zapier geht auch, aber sein Webhook-Trigger braucht einen bezahlten Zapier-Tarif. Kostenlos sind also Make oder n8n.

Den JSON-Body und die Prüfung der Signatur auf Ihrem eigenen Server beschreibt die Webhook-Dokumentation.

Häufig gestellte Fragen

Kann ein HTML-Formular ohne Code in Google Sheets schreiben?

Direkt nicht. Sie brauchen ein kleines Apps Script oder ein Werkzeug dazwischen, etwa ein Form-Backend mit Make oder n8n. Das Skript in diesem Artikel sind rund 20 Zeilen zum Kopieren.

Warum öffnet sich nach dem Absenden eine Google-Seite?

Das Formular sendet direkt an die Web-App, und der Browser zeigt deren Antwort. Senden Sie per fetch wie bei Weg 1 oder über ein Form-Backend, das auf Ihre eigene Danke-Seite weiterleitet.

Warum erzeugt ein Webhook doppelte Zeilen?

Der Absender hat einen Fehler gesehen und es erneut versucht. Bei Apps Script antwortet ContentService mit einer Weiterleitung, die manche Absender als Fehler werten. Antworten Sie mit HtmlService und überspringen Sie IDs, die schon in der Tabelle stehen.

Ist der Zugriff „Anyone“ auf die Web-App sicher?

Jeder mit der URL kann Daten senden, aber niemand kann darüber Ihre Tabelle lesen. Halten Sie das Skript klein, prüfen Sie bei Webhooks einen geheimen Schlüssel und geben Sie nie Tabellendaten in der Antwort zurück.

Quellen und Dokumentation

Offizielle Quellen zu dieser Anleitung: Apps Script: web apps, Apps Script: Content service redirects, Apps Script: quotas, Apps Script: Lock service, Stack Overflow: HtmlService avoids the redirect, Zapier pricing. Formgong-Webhooks, wo die Daten gespeichert werden.

Diesen Artikel als Markdown lesen

Bewerten Sie diesen Leitfaden

Ihre Bewertung

Wir lesen jede Bewertung. Ein Kommentar erscheint hier erst nach unserer Freigabe.

← Zurück zum Blog