Automations Anonymous
Sheet
Display
Read
Type

Sheet 04 · /automations/post-every-form-response-to-chat

Post every form response to a chat channel

An Apps Script trigger on the responses spreadsheet posts each new form submission to a chat channel as a readable message, so the people who act on it never open the sheet.

Difficulty:
beginner

Problem

A form writes a row and nobody sees it. The team either checks the sheet out of habit or finds out days later that someone was waiting on them.

Trigger

A form submission, through the spreadsheet's on form submit trigger.

Prerequisites

  • 01A Google Form whose responses go to a spreadsheet.
  • 02An incoming webhook URL from the chat tool.
  • 03Permission to authorize a script on the account that owns the form.

Steps

  1. 01

    Open the responses spreadsheet, then Extensions > Apps Script google-apps-script

  2. 02

    Paste the script and save google-apps-script

  3. 03

    Add SLACK_WEBHOOK_URL under Project Settings > Script properties slack

    Script properties keep the webhook out of the code and out of version control.

  4. 04

    Add the trigger google-apps-script

    Triggers > Add trigger > function onFormSubmit > event source From spreadsheet > event type On form submit. Authorize when prompted.

  5. 05

    Submit the form once as a test google-forms

    Executions in the Apps Script sidebar shows the run and any error.

Payload · javascript

/**
 * Google Apps Script, bound to the form's responses spreadsheet.
 * Extensions > Apps Script, paste this, then add a trigger:
 * Triggers > Add trigger > onFormSubmit > From spreadsheet > On form submit.
 * Put the webhook in Project Settings > Script properties as SLACK_WEBHOOK_URL.
 */
function onFormSubmit(e) {
  const webhook = PropertiesService.getScriptProperties().getProperty('SLACK_WEBHOOK_URL');
  if (!webhook) throw new Error('Script property SLACK_WEBHOOK_URL is not set');

  const answers = e.namedValues;
  const lines = Object.keys(answers)
    .filter(function (question) { return String(answers[question]).trim() !== ''; })
    .map(function (question) { return '*' + question + '*: ' + answers[question]; });

  const body = {
    text: 'New form response',
    blocks: [{ type: 'section', text: { type: 'mrkdwn', text: lines.join('\n') } }]
  };

  UrlFetchApp.fetch(webhook, {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(body),
    muteHttpExceptions: true
  });
}

Failure modes

  • !The trigger is attached to the form instead of the spreadsheet and e.namedValues is empty. It must be From spreadsheet.
  • !A long free text answer makes the message unreadable in chat. Post the questions that matter rather than all of them.
  • !The webhook is revoked and every run fails quietly. muteHttpExceptions keeps the row from being lost, so check Executions occasionally.
  • !Apps Script has daily quotas on UrlFetchApp. A form taking thousands of responses a day needs a different approach.

JSON-LD · HowTo

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "Post every form response to a chat channel",
  "description": "An Apps Script trigger on the responses spreadsheet posts each new form submission to a chat channel as a readable message, so the people who act on it never open the sheet.",
  "url": "https://automationsanonymous.com/automations/post-every-form-response-to-chat",
  "tool": [
    {
      "@type": "HowToTool",
      "name": "google-forms",
      "url": "https://automationsanonymous.com/tools/google-forms"
    },
    {
      "@type": "HowToTool",
      "name": "google-sheets",
      "url": "https://automationsanonymous.com/tools/google-sheets"
    },
    {
      "@type": "HowToTool",
      "name": "google-apps-script",
      "url": "https://automationsanonymous.com/tools/google-apps-script"
    },
    {
      "@type": "HowToTool",
      "name": "slack",
      "url": "https://automationsanonymous.com/tools/slack"
    }
  ],
  "step": [
    {
      "@type": "HowToStep",
      "position": 1,
      "name": "Open the responses spreadsheet, then Extensions > Apps Script",
      "text": "Open the responses spreadsheet, then Extensions > Apps Script",
      "url": "https://automationsanonymous.com/tools/google-apps-script"
    },
    {
      "@type": "HowToStep",
      "position": 2,
      "name": "Paste the script and save",
      "text": "Paste the script and save",
      "url": "https://automationsanonymous.com/tools/google-apps-script"
    },
    {
      "@type": "HowToStep",
      "position": 3,
      "name": "Add SLACK_WEBHOOK_URL under Project Settings > Script properties",
      "text": "Script properties keep the webhook out of the code and out of version control.",
      "url": "https://automationsanonymous.com/tools/slack"
    },
    {
      "@type": "HowToStep",
      "position": 4,
      "name": "Add the trigger",
      "text": "Triggers > Add trigger > function onFormSubmit > event source From spreadsheet > event type On form submit. Authorize when prompted.",
      "url": "https://automationsanonymous.com/tools/google-apps-script"
    },
    {
      "@type": "HowToStep",
      "position": 5,
      "name": "Submit the form once as a test",
      "text": "Executions in the Apps Script sidebar shows the run and any error.",
      "url": "https://automationsanonymous.com/tools/google-forms"
    }
  ],
  "datePublished": "2026-09-05T16:53:37.448Z"
}