Route submissions to Salesforce Web2Lead
This recipe configures a lead-capture form that creates a Salesforce lead on every submission using Salesforce’s Web2Lead feature. No Salesforce API credentials or connected app are required — Web2Lead uses a simple HTTP POST to a public Salesforce endpoint, controlled by an org ID embedded in the form data.
Prerequisites
- A deployed Webform Relay stack
- A Salesforce org with Web2Lead enabled
- Your Salesforce org ID (15 or 18 characters)
Enable Web2Lead in Salesforce
- In Salesforce, go to Setup → Feature Settings → Marketing → Web-to-Lead.
- Click Edit and check Web-to-Lead Enabled, then Save.
- Note your Org ID — find it under Setup → Company Information → Salesforce.com Organization ID.
Standard Salesforce field names
Web2Lead uses specific field names. Map your form fields to them in the
mapping block:
| Salesforce field | Type | Notes |
|---|---|---|
first_name | text | Lead first name |
last_name | text | Required by Salesforce |
email | Lead email address | |
phone | text | Phone number |
company | text | Company name |
city | text | City |
state | text | State/province |
country | text | Country |
description | textarea | Free-text description / notes |
lead_source | picklist | Usually set as a static value (e.g. Website) |
Finding custom field names
Custom field API names in Salesforce end in __c. To find the name Web2Lead
uses for a custom field:
- Setup → Object Manager → Lead → Fields & Relationships
- Click the field name, then note the Field Name value (e.g.
My_Custom_Field__c). - Use the lowercase, underscore version in Web2Lead:
my_custom_field__c.
Alternatively, generate a Web2Lead form in Salesforce (Setup → Web-to-Lead →
Create Web-to-Lead Form), inspect the generated HTML, and read the name
attributes.
Config
cache_ttl: 30s
forms:
lead:
fields:
- name: first_name
required: false
type: text
- name: last_name
required: true
type: text
- name: email
required: true
type: email
- name: company
required: false
type: text
- name: message
required: false
type: textarea
outputs:
- type: salesforce_web2lead
url: https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8
mapping:
first_name: first_name
last_name: last_name
email: email
company: company
description: message
static:
oid: "00Dxxxxxxxxxxxxxxx" # your Salesforce org ID
retURL: "https://yoursite.com/thank-you"
lead_source: WebsiteReplace 00Dxxxxxxxxxxxxxxx with your actual org ID.
The static fields
| Field | Purpose |
|---|---|
oid | Identifies your Salesforce org. Required. |
retURL | Where Salesforce redirects after a browser form POST. Not used when submitting via the relay (server-to-server), but Salesforce still validates that it looks like a URL. |
lead_source | Salesforce picklist value tagging the lead’s origin. Must match an existing picklist value in your org. Common values: Website, Web, Other. |
Form fields don’t match Salesforce field names
Use mapping to rename. In this example the form collects a single name
field, and the message textarea maps to description:
forms:
contact:
fields:
- name: name
required: true
type: text
- name: email
required: true
type: email
- name: message
required: false
type: textarea
outputs:
- type: salesforce_web2lead
url: https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8
mapping:
last_name: name # form "name" → Salesforce "last_name"
email: email
description: message # form "message" → Salesforce "description"
static:
oid: "00Dxxxxxxxxxxxxxxx"
retURL: "https://yoursite.com/thank-you"
lead_source: Websitemapping rules: salesforce-field-name: form-field-name. Only fields in the
mapping are sent — unlisted form fields are dropped.
Fan-out: also send an email notification
Add a second output to the same form to both create a Salesforce lead and send a notification email:
outputs:
- type: salesforce_web2lead
url: https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8
mapping:
last_name: name
email: email
description: message
static:
oid: "00Dxxxxxxxxxxxxxxx"
retURL: "https://yoursite.com/thank-you"
lead_source: Website
- type: email
to: sales@yourcompany.com
subject: "New lead from website"
mapping:
from_name: name
from_email: email
inquiry: messageBoth outputs run on every submission. If Salesforce accepts the lead but SES fails (or vice versa), the relay returns HTTP 500 and logs the error — but the successful output is not rolled back.
Test the config before going live
Validate locally:
bin/webform-relay --config webform.yaml config validate
# okSend a test submission to your deployed endpoint:
curl -v -X POST \
https://<api-id>.execute-api.<region>.amazonaws.com/api/v1/submit/lead \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "first_name=Test&last_name=User&email=test@example.com&company=Acme&message=Hello"A successful relay returns:
{"message": "ok"}Then verify in Salesforce: App Launcher → Leads — the test lead should appear within a few seconds.
Debugging a 500
Check CloudWatch logs:
task relay:logs:tailCommon errors:
| Log message | Likely cause |
|---|---|
http_post: unexpected status 400 | Missing oid or invalid org ID |
http_post: unexpected status 200 with no lead created | last_name is missing or empty (Salesforce silently drops the lead) |
http_post: no data to send | All mapping rules produced empty values; check field names |
http_post: request failed | Salesforce endpoint unreachable from Lambda |
Salesforce Web2Lead does not return an error response for invalid data — it returns HTTP 200 and silently discards the submission. If the lead doesn’t appear in Salesforce after a successful relay, double-check:
oidmatches your org exactly (case-sensitive)last_nameis mapped and non-empty in the submissionlead_sourcematches a valid picklist value in your org- Web2Lead is enabled in Salesforce Setup
Generate the HTML form
task build:cli
bin/webform-relay --config webform.yaml form html leadPaste the output <form> element into your HTML page. The action attribute
points to your deployed endpoint automatically.