---
title: Integration with Salesforce: Create Web-to-Lead Forms
product: Survey Creator
description: Integrate SurveyJS form builder with Salesforce to set up effective web-to-lead forms. Collect contact data from your potential clients and get it automatically sent to your CRM system as a new lead. Try out this live demo for JavaScript to learn more.
framework: Vanilla JS
source: https://surveyjs.io/survey-creator/examples/create-web-to-lead-forms-for-salesforce-crm/vanillajs
index: https://surveyjs.io/survey-creator/examples/overview.md
---

# Integration with Salesforce: Create Web-to-Lead Forms (Vanilla JS)

With SurveyJS Form Builder, you can easily create web-to-lead forms to capture essential lead information and submit it directly to your Salesforce CRM for further lead management by your sales team. This example demonstrates how to integrate the Form Builder with Salesforce to set up an effective web-to-lead form. Common Salesforce fields appear in the Form Builder's Toolbox, ready for you to drag and drop them onto the design surface to customize your form. Once completed, open the JSON Editor tab to view the survey JSON schema, which outlines the form's structure and layout. Feed this schema into the SurveyJS Form Library to render your web-to-lead form on a webpage. The code from this example can also be adapted to integrate SurveyJS with other Salesforce web forms or similar CRM platforms, including custom in-house systems.

## How to Integrate SurveyJS Form Builder with Salesforce

### Add Salesforce Fields to the Toolbox

Form Builder's Toolbox contains questions and panels that users can add to their forms.

1. Load a Salesforce field array from your server.          
Each object in this array should specify a field's name, title, description, and other properties relevant to this field. Open the Code tab and view the `salesforce.js` file for an example.

