Send Warmly Intent Signals to Google Sheets via Webhook

Last updated: November 7, 2025

Summary

You can automatically push Warmly intent signals (Website Visits, Bombora Research Intent, Job Changes, etc.) into a Google Sheet for custom analysis, AI-powered filtering, or integration with external toolsβ€”all without using Zapier or paying for third-party services. This guide walks you through setting up a free webhook receiver using Google Apps Script.


Pre-reqs

βœ… Active Warmly orchestration collecting intent signals
βœ… Google account with access to Google Sheets
βœ… 10-15 minutes for setup


Step 1: Create Your Google Sheet

  1. Open Google Sheets and create a new blank spreadsheet

  2. Name your sheet something like "Warmly Intent Data" or "Bombora Leads"

  3. Add header row in Row 1 based on the signal type you're tracking:

For Website Visit Signals (Contact or Company), use these headers:

Received At | Signal | Orchestration Name | Webhook Sent At | LinkedIn URL | Business Email | First Name | Last Name | Title | City | State | Country | Company Name | Website | Industry | Employee Count | Estimate Revenue | Company City | Company State | Company Country | Company Logo | Seen At | Referrer | Captured URL | Session URL | Session ID | Session Active Seconds | Session Identification Score | Session Identification Confidence | IP City | IP State | IP Country | UTM Medium | UTM Campaign | UTM Content | UTM Source | Pages Viewed | Pages Viewed Details

For Bombora Research Intent signals, use these headers:

Received At | Signal | Orchestration Name | Webhook Sent At | LinkedIn URL | Business Email | First Name | Last Name | Title | City | State | Country | Company Name | Website | Industry | Employee Count | Estimate Revenue | Company City | Company State | Company Country | Company Logo | Bombora Research Intent

See the exact payload your trigger would send in our webhook guide HERE

πŸ’‘ Tip: Copy the header row directly from above and paste it into Row 1 of your sheet.


Step 2: Set Up the Apps Script Webhook Receiver

  1. In your Google Sheet, go to Extensions β†’ Apps Script

  2. Delete any default code you see in the editor

  3. Copy and paste one of the code blocks below based on your signal type:

Code for Website Visit Signals (Contact or Company)

function doPost(e) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
    const data = JSON.parse(e.postData.contents);
    
    const timestamp = new Date();
    
    // Flatten Pages Viewed Details array
    const pagesDetails = (data["Pages Viewed Details"] || [])
      .map(p => `${p.URL} (${p["Active Seconds"]}s at ${p["Page Viewed At"]})`)
      .join(" | ");
    
    const row = [
      timestamp,
      data.Signal || '',
      data["Orchestration Name"] || '',
      data["Webhook Sent At"] || '',
      data["LinkedIn URL"] || '',
      data["Business Email"] || '',
      data["First Name"] || '',
      data["Last Name"] || '',
      data.Title || '',
      data.City || '',
      data.State || '',
      data.Country || '',
      data["Company Name"] || '',
      data.Website || '',
      data.Industry || '',
      data["Employee Count"] || '',
      data["Estimate Revenue"] || '',
      data["Company City"] || '',
      data["Company State"] || '',
      data["Company Country"] || '',
      data["Company Logo"] || '',
      data["Seen At"] || '',
      data.Referrer || '',
      data["Captured URL"] || '',
      data["Session URL"] || '',
      data["Session ID"] || '',
      data["Session Active Seconds"] || '',
      data["Session Identification Score"] || '',
      data["Session Identification Confidence"] || '',
      data["IP City"] || '',
      data["IP State"] || '',
      data["IP Country"] || '',
      data["UTM Medium"] || '',
      data["UTM Campaign"] || '',
      data["UTM Content"] || '',
      data["UTM Source"] || '',
      data["Pages Viewed"] || '',
      pagesDetails
    ];
    
    sheet.appendRow(row);
    
    return ContentService.createTextOutput(JSON.stringify({
      status: 'success',
      message: 'Data received'
    })).setMimeType(ContentService.MimeType.JSON);
    
  } catch (error) {
    Logger.log('Error: ' + error.toString());
    return ContentService.createTextOutput(JSON.stringify({
      status: 'error',
      message: error.toString()
    })).setMimeType(ContentService.MimeType.JSON);
  }
}

Code for Bombora Research Intent Signals

