DEV Community

Sabir Sheikh
Sabir Sheikh

Posted on

Complete Guide: Building a Google Forms to Salesforce Webhook Integration

Introduction
Integrating Google Forms with Salesforce via webhooks enables real-time data transfer without third-party tools. This guide covers the end-to-end implementation, troubleshooting common errors, and best practices.

Section 1: Architecture Overview

Image description

Components:

  1. Google Form: Collects user data
  2. Google Apps Script: Processes form submissions
  3. Salesforce REST Endpoint: Receives and stores data
  4. OAuth 2.0: Secures the connection

Section 2: Step-by-Step Implementation
Step 1: Prepare Salesforce

  1. Create a REST Endpoint
@RestResource(urlMapping='/form-submissions/*')
global class FormWebhook {

    @HttpPost
    global static String processFormData() {
        try {
            // Parse incoming JSON
            RestRequest req = RestContext.request;
            Map<String, Object> payload = (Map<String, Object>)JSON.deserializeUntyped(req.requestbody.toString());

            // Create Lead record
            Lead newLead = new Lead(
                FirstName = String.valueOf(payload.get('firstName')),
                LastName = String.valueOf(payload.get('lastName')),
                Email = String.valueOf(payload.get('email')),
                Company = String.valueOf(payload.get('company'))
            );
            insert newLead;

            return '{"status": "success", "recordId": "' + newLead.Id + '"}';

        } catch(Exception e) {
            return '{"error": "' + e.getMessage() + '"}';
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

2. Enable Remote Site Settings
`

Step 2: Set Up Google Apps Script

  1. Create the Webhook Handler
function onFormSubmit(e) {
  const sfEndpoint = 'https://yourdomain.salesforce.com/services/apexrest/form-submissions';
  const accessToken = getSalesforceToken(); // See Step 3 for OAuth setup

  const payload = {
    firstName: e.namedValues['First Name'][0],
    lastName: e.namedValues['Last Name'][0],
    email: e.namedValues['Email'][0],
    company: e.namedValues['Company'][0]
  };

  const options = {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + accessToken,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(sfEndpoint, options);
    const result = JSON.parse(response.getContentText());

    if (result.error) {
      Logger.log('Error: ' + result.error);
      sendErrorEmail(result.error); // Implement error handling
    } else {
      Logger.log('Success: Record ID ' + result.recordId);
    }
  } catch (error) {
    Logger.log('Connection Error: ' + error.toString());
  }
}

Enter fullscreen mode Exit fullscreen mode

2. Configure the Trigger
Open script editor in Google Forms
Go to Edit → Current project's triggers
Set:
Function: onFormSubmit
Event: On form submit
Failure notification: Daily

Section 3: Authentication Methods
Option A: Password-Based OAuth

function getSalesforceToken() {
  const loginUrl = 'https://login.salesforce.com/services/oauth2/token';

  const params = {
    method: 'POST',
    payload: {
      grant_type: 'password',
      client_id: 'YOUR_CONSUMER_KEY',
      client_secret: 'YOUR_CONSUMER_SECRET',
      username: 'salesforce@email.com',
      password: 'PASSWORD+SECURITY_TOKEN'
    }
  };

  const response = UrlFetchApp.fetch(loginUrl, params);
  return JSON.parse(response).access_token;
}

Enter fullscreen mode Exit fullscreen mode

*Option B: JWT Bearer Flow (Recommended for Production)
*

  1. Generate a self-signed certificate:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out cert.pem
Enter fullscreen mode Exit fullscreen mode
  1. Upload cert.pem to Salesforce: Setup → Certificate and Key Management
  2. Use this Apps Script function:
function getJWTAccessToken() {
  const jwtHeader = Utilities.base64Encode(JSON.stringify({
    "alg": "RS256",
    "typ": "JWT"
  }));

  const jwtClaim = Utilities.base64Encode(JSON.stringify({
    "iss": "YOUR_CONSUMER_KEY",
    "sub": "user@domain.com",
    "aud": "https://login.salesforce.com",
    "exp": Math.floor(Date.now()/1000) + 300
  }));

  const signature = Utilities.computeRsaSha256Signature(
    jwtHeader + "." + jwtClaim,
    "-----BEGIN PRIVATE KEY-----\n" + 
    "YOUR_PRIVATE_KEY\n" +
    "-----END PRIVATE KEY-----"
  );

  const jwt = jwtHeader + "." + jwtClaim + "." + Utilities.base64Encode(signature);

  const response = UrlFetchApp.fetch('https://login.salesforce.com/services/oauth2/token', {
    method: 'POST',
    payload: {
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      assertion: jwt
    }
  });

  return JSON.parse(response).access_token;
}

Enter fullscreen mode Exit fullscreen mode

Section 4: Testing & Debugging
Test Cases

Top comments (0)