+91 98765 43210 growth@cleverroi.com
Login

Google Sheets Integration

Import leads from Google Sheets into CleverROI in three ways: manual import (one‑time), automated via Zapier (real‑time), or live scoring with Google Apps Script (scores appear directly in your sheet).

Method 1: Manual Import (Public Sheet)

Use this method for one‑time imports or if your sheet is already public. This uses our dedicated import page.

1

Publish your sheet as CSV

Open your Google Sheet, go to File → Share → Publish to web. Choose Comma-separated values (.csv) and click Publish.

Publish to web dialog
2

Copy the sheet URL

The URL will look like: https://docs.google.com/spreadsheets/d/.../edit. Copy it from your browser's address bar.

3

Go to CleverROI → Google Sheet Import

In your dashboard, navigate to Google Sheet Import (under Leads). Paste the URL and click Fetch & Import.

Our system automatically maps common column names (name, email, phone, budget, message, source). Rows without email or phone are skipped.

Import page

Method 2: Automated via Zapier

Use this method to score leads as soon as a new row is added to your sheet. This example includes custom fields.

1

Create a Zap with Google Sheets trigger

In Zapier, create a new Zap. Choose Google Sheets as the trigger app and New Spreadsheet Row as the event.

2

Connect your sheet and set up the trigger

Select the spreadsheet and worksheet you want to monitor.

Zapier trigger setup
3

Add a Webhook action

Add an action step, choose Webhooks by Zapier, and select POST. Configure as follows:

  • URL: https://yourdomain.com/api/webhook.php
  • Payload Type: JSON
  • Headers: X-API-KEY with your API key
  • Data: Map sheet columns to JSON fields. For custom fields, create a JSON object:
{
  "name": "{{full_name}}",
  "email": "{{email}}",
  "phone": "{{phone}}",
  "budget": "{{budget}}",
  "message": "{{message}}",
  "source": "google_sheet",
  "custom_fields": {
    "Your role": "{{role}}",
    "When do you want to start?": "{{start_time}}",
    "Are you decision maker?": "{{decision_maker}}",
    "Company size": "{{company_size}}",
    "Primary goal": "{{primary_goal}}"
  }
}

Note: Replace {{...}} with the actual column names from your sheet.

4

Test and publish

Run a test with a sample row. If successful, the lead will appear in your CleverROI dashboard. Publish your Zap.

Method 3: Live Scoring with Google Apps Script

For advanced users who want scores written directly into their sheet as soon as a new row is added. This script calls the CleverROI API and writes 10+ scoring fields.

Column Layout (A–P for input, Q–Z for output) – set up your sheet like this:

ColumnFieldDescription
ANameLead's full name
BEmailEmail address
CPhonePhone number
DBudgetBudget amount (text or number)
EMessageInquiry message
FSourceLead source (optional)
GRoleCustom field: Your role
HStart TimeCustom field: When to start
IDecision MakerCustom field: Are you decision maker?
JCompany SizeCustom field: Company size
KPrimary GoalCustom field: Primary goal
L(reserved)Additional custom field
MScoreTotal score (0–100)
NGradeHot / Warm / Mild / Cold
OPriority ActionRecommended next step
PClosing Probabilitye.g., "High (70-90%)"
QAI ImpactHigh / Medium / Low
RContact GradeA, B, C, D
SAI Confidencehigh / medium / low
TAI Scoree.g., "12/20"
UReasonsKey signals (truncated)
VStructured Signalse.g., "high_urgency, decision_authority"
1

Open the Apps Script editor

In your Google Sheet, go to Extensions → Apps Script.

2

Copy the script below

Delete any existing code and paste the following script. Replace YOUR_API_KEY with your actual API key and yourdomain.com with your CleverROI domain.

/**
 * CLEVERROI GOOGLE SHEET → WEBHOOK INTEGRATION (ENHANCED)
 * Columns A–K: input fields (including custom fields)
 * Columns M–V: output scoring data
 */

function onFormSubmit(e) {
  var sheet = e.range.getSheet();
  var row = e.range.getRow();
  processRow(row, sheet);
}

function testLatestRow() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var lastRow = sheet.getLastRow();
  processRow(lastRow, sheet);
}

function processAllRows() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var lastRow = sheet.getLastRow();
  for (var row = 2; row <= lastRow; row++) {
    var existingScore = sheet.getRange(row, 13).getValue(); // Column M
    if (existingScore) continue;
    processRow(row, sheet);
    Utilities.sleep(500);
  }
  Logger.log("All rows processed.");
}