function doPost(e) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
    const data = JSON.parse(e.postData.contents);
    
    const timestamp = new Date();
    
    // Flatten Bombora Research Intent array
    const bomboraIntents = (data["Bombora Research Intent"] || [])
      .map(intent => `${intent.Topic} (Score: ${intent.Score})`)
      .join(" | ");
    
    const row = [
      timestamp,
      data.Signal || '',
      data["Orchestration Name"] || '',
      data["Webhook Sent At"] || '',
      data["LinkedIn URL"] || '',
      data["Business Email"] || '',
      data["First Name"] || '',
      data["Last Name"] || '',
      data.Title || '',
      data.City || '',
      data.State || '',
      data.Country || '',
      data["Company Name"] || '',
      data.Website || '',
      data.Industry || '',
      data["Employee Count"] || '',
      data["Estimate Revenue"] || '',
      data["Company City"] || '',
      data["Company State"] || '',
      data["Company Country"] || '',
      data["Company Logo"] || '',
      bomboraIntents
    ];
    
    sheet.appendRow(row);
    
    return ContentService.createTextOutput(JSON.stringify({
      status: 'success',
      message: 'Data received'
    })).setMimeType(ContentService.MimeType.JSON);
    
  } catch (error) {
    Logger.log('Error: ' + error.toString());
    return ContentService.createTextOutput(JSON.stringify({
      status: 'error',
      message: error.toString()
    })).setMimeType(ContentService.MimeType.JSON);
  }
}
  1. Change 'Sheet1' in the code if your sheet tab has a different name

  2. Save the project (File β†’ Save or Ctrl/Cmd + S)

  3. Name your project something like "Warmly Webhook Handler"


Step 3: Deploy the Web App

  1. Click Deploy β†’ New deployment

  2. Click the gear icon βš™ next to "Select type" and choose Web app

  3. Configure the deployment:

    • Description: "Warmly Webhook Receiver" (or any name you prefer)

    • Execute as: Me (your email)

    • Who has access: Anyone ⚠ This is required for external webhooks to work

  4. Click Deploy

  5. Authorize the script when prompted (click "Authorize access" β†’ choose your Google account β†’ click "Advanced" β†’ "Go to [Project Name]" β†’ "Allow")

  6. Copy the Web App URL that appears β€” this is your webhook endpoint

πŸ’‘ Important: Save this URL somewhere safe. You'll paste it into Warmly in the next step.


Step 4: Connect the Webhook to Warmly Orchestration

  1. Log into Warmly and go to Outbound Agent β†’ Orchestrations

  2. Select the orchestration you want to send to Google Sheets (or create a new one)

  3. Click Edit Orchestration

  4. Add a Webhook step:

    • Click + Add Step

    • Select Webhook

  5. Paste your Google Apps Script Web App URL into the webhook URL field

  6. Remove any other steps (like "Send to CRM") if you only want data flowing to the Google Sheet

  7. Click Save and ensure the orchestration is Active


Step 5: Test the Integration

Option 1: Use Built-In Test Function

  1. Go back to your Apps Script editor

  2. Add this test function at the bottom of your code:

function testWebhook() {
  const testPayload = {
    postData: {
      contents: JSON.stringify({
        "Signal": "Website Visit Company",
        "Orchestration Name": "Test Orchestration",
        "Webhook Sent At": new Date().toISOString(),
        "Business Email": "[email protected]",
        "First Name": "Test",
        "Last Name": "User",
        "Company Name": "Test Company",
        "Website": "example.com"
      })
    }
  };
  
  const result = doPost(testPayload);
  Logger.log(result.getContent());
}
  1. Select testWebhook from the function dropdown at the top

  2. Click Run

  3. Check your Google Sheet β€” you should see a new row with test data

  4. View logs (View β†’ Logs) to see if there were any errors

Option 2: Trigger from Warmly

  • Wait for a real visitor to trigger your orchestration

  • Check the Orchestration Logs in Warmly to confirm the webhook was sent

  • Refresh your Google Sheet to see the new row


🎯 Final Tips & Best Practices

βœ… Use separate sheets for different signal types β€” Create tabs like "Website Visits," "Bombora Intent," "Job Changes"

βœ… Add conditional formatting to highlight high-intent signals (e.g., Session Identification Score > 0.7)

βœ… Filter and sort your data using Google Sheets' built-in tools to prioritize leads

βœ… Connect to external AI tools β€” Use this data with ChatGPT, Claude, or Gemini via Google Sheets Add-ons for ICP filtering

βœ… Set up weekly reviews β€” Create a calendar reminder to review new leads every Monday

⚠ If you modify the Apps Script code:

  1. Go to Deploy β†’ Manage deployments

  2. Click the Edit icon (pencil) next to your existing deployment

  3. Change version to New version

  4. Click Deploy


Troubleshooting

Issue

Solution

No data appearing in sheet

Check that the sheet name in your code matches your actual sheet tab name (default is 'Sheet1')

"Authorization required" error

Re-deploy the web app and make sure "Who has access" is set to Anyone

Headers don't match data

Ensure your header row matches the signal type (Website Visit vs. Bombora Intent)

Webhook URL changed

Webhook URLs only change if you create a NEW deployment. Editing an existing deployment keeps the same URL

Data in wrong columns

Double-check that your header row exactly matches the code's row array order


Questions? Contact [email protected]