|
/ Documentation /Apps & Integrations Setup/ Trigger OttoKit Workflows from Google Sheets Using App Script & Webhooks (Within 1 Minute)

Trigger OttoKit Workflows from Google Sheets Using App Script & Webhooks (Within 1 Minute)

With OttoKit, you can now trigger powerful automations the moment new data lands in your Google Sheet — whether it comes from a third-party app, IMPORTRANGE, a formula, another App Script, or any external integration.

This is made possible through our newly developed App Script, which enables near-instant (within 1 minute) workflow triggers based on dynamic changes in your Google Sheets.

For example, you can automatically add new subscribers to your email marketing tool as soon as a new row is added, no matter how the data arrives.

To make this work, you’ll be using the OttoKit Webhooks Google Sheets add-on to set up and manage your triggers effortlessly.

In this guide, we’ll show you how to set up the OttoKit Webhook add-on and start triggering workflows from your Google Sheet in real-time.

Let’s dive in!

What Is OttoKit Webhook Add-on?

OttoKit Webhook is an extension for Google Sheets that helps you connect your OttoKit account with Google Sheets using webhooks.

It can help you create workflows that trigger when new rows are added to a specific spreadsheet.

How to Set Up Google Sheets Triggers

Step 1: Setting Up Google Sheets Trigger

  • Click on the “Add Trigger” button.
  • Search for the Google Sheets trigger and select it as your trigger app.
  • Copy the webhook URL displayed on the screen, as we will use it in the following steps.

Step 2: Setting Up OttoKit Webhook Addon for Google Sheets

  • Click on “Extensions” > “App Script.”
  • Copy the provided App Script from below:
function onOpen(e) {
  SpreadsheetApp.getUi().createMenu('Ottokit Webhooks')
    .addItem('Send rows every minute', 'setup')
    .addItem('Help', 'help')
    .addToUi();
}

function setup() {
  var trigOwner = PropertiesService.getDocumentProperties().getProperty('trigOwner');
  var sheetId = PropertiesService.getDocumentProperties().getProperty('sheetId');
  var setup = PropertiesService.getDocumentProperties().getProperty('setup');
  var sheet = !sheetId ? false : SpreadsheetApp.getActive().getSheets().find(sh => sh.getSheetId() == sheetId);
  var n = !sheet ? sheetId : sheet.getName();
  var config = (!trigOwner ? '' : `Trigger owner: ${trigOwner}.`)
    + (!sheetId ? '' : ` Sheet: ${n}.`)
    + (!setup ? '' : `\nWebhook & last column: ${setup}.`);
  if (config.length) {
    config = `\n* Current configuration:- ${config}\n`;
  }

  var title = 'Set Up Ottokit Webhook Trigger?';
  var body = `Ottokit will automatically send your new spreadsheet entries every minute.

1. To Start or Update:
Please paste the Ottokit webhook link below. If you also want to wait until a certain column has data before sending a row, mention that column letter too — after a comma.

Examples:
a. Just the link: https://webhook.ottokit.com/GoogleSheetsTrigger/140d11b8-7ec7-42e5-bfd5-8ee651145ejs  
b. Link with column condition: https://webhook.ottokit.com/GoogleSheetsTrigger/140d11b8-7ec7-42e5-bfd5-8ee651145ejs, D

(For the second example, the system will send the row only when there's something filled in Column D.)

2. To Stop Sending:
Click "No" if you want to turn off this automation.
${config}\n`;

  var ui = SpreadsheetApp.getUi();
  var result = ui.prompt(title, body, ui.ButtonSet.YES_NO_CANCEL);

  var button = result.getSelectedButton();
  var setup = result.getResponseText();
  if (button == ui.Button.YES) {
    if (!trigOwner) {
      ScriptApp.newTrigger('onSchedule')
        .timeBased()
        .everyMinutes(1)
        .create();
      PropertiesService.getDocumentProperties().setProperty('trigOwner', Session.getEffectiveUser().getEmail());
    }
    PropertiesService.getDocumentProperties().setProperty('sheetId', SpreadsheetApp.getActiveSheet().getSheetId().toString());
    PropertiesService.getDocumentProperties().setProperty('setup', setup);
    PropertiesService.getDocumentProperties().setProperty('lastSentRow', 1);
    ui.alert('Webhook trigger has been set!');
  } else if (button == ui.Button.NO) {
    PropertiesService.getDocumentProperties().deleteAllProperties();
    var msg = 'All configurations cleared.';
    if (Session.getEffectiveUser().getEmail() == trigOwner) {
      var triggers = ScriptApp.getUserTriggers(SpreadsheetApp.getActive());
      for (var i = 0; i < triggers.length; i++) {
        ScriptApp.deleteTrigger(triggers[i]);
      }
      msg += '\nThe automated trigger has been removed.';
    } else {
      msg += `\nPlease use the account ${trigOwner} to fully remove the automation.`;
    }
    ui.alert(msg);
  }
}

