I need help with connecting Google Sheets to my external system. When someone adds a new row to their sheet, I want it to automatically send that data to my webhook endpoint.
Right now I’m using Google Apps Script but running into some issues. The onChange trigger seems like it should work but it doesn’t have permission to make external HTTP requests. I tried using installable triggers but that means users have to set things up manually which is not what I want.
Here’s my current setup:
// OAuth setup
const authClient = new google.auth.OAuth2();
authClient.setCredentials(userTokens);
// Get sheet ID from URL
const sheetId = sheetUrl.match(/\/spreadsheets\/d\/([a-zA-Z0-9-_]+)/)[1];
// Script code to inject
const scriptCode = `
function onChange(event) {
const editRange = event.range;
const activeSheet = editRange.getSheet();
// Only process if editing first column and not header row
if (editRange.getColumn() === 1 && editRange.getRow() > 1) {
const rowData = activeSheet.getRange(editRange.getRow(), 1, 1, activeSheet.getLastColumn()).getValues()[0];
// Create webhook payload
const data = JSON.stringify({
sheetId: event.source.getId(),
sheetName: activeSheet.getName(),
newRowData: rowData,
rowNumber: editRange.getRow()
});
// Send to webhook
const requestOptions = {
method: 'post',
contentType: 'application/json',
payload: data,
muteHttpExceptions: true
};
try {
const result = UrlFetchApp.fetch('https://my-app-webhook.com/notify', requestOptions);
Logger.log('Webhook result:', result.getContentText());
} catch (err) {
Logger.log('Webhook error:', err);
}
}
}
`;
// Manifest configuration
const manifestConfig = JSON.stringify({
timeZone: "UTC",
dependencies: {},
exceptionLogging: "STACKDRIVER",
oauthScopes: [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/script.external_request"
]
});
// Create and deploy script
const scriptAPI = google.script({ version: 'v1', auth: authClient });
const projectResult = await scriptAPI.projects.create({
requestBody: {
title: 'Sheet Webhook Handler',
parentId: sheetId
}
});
const newScriptId = projectResult.data.scriptId;
await scriptAPI.projects.updateContent({
scriptId: newScriptId,
requestBody: {
files: [
{
name: 'Main',
type: 'SERVER_JS',
source: scriptCode
},
{
name: 'appsscript',
type: 'JSON',
source: manifestConfig
}
]
}
});
My main questions are:
- What’s the best way to automatically set up triggers that can make external requests without user intervention?
- How do I handle the permission issues with simple triggers vs installable triggers?
- Is there a better approach than Apps Script for getting real-time data from Google Sheets?
Any help would be awesome!