DEV Community

Cover image for How to Setup Webhook in Google Form?
Amjad C P
Amjad C P

Posted on

3 1 1 1

How to Setup Webhook in Google Form?

If you aim to implement custom logic when a user submits a Google Form, this workaround is for you.

1

Our goal is to automate the two steps outlined in the previous diagram using Google Workspace APIs. In order to access these APIs, it is necessary to create a service account and enable both the Google Forms API and Google Drive API.

Create Service Account & Enable APIs

  • Log in to Google Cloud Console and create a project.
  • Go to IAM & Admin > Service Account and create the service account.

2

Assign Editor access to the service account from the basic roles.

  • Create new key as JSON file.

3

  • Go to APIs & Services > Enabled APIs Services and enable Google Cloud API and Google Form API.

4

5

Setup Google Form

  • Create a Google Form and add the service account email as a collaborator ( edit access ).

6

Setup Server

  • Create a web server using Express.

    const express = require('express');
    const cors = require('cors');
    const { fetchForm, addFormToSheet, authenticateForm } = require('./utils');
    const app = express();
    const port = 3000;
    
    authenticateForm();
    
    app.use(cors());
    app.use(express.json({
        type: ["application/json", "text/plain"]
    }));
    
    // To upload Google Form ID to link to a Google Sheet
    app.post('/api/v1/form', async (req, res) => {
        const { formId } = req.body;
        console.log(formId);
        const data = await fetchForm(formId);
        const formName = data?.info?.title || "undefined";
        await addFormToSheet(formId, formName);
        res.status(200).json({
            message: "Form added to sheet",
        });
    });
    
    // Webhook url to get response when a user submit a form. We have to add this in AppScript
    app.post('/api/v1/webhook', async (req, res) => {
        console.log(req.body);
        res.status(200).json({
            message: "Webhook received",
        });
    });
    
    app.listen(port, () => {
        console.log(`Server is running on port ${port}`);
    });
    
```jsx
const { google } = require("googleapis");
const path = require("path");
const axios = require("axios");
const FormData = require("form-data");
const {config} = require("dotenv");

config();

let forms;
const authenticateForm = async () => {
  const auth = new google.auth.GoogleAuth({
    keyFile: "./key.json", // service account key that we downloaded from Google Cloud Console
    scopes: [
      "https://www.googleapis.com/auth/forms.responses.readonly",
      "https://www.googleapis.com/auth/forms.body.readonly",
      "https://www.googleapis.com/auth/forms.body",
      "https://www.googleapis.com/auth/drive",
    ],
  });

  const client = await auth.getClient();
  forms = google.forms({ version: "v1", auth: client });
  console.log("google form authenticated");
};

const fetchForm = async (formId) => {
  const data = await forms.forms.get({
    formId,
  });
  return data.data;
};

const addFormToSheet = async (formId, formName) => {
  const data = new FormData();
  data.append("formId", formId);
  data.append("formName", formName);
  // APP_SCRIPT_URL from the ENV file added in the same folder.
  // We will get this URL after the deploy the AppScript
  const response = await axios.post(process.env.APP_SCRIPT_URL, data, {
    headers: {
      "Content-Type": "multipart/form-data",
    },
  });

  console.log(response.data);
};

module.exports = {
  authenticateForm,
  fetchForm,
  addFormToSheet,
};

```
Enter fullscreen mode Exit fullscreen mode
  • Make the server publicly available using ngrok. Checkout the link to setup ngrok.

Setup Google Sheet

  • Create a Google Sheet and set the AppScript logic to link Google Form to the Google Sheet and trigger a webhook while user submit the form.

7

8

  • Use the AppScript provided below.
// This function will trigger when you do the post request using the AppScript deploy link
function doPost(e) {
  var formId = e.parameter.formId; // Google Form ID send in POST request
  var sheetName = e.parameter.formName; // Google Form title send in POST rquest
  var form = FormApp.openById(formId);

  // Replace with your sheet ID
  var sheetId = 'sheet_id';

  // Link the form to the sheet
  form.setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);

  // Get all sheets in the spreadsheet
  var spreadsheet = SpreadsheetApp.openById(sheetId);
  var sheets = spreadsheet.getSheets();

  // set the sheet name as the form title
  for (var i = 0; i < sheets.length; i++) {
    if (sheets[i].getName().startsWith('Form')) {
      sheets[i].setName(sheetName);
      break;
    }
  }

  return ContentService.createTextOutput("Done");
}

// This function will trigger when a user submits any of the linked form
function onFormSubmit(e) {
  // Get the active spreadsheet and the first sheet
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  // Get the headers (field names)
  var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];

  // Get the response values
  var values = e.values;

  // Create an object with the field names and values
  var data = {};
  for (var i = 0; i < headers.length; i++) {
    data[headers[i]] = values[i];
  }
  console.log(data);

  // Get the form URL
  var formUrl = e.range.getSheet().getFormUrl();

  // Extract the form ID from the form URL
  var formId = formUrl.split('/forms/d/')[1].split('/')[0];
  console.log('Form ID: ' + formId);

  // Add the form ID to the data
  data['formId'] = formId;

  // Prepare the options for the HTTP request
  var options = {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    payload: JSON.stringify(data)
  };

  // Send the HTTP request. Replace the URL with your server webhook url (url from ngrok)
  UrlFetchApp.fetch('webhook_url', options);
}
Enter fullscreen mode Exit fullscreen mode

The selected part of the Google Sheet URL is the sheet ID.

9

  • After saving the AppScript go to the trigger section and create the trigger to execute the onFormSubmit function when a row entry happens in sheet.

10

When you clicks the save button you have to authorize with your Google account.

11

  • Deploy the AppScript

12

12

13

After clicks the deploy button, you will get the AppScript URL and update in your server ENV file and restart the server .

14

Testing

  • Upload Google Form ID using the API to link with Google Sheet.

15

The selected part of the Google Form URL is the Google Form ID

16

  • Submit a response using the form you will get the form response in your terminal.

17

18

19

You can link multiple forms to a sheet using the Form ID Upload API. Responses from these forms can be found using the "formId" key in the webhook.

NOTE

  • Upon calling the Google Workspace API for the first time, you may receive an unauthorized error due to a delay in API enablement or service account setup.
  • If you still encounter the error, try changing the service account role to owner.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more