function processRow(row, sheet) {
  try {
    // Read input columns A–K (11 columns)
    var rowData = sheet.getRange(row, 1, 1, 11).getValues()[0];

    // Build payload with custom_fields object
    var payload = {
      name: rowData[0] || "",
      email: rowData[1] || "",
      phone: rowData[2] || "",
      budget: rowData[3] || "",
      message: rowData[4] || "",
      source: rowData[5] || "google_sheet",
      custom_fields: {
        "Your role": rowData[6] || "",
        "When do you want to start?": rowData[7] || "",
        "Are you decision maker?": rowData[8] || "",
        "Company size": rowData[9] || "",
        "Primary goal": rowData[10] || ""
      }
    };

    var options = {
      method: 'post',
      contentType: 'application/json',
      headers: { 'X-API-KEY': 'YOUR_API_KEY' }, // <-- REPLACE THIS
      payload: JSON.stringify(payload),
      muteHttpExceptions: true
    };

    var response = UrlFetchApp.fetch('https://yourdomain.com/api/webhook.php', options);
    var result = JSON.parse(response.getContentText());

    if (result.success && result.data) {
      var data = result.data;

      // M – Score
      sheet.getRange(row, 13).setValue(data.score || "");
      // N – Grade
      sheet.getRange(row, 14).setValue(data.grade || "");
      // O – Priority Action
      sheet.getRange(row, 15).setValue(data.priority_action || "");
      // P – Closing Probability
      sheet.getRange(row, 16).setValue(data.closing_probability || "");

      // Q – AI Impact
      var aiImpact = (data.ai && data.ai.impact) ? data.ai.impact : "";
      sheet.getRange(row, 17).setValue(aiImpact);

      // R – Contact Grade
      sheet.getRange(row, 18).setValue(data.contact_grade || "");

      // S – AI Confidence
      var aiConfidence = (data.ai && data.ai.confidence) ? data.ai.confidence : "";
      sheet.getRange(row, 19).setValue(aiConfidence);

      // T – AI Score display
      var aiScoreDisplay = (data.ai && data.ai.display) ? data.ai.display : "";
      sheet.getRange(row, 20).setValue(aiScoreDisplay);

      // U – Reasons (join array, truncate)
      var reasons = (data.reasons || []).join("; ");
      if (reasons.length > 200) reasons = reasons.substring(0,200) + "…";
      sheet.getRange(row, 21).setValue(reasons);

      // V – Structured Signals
      var signals = [];
      if (data.structured_signals) {
        for (var key in data.structured_signals) {
          if (data.structured_signals[key]) signals.push(key);
        }
      }
      var signalStr = signals.join(", ");
      if (signalStr.length > 200) signalStr = signalStr.substring(0,200) + "…";
      sheet.getRange(row, 22).setValue(signalStr);

    } else {
      sheet.getRange(row, 13).setValue("API Error");
    }
  } catch (error) {
    sheet.getRange(row, 13).setValue("Script Error");
    Logger.log(error);
  }
}
3

Set up a trigger

In the Apps Script editor, click on the clock icon (Triggers). Add a new trigger:

  • Choose function: onFormSubmit
  • Choose event source: From spreadsheet
  • Choose event type: On form submit (or On change if you want every edit)

Save and authorize the script (it will ask for permissions to access your sheet and send external requests).

Trigger setup
4

Test it

Add a new row to your sheet (or submit a form if you're using Google Forms). The script will run automatically, and you should see the score appear in columns M–V within seconds.

You can also manually run testLatestRow() from the Apps Script editor to test the last row.

5

Process existing rows

If you already have many rows that you want to score, run the processAllRows() function once from the editor. It will process each row that doesn't already have a score, with a 500ms delay to avoid hitting rate limits.

Sample Webhook Payload

Here’s a complete example of the JSON payload your webhook receives (including custom fields). Use this to test your integration.

{
  "name": "Rajat Malhotra",
  "email": "akash.digitalblue@gmail.com",
  "phone": "+919845612345",
  "budget": "15-20 lakh allocated based on phase-wise rollout",
  "message": "We are optimizing our inbound qualification layer and need deterministic scoring integrated with Zoho CRM. Fraud filtering and phone validation accuracy are important for our SDR workflows.",
  "source": "google_ads",
  "custom_fields": {
    "Your role": "VP - Revenue Operations",
    "When do you want to start?": "Within 45 days",
    "Are you decision maker?": "Partially involved",
    "Company size": "55-75",
    "Primary goal": "Improve SQL conversion rate and eliminate low-intent leads"
  }
}

Need Help?

If you encounter any issues:

For further assistance, contact us at growth@cleverroi.com.