How to send Wix form submissions to Google Sheets with Velo
Mosaddik Billah 3 min read

On this page
Many teams live in Google Sheets. If your leads arrive through a Wix form, someone ends up copying them over by hand. This guide sends every new submission to a sheet automatically, using a Velo data hook and a short Google Apps Script. No paid connector, no monthly fee.
The idea: your form saves each submission to a CMS collection. When a new item is added, a backend hook sends it to a Google Apps Script URL, and the script adds a row to the sheet.
1. Collect submissions in a CMS collection#
Create a collection called Leads with the fields name, email and message. Connect your form inputs to it through a dataset with a submit button, or insert items from your own code. Set the collection’s permissions so visitors can add items but not read them.
2. Create the Google Apps Script#
- Create a Google Sheet with a tab named
Leadsand the headersDate,Name,Email,Messagein the first row. - In the sheet, open Extensions → Apps Script and replace the code with:
const TOKEN = "change-this-to-a-long-random-string";
function doPost(e) {
const data = JSON.parse(e.postData.contents);
if (data.token !== TOKEN) {
return ContentService.createTextOutput("forbidden");
}
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Leads");
sheet.appendRow([new Date(), data.name, data.email, data.message]);
return ContentService.createTextOutput("ok");
}- Click Deploy → New deployment, choose Web app, set Execute as to yourself and Who has access to Anyone, then deploy and copy the web app URL.
The URL can be called by anyone who has it, which is why the script checks a token before writing anything.
3. Store the URL and token in Wix#
In your Wix dashboard, open Developer Tools → Secrets Manager and add two secrets:
SHEETS_WEBHOOK_URL: the web app URL from step 2SHEETS_TOKEN: the same random string you put in the script
4. Add the data hook#
In the Velo sidebar, open the backend folder and create data.js if it doesn’t exist. Hooks are named after the collection and the event:
import { getSecret } from "wix-secrets-backend";
import { fetch } from "wix-fetch";
export async function Leads_afterInsert(item, context) {
try {
const url = await getSecret("SHEETS_WEBHOOK_URL");
const token = await getSecret("SHEETS_TOKEN");
await fetch(url, {
method: "post",
headers: { "content-type": "application/json" },
body: JSON.stringify({
token,
name: item.name,
email: item.email,
message: item.message,
}),
});
} catch (error) {
console.error("Could not send lead to Google Sheets", error);
}
return item;
}Two details matter:
afterInsertruns after the item is saved, so a problem with Google never stops the visitor’s submission from going through.- The
try…catchmeans a failed request is logged instead of throwing. You can see these logs under Developer Tools → Logs in the dashboard.
5. Test it#
Publish the site, submit the form once, and check the sheet. A new row with the date and the visitor’s details means it works. If nothing appears, check the site logs first, then the script’s Executions page in Apps Script.
When to go further#
The same pattern sends data anywhere that accepts a web request: a CRM, a Slack channel or an email tool. Common additions are sending only certain form types, formatting dates for your region, or writing updates back when a row changes in the sheet.
If you’d like your Wix forms connected to Sheets, a CRM or other tools, I do custom API integrations for Wix.
Comments