Connecting Google Sheets, Zapier and Make
Three copy-paste recipes that post new leads to your source's webhook: a Google Apps Script for Sheets, a Webhooks by Zapier step, and an HTTP module in Make.
Updated 5 October 2026
All three send the same thing: a JSON body with at least a phone field, to your source's webhook URL, with the secret in an Authorization: Bearer <secret> header. The URL and a ready-filled script are on each source card under Lead response → Connect Google Sheets / Zapier / Make. Everything in Lead response about recognised fields, variables and the activity log applies.
Google Sheets
A short Apps Script posts each new row. The header row becomes the JSON keys, so every column reaches the caller as a {{variable}}. Replace the URL with your source's and <secret> with the secret you copied when you created it.
// ElevateBox: paste into Extensions → Apps Script, then add a trigger (see steps below)
var WEBHOOK_URL = "https://<your-app>/api/leads/ingest/<sourceId>";
var SECRET = "<secret>"; // the secret shown once when you connected the source
function onFormSubmit(e) {
sendRow_(e.range.getSheet(), e.range.getRow());
}
function onChange(e) {
var sheet = SpreadsheetApp.getActiveSheet();
sendRow_(sheet, sheet.getLastRow());
}
function sendRow_(sheet, row) {
var width = sheet.getLastColumn();
var headers = sheet.getRange(1, 1, 1, width).getValues()[0];
var values = sheet.getRange(row, 1, 1, width).getValues()[0];
var body = {};
for (var i = 0; i < headers.length; i++) {
var key = String(headers[i]).trim();
if (key) body[key] = values[i] == null ? "" : String(values[i]);
}
UrlFetchApp.fetch(WEBHOOK_URL, {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + SECRET,
"Idempotency-Key": sheet.getSheetId() + ":" + row,
},
payload: JSON.stringify(body),
muteHttpExceptions: true,
});
}- Open the sheet your form or team writes leads into. Row 1 must be a header row with one column named phone (or map your own name under Field mapping).
- Go to Extensions → Apps Script, delete the sample code and paste the snippet. Replace <secret> with your source secret.
- Click the clock icon (Triggers) → Add Trigger. Function: onFormSubmit for a Google Form sheet, or onChange for a sheet your team edits. Event source: From spreadsheet. Event type: On form submit, or On change.
- Save. Google asks you to authorize the script for this spreadsheet and for external requests. Approve it once.
- Add a row (or submit the form once) with your own number as a test. The row is posted within a second.
- Check Webhook activity on this page: the post shows as Accepted and your phone rings inside the calling window.
Zapier
- Trigger: whatever brings the lead in (a form, an ad platform, your CRM).
- Action: Webhooks by Zapier → POST.
- URL: the webhook URL above. Payload type: json. Wrap request in array: no.
- Data: add a key named phone mapped to the lead's phone number. Add name, email and any other fields you want the caller to know — each becomes a {{variable}}.
- Headers: Authorization = Bearer <secret>, Content-Type = application/json.
- Test the step, then check Webhook activity here for an Accepted row.
Make
- Add an HTTP → Make a request module after your trigger.
- URL: the webhook URL above. Method: POST.
- Headers: add Authorization with value Bearer <secret>.
- Body type: Raw. Content type: JSON (application/json).
- Request content: a JSON object with phone plus any other fields, for example {"phone": "{{1.Phone}}", "name": "{{1.Name}}"}.
- Run once, then check Webhook activity here for an Accepted row.
When nothing arrives
- No row in Webhook activity: the request never reached us. Check the URL (it ends with your source id) and that the method is POST.
- Rejected · not application/json: set the content type to JSON; a form-encoded body is not read.
- Rejected · phone number looks wrong: the value must be a mobile number. Map your column to Phone under Field mapping if it has another name.
401: the secret is wrong or was rotated. Paste the current one.