2. Construct toolbox items based on this array.         
Toolbox item configuration objects should implement the [`IQuestionToolboxItem`](https://surveyjs.io/survey-creator/documentation/api-reference/iquestiontoolboxitem) interface. These objects contain information about a toolbox item's name, title, category, tooltip, JSON object associated with the item, etc. Specify the objects' properties using information about Salesforce fields (see the `getSalesforceFields()`, `getQuestionJsonByField()`, and `getQuestionTypeByField()` functions). Make sure to assign a field's name to the [`valueName`](/form-library/documentation/api-reference/question#valueName) property in the `json` object. `valueName` specifies a property name that should store the question value. Setting `valueName` to the name of a Salesforce field ensures correct mapping between that field and the survey question based on it.

3. Add a [custom Boolean property](https://surveyjs.io/form-library/documentation/customize-question-types/add-custom-properties-to-a-form#add-custom-properties-to-an-existing-class) that identifies questions mapped to Salesforce fields.           
This property will be used to [restrict configuration capabilities](#disable-predefined-properties-in-property-grid) for such questions. Use the `Serializer.addProperty("question", propMeta)` method to add the custom property to all question types. Set this property to `true` in the JSON objects associated with Salesforce toolbox items.

4. Add Salesforce items to the Toolbox.         
Access the [`QuestionToolbox`](/survey-creator/documentation/api-reference/questiontoolbox) instance using Form Builder's [`toolbox`](/survey-creator/documentation/api-reference/survey-creator#toolbox) property and call the [`addItem(item, index)`](/survey-creator/documentation/api-reference/questiontoolbox#addItem) method on this instance. You can also customize toolbox settings to your preferences. For instance, this demo disables the [compact toolbox mode](https://surveyjs.io/survey-creator/documentation/api-reference/questiontoolbox#forceCompact), allows [multiple toolbox categories to stay expanded](https://surveyjs.io/survey-creator/documentation/api-reference/questiontoolbox#allowExpandMultipleCategories), and [displays category titles](https://surveyjs.io/survey-creator/documentation/api-reference/questiontoolbox#showCategoryTitles) (see the `setupToolbox()` function).

### Disable Predefined Properties in the Property Grid

The JSON objects associated with Salesforce fields include additional configuration properties that users shouldn't change so as not to break the preconfigured functionality. For example, the `valueName` property ensures correct mapping between Salesforce fields and survey questions. If users change the property's value, the mapping will break. To disable `valueName` and other predefined properties in the Property Grid, handle the [`onPropertyGetReadOnly`](https://surveyjs.io/survey-creator/documentation/api-reference/survey-creator#onPropertyGetReadOnly) event. Its `options.readOnly` parameter specifies whether the currently checked property is read-only. Set this parameter to `true` for the predefined properties. View the code listing for a code example.

## Render the Web-to-Lead Form on a Web Page

The content and layout of a web-to-lead form is described in a survey JSON schema. Form Builder users can view, edit, and copy it in the JSON Editor tab. To render the form on your web page, feed the JSON schema into SurveyJS Form Library.

- [Get Started with Form Library in Angular](/form-library/documentation/get-started-angular)
- [Get Started with Form Library in Vue](/form-library/documentation/get-started-vue)
- [Get Started with Form Library in React](/form-library/documentation/get-started-react)
- [Get Started with Form Library in HTML/CSS/JavaScript](/form-library/documentation/get-started-html-css-javascript)

## Handle Form Submission

Once potential clients fill out your web-to-lead form and click Complete, a data object with lead information should be sent to your Salesforce. Handle the [`onComplete`](https://surveyjs.io/form-library/documentation/api-reference/survey-data-model#onComplete) event in SurveyJS Form Library to modify the data object if required and send it to your server. This example shows how to identify Salesforce field values and create an individual object for them. To demo this functionality, open the Preview tab and fill out your form. You will see the resulting data object in the browser's console.

## Files

### `public/index.html`

```html
<!-- Uncomment the following lines to enable Ace Editor in the JSON Editor tab -->
<!-- 
<script src="https://unpkg.com/ace-builds/src-min-noconflict/ace.js"></script>
<script src="https://unpkg.com/ace-builds/src-min-noconflict/ext-searchbox.js"></script>
<script src="https://unpkg.com/ace-builds/src-min-noconflict/theme-clouds_midnight.js"></script>
-->

<div id="surveyCreatorContainer" style="position: absolute; height: 100%; width: 100%"></div>
```

### `src/index.css`

```css
/* You can add your custom CSS here. */
```

### `src/salesforce.js`

```js
// A list of Salesforce form fields. This list should come from a server.
export const salesforceFormFields = [
    { name: "address", title: "Address", description: "Street address for the lead, for example, 475 Boardwalk Ave. Up to 255 characters are allowed in this field.", maxLength: 255, type: "comment" },
    { name: "annual_revenew", title: "Annual Revenue", description: "Amount of annual revenue at lead's company.", type: "currency" },
    { name: "campaign", title: "Campaign", description: "Name of the campaign responsible for generating the lead. Displays only when creating a lead. Data entered in this field is stored in the Campaign History related list on the lead.", type: "lead_campaign" },
    { name: "city", title: "City", description: "City portion of the lead's address, for example, San Francisco. Up to 40 characters are allowed in this field.", maxLength: 40 },
    { name: "company", title: "Company", description: "Name of company with which lead is affiliated. Up to 255 characters are allowed in this field." },
    { name: "company_local", title: "Company Name (Local)", description: "Name of the company in the local language." },
    { name: "country", title: "Country", description: "Country portion of user's address. Entry is selected from a picklist of standard values, or entered as text. Up to 80 characters are allowed if the field is a text field.", type: "country" },
    { name: "description", title: "Description", description: "Description of the lead. Up to 32 KB of data is allowed in this field. Only the first 255 characters appear in reports.", type: "comment" },
    { name: "do_not_call", title: "Do Not Call", description: "Whether the contact wants to be contacted by phone.", type: "boolean" },
    { name: "email", title: "Email", description: "Email address of lead. Must be a valid email address in the form: jsmith@acme.com. Up to 80 characters are allowed in this field.", type: "email" },
    { name: "email_opt_out", title: "Email Opt Out", description: "Whether the lead wants to receive email (false) or not (true).", type: "boolean" },
    { name: "fax", title: "Fax", description: "Lead's fax number. Up to 40 characters are allowed in this field.", type: "phone" },
    { name: "fax_opt_out", title: "Fax Opt Out", description: "Lead hasn't requested to be included in broadcast faxes.", type: "boolean" },
    { name: "first_name", title: "First Name", description: "First name of the lead, as displayed on the lead edit page. Up to 40 characters are allowed in this field.", maxLength: 40 },
    { name: "first_name_local", title: "First Name (Local)", description: "First name of the lead translated into the local language.", maxLength: 40 },
    { name: "industry", title: "Industry", description: "Primary business of lead's company. Entry is selected from a picklist of available values, which are set by an administrator. Each picklist value can have up to 40 characters.", type: "industry" },
    { name: "last_name", title: "Last Name", description: "Last name of the lead, as displayed on the lead edit page. Up to 80 characters are allowed in this field.", maxLength: 80 },
    { name: "last_name_local", title: "Last Name (Local)", description: "Last name of the lead translated into the local language.", maxLength: 80 },
    { name: "lead_owner", title: "Lead Owner", description: "Assigned owner of the lead.", type: "users" },
    { name: "lead_record_type", title: "Lead Record Type", description: "Name of the field that determines what picklist values are available for the record. The record type can be associated with a lead process. Available in Professional, Enterprise, Unlimited, Performance, and Developer Editions." },
    { name: "lead_source", title: "Lead Source", description: "Source of lead, for example, Advertisement, Partner, or Web. Entry is selected from a picklist of available values, which are set by an administrator. Each picklist value can have up to 40 characters.", type: "lead_source" },
    { name: "lead_status", title: "Lead Status", description: "Status of the lead, for example, Open, Contacted, Qualified. Entry is selected from a picklist of available values, which are set by an administrator. Each picklist value can have up to 40 characters.", type: "lead_status" },
    { name: "mobile", title: "Mobile", description: "Cellular or mobile phone number. Up to 40 characters are allowed in this field.", type: "phone" },
    { name: "no_of_employees", title: "No. of Employees", description: "Number of employees at the lead's company.", type: "number" },
    { name: "phone", title: "Phone", description: "Lead's primary phone number. Up to 40 characters are allowed in this field.", type: "phone" },
    { name: "rating", title: "Rating", description: "Indicates value or prospect of the lead, for example, Hot, Warm, Cold. Entry is selected from a picklist of available values, which are set by an administrator. Each picklist value can have up to 40 characters.", type: "lead_rating" },
    { name: "saluation", title: "Salutation", description:"Title for addressing the lead, for example, Mr., Ms., Dr., or Prof. Entry is selected from a picklist of available values, which are set by an administrator. Each picklist value can have up to 40 characters.", type: "salutation" },
    { name: "state", title: "State/Province", description: "State or province portion of user's address. Entry is selected from a picklist of standard values, or entered as text. Up to 80 characters are allowed if the field is a text field.", maxLength: 80 },
    { name: "title", title: "Title", description: "Position of lead within his or her company. Up to 128 characters are allowed in this field. When converting a lead to a person account, the conversion fails if the lead Title field contains more than 80 characters.", maxLength: 80 },
    { name: "website", title: "Website", description: "URL of company's website, for example, www.acme.com. Up to 255 characters are allowed in this field; only the first 50 are displayed.", maxLength: 255 },
    { name: "zip", title: "ZIP", description: "ZIP code or postal code portion of the lead's address. Up to 20 characters are allowed in this field.", maxLength: 20 }
];
```

### `src/index.js`

```js
import { SurveyCreator } from "survey-creator-js";
import "survey-core/survey.i18n";
import "survey-creator-core/survey-creator-core.i18n";
import { Serializer } from "survey-core";
import { salesforceFormFields } from "./salesforce";
import "survey-core/survey-core.css";
import "survey-creator-core/survey-creator-core.css";
import "./index.css";
import SurveyTheme from "survey-core/themes";
import { registerCreatorTheme } from "survey-creator-core";

registerCreatorTheme(SurveyTheme); // Add predefined Survey Creator UI themes

// Add a property used to distinguish Salesforce fields from other fields
Serializer.addProperty("question", {
    name: "isSalesforceField:boolean",
    visibleIf: (obj) => obj.isSalesforceField,
    readOnly: true,
    category: "general",
    visibleIndex: 2,
    displayName: "This is a Salesforce field"
});

const salesforceToolboxCategory = "Salesforce Fields";
    
function getQuestionTypeByField (field) {
    const dropdownTypes = ["lead_campaign", "country", "industry", "users", "lead_source", "lead_status"];
    const fieldType = field.type;
    if (fieldType === "boolean") return "boolean";
    if (fieldType === "comment") return "comment";
    if (fieldType === "lead_rating") return "rating";
    if (dropdownTypes.indexOf(fieldType) > -1) return "dropdown";
    return "text";
}
function getQuestionJsonByField (field) {
    const json = {
        type: getQuestionTypeByField(field),
        title: field.title,
        isSalesforceField: true,
        // Ensures mapping between Salesforce fields and survey questions
        valueName: field.name
    };

    if (!!field.maxLength) {
        json.maxLength = field.maxLength;
    }

    if (field.type === "currency") {
        json.maskType = "currency";
        json.maskSettings = { prefix: "$" };
    }

    if (field.type === "number") {
        json.maskType = "number";
    }

    if (field.type === "phone") {
        json.inputType = "tel";
    }

    if (field.type === "email") {
        json.inputType = "email";
    }

    if (field.type === "country") {
        json.placeholder = "Select a country...";
        json.choicesByUrl = {
            url: "https://surveyjs.io/api/CountriesExample",
        };
    }

    if (field.type === "salutation") {
        json.dataList = ["Mr.", "Ms.", "Dr.",  "Prof."];
    }

    if  (field.type === "lead_rating") {
        json.rateValues = ["Cold", "Warm", "Hot"];
    }

    if (field.type === "lead_status") {
        json.choices = ["Open", "Contacted", "Qualified"];
    }

    if (field.type === "lead_source") {
        json.choices = ["Advertisement", "Partner", "Web"];
    }
    
    // Industries, campaigns, and users should come from a database
    if (field.type === "industry") {
        json.choices = ["Accounting", "Construction", "Education"];
    }

    if (field.type === "lead_campaign") {
        json.choices = [
            { value: "A101", text: "Campaign 1" },
            { value: "B131", text: "Campaign 2024" },
            { value: "N456", text: "New Campaign" }
        ];
    }

    if (field.type === "users") {
        json.choices = [
            { value: "U101", text: "Elizabeth Backer" },
            { value: "U254", text: "John Snow" },
            { value: "U567", text: "David Miller" }
        ];
    }

    return json;
}
    
function getSalesforceFields () {
    const items = [];
    salesforceFormFields.forEach(field => {
        const item = { 
            name: field.name,
            category: salesforceToolboxCategory,
            title: field.title, 
            tooltip: field.description,
            json: getQuestionJsonByField(field)
        }
        items.push(item);
    });

    return items;
}
    
function setupToolbox (toolbox) {
    const salesforceItems = getSalesforceFields();
    salesforceItems.forEach(item => {
        toolbox.addItem(item);
    });
    
    toolbox.allowExpandMultipleCategories = true;
    toolbox.showCategoryTitles = true;
    toolbox.forceCompact = false;
    toolbox.expandCategory(salesforceToolboxCategory);
}

const propertiesToDisable = ["valueName", "inputType", "maskType", "maxLength", "choices"];
    
function setupEventHandlers (creator) {
    // Disable properties that shouldn't be changed for Salesforce fields
    creator.onPropertyGetReadOnly.add((_, options) => {
        if (!options.readOnly && options.element.isSalesforceField) {
            options.readOnly = propertiesToDisable.indexOf(options.property.name) > -1;
        }
    });
    // Fill in the question name with the `valueName` property value 
    creator.onQuestionAdded.add((_, options) => {
        const q = options.question;
        if (q.isSalesforceField && !creator.survey.getQuestionByName(q.valueName)) {
            q.name = q.valueName;
        }
    });
    creator.onSurveyInstanceSetupHandlers.add((_, options) => {
        if (options.area === "preview-tab") {
            // Use this code in SurveyJS Form Library to submit the form data
            options.survey.onComplete.add((survey) => {
                const salesforceFields = [];
                const data = survey.data;
                // Use the following code if you need to distinguish Salesforce fields' data from other field values.
                // Otherwise, simply submit the `survey.data` object.
                for (let key in data) {
                    const q = survey.getQuestionByName(key);
                    if (q && q.isSalesforceField) {
                        salesforceFields.push({ name: key, value: q.value });
                    }
                }
                const response = { salesforce: salesforceFields, data: data };
                // ...
                // Submit the form data to your server here
                // ...
                console.log(JSON.stringify(response, null, 3));
            });
        }
    });
}
const creator = new SurveyCreator();

setupToolbox(creator.toolbox);
setupEventHandlers(creator);
creator.JSON = {};
creator.render("surveyCreatorContainer");
```

### `package.json`

```json
{
  "dependencies": {
    "survey-core": "latest",
    "survey-js-ui": "latest",
    "survey-creator-core": "latest",
    "survey-creator-js": "latest"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/survey-creator/examples/create-web-to-lead-forms-for-salesforce-crm/angular.md)
- [React](https://surveyjs.io/survey-creator/examples/create-web-to-lead-forms-for-salesforce-crm/reactjs.md)
- [Vue 3](https://surveyjs.io/survey-creator/examples/create-web-to-lead-forms-for-salesforce-crm/vue3js.md)
- [jQuery](https://surveyjs.io/survey-creator/examples/create-web-to-lead-forms-for-salesforce-crm/jquery.md)