function help() {
  var htmlOutput = HtmlService
    .createHtmlOutput('<p>Refer to the Ottokit guide <a href="https://ottokit.com/docs/triggering-workflows-using-google-sheets-in-ottokit/" target="_blank">here</a>.</p>')
    .setWidth(300)
    .setHeight(100);
  SpreadsheetApp.getUi().showModelessDialog(htmlOutput, 'Ottokit Webhooks Help');
}

function onSchedule() {
  const start = Date.now();
  var ss = SpreadsheetApp.getActive();
  var sheetId = PropertiesService.getDocumentProperties().getProperty('sheetId');
  var sheet = ss.getSheets().find(sh => sh.getSheetId() == sheetId);
  var setup = PropertiesService.getDocumentProperties().getProperty('setup');
  if (!sheet || !setup) { return; }

  var webhook_url, end_column;
  var li = setup.lastIndexOf(',');
  if (li == -1) {
    webhook_url = setup;
    let i = sheet.getDataRange().getLastColumn();
    let l = '';
    let c;
    while (i > 0) {
      c = (i - 1) % 26;
      l = String.fromCharCode(c + 65) + l;
      i = (i - c - 1) / 26;
    }
    end_column = l;
  } else {
    webhook_url = setup.substring(0, li);
    end_column = setup.substring(li + 1).trim();
  }
  var lastSentRow = PropertiesService.getDocumentProperties().getProperty('lastSentRow');
Logger.log(lastSentRow)
  if (!webhook_url || !end_column || !lastSentRow) { return; }

  lastSentRow = parseInt(lastSentRow, 10);
  var rowEnd = parseInt(sheet.getLastRow(), 10);
  if (rowEnd > lastSentRow) {
    if (timeUp(start)) { return; }
    var headers = sheet.getRange(`A1:${end_column}1`).getDisplayValues()[0];
    var values = sheet.getRange(`A${parseInt(lastSentRow + 1, 10)}:${end_column + rowEnd}`).getDisplayValues();
    var sent = -1;
    for (var v = 0; v < values.length; v++) {
      if ((values[v][values[v].length - 1]).length) {
        connectWebhook(
          convertToJson(values[v], headers, ss.getName(), ss.getId(), sheet.getName(), sheetId, end_column, lastSentRow + 1 + v),
          webhook_url
        );
        sent = v;
      }
      if (timeUp(start)) { break; }
    }
Logger.log(lastSentRow)
    if (sent >= 0) {
      lastSentRow += (sent + 1);
      PropertiesService.getDocumentProperties().setProperty('lastSentRow', lastSentRow);
    }
  }
}

function timeUp(start) {
  return (Date.now() - start) > 45000;
}

function connectWebhook(data, url) {
  var options = {
    'method': 'post',
    'payload': JSON.stringify(data)
  };
  UrlFetchApp.fetch(url, options);
}

function convertToJson(values, headers, spreadsheetName, spreadsheetID, sheetName, sheetID, triggerColumn, rowIndex) {
  var data = {};
  for (var i in values) {
    data[headers[i]] = values[i];
  }
  data.SpreadsheetName = spreadsheetName;
  data.SpreadsheetID = spreadsheetID;
  data.SheetName = sheetName;
  data.SheetID = sheetID;
  data.TriggerColumn = triggerColumn;
  data.RowIndex = rowIndex;
  return data;
}
  • Click on Save & close the tab.
  • Go to your Google Sheet, and you will see OttoKit Webhooks.
  • Click on OttoKit Webhooks< Send rows every minute.
  • Click OK to authorize your Google account, and then follow the authentication process as shown in the screenshots below.
  • Once you’ve completed the authentication process, you’ll see a popup titled “Set Up OttoKit Webhook Trigger?”
  • In the input field, paste the webhook URL you copied in the Google Sheet step, then add a comma and enter the trigger column.
  • Click on Yes.
  • Now you can go to your workflow and within 1 minute of time, the response will get captured and you can further setup the workflow.

That’s done! Your Google Sheet trigger step is now setup and it will work for any new rows added by any third party within 1 minute of time.

Was this doc helpful?
What went wrong?

We don't respond to the article feedback, we use it to improve our support content.

Need help? Contact Support
On this page
Scroll to Top