Receive Google Forms responses
Google Forms has no webhook of its own. An Apps Script attached to the form sends each response to DataLug and signs it with the DataLug signature. Receive a webhook from any system covers the shared settings.
Create the webhook
- In Manage Account > Webhooks, select New webhook, enter a name and keep Signature as DataLug signature.
- Set Event id for duplicates to Field path and enter
responseId. - Press Create webhook and copy the webhook URL and the secret.
Add the script
- Open Apps Script from the form editor.
- In Project Settings, add a script property named
DATALUG_WEBHOOK_SECRETwith the secret. - Replace the script with the code below and set
WEBHOOK_URLto the webhook URL. - Add a trigger for
onFormSubmitwith the event type On form submit.
const WEBHOOK_URL = "PASTE_THE_WEBHOOK_URL_HERE";
function onFormSubmit(e) {
const secret = PropertiesService.getScriptProperties().getProperty("DATALUG_WEBHOOK_SECRET");
const answers = {};
e.response.getItemResponses().forEach(function (item) {
answers[item.getItem().getTitle()] = item.getResponse();
});
const body = JSON.stringify({
responseId: e.response.getId(),
submittedAt: e.response.getTimestamp().toISOString(),
email: e.response.getRespondentEmail(),
answers: answers,
});
// X-DataLug-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body">
const t = Math.floor(Date.now() / 1000);
const mac = Utilities.computeHmacSha256Signature(t + "." + body, secret, Utilities.Charset.UTF_8);
const hex = mac
.map(function (b) {
return ("0" + (b & 0xff).toString(16)).slice(-2);
})
.join("");
const res = UrlFetchApp.fetch(WEBHOOK_URL, {
method: "post",
contentType: "application/json; charset=utf-8",
payload: body,
headers: { "X-DataLug-Signature": "t=" + t + ",v1=" + hex },
muteHttpExceptions: true,
});
if (res.getResponseCode() !== 202) {
throw new Error("DataLug answered " + res.getResponseCode());
}
}
Keep the secret out of the code
The script reads the secret from its script properties, so the code can be shared without it.
What arrives
One row per response, with responseId, submittedAt, email and an answers object keyed by
question title. email is empty unless the form collects email addresses.
Duplicates and responses
responseId is the event id, so a response sent twice runs once. An accepted request is answered
202; the script raises an error on any other status, and the failure shows in the script's
executions.