Create a Custom Web Form Handler With Sites

No doubt you’ve run into this also…we needed a form handler that captured data for sObjects other than Cases or Leads (e.g. custom objects), we did not want to redirect visitors to a new page upon form submission, and our functional requirements were more complex than what the standard Salesforce form handlers could support. The standard Salesforce Web-to-Lead and Web-to-Case form handlers were not an option, so we had to create our own custom web form handler. And because we wanted to keep everything on, we decided to build this solution using VisualForce pages and an Apex controller served by Sites. We developed an alternative solution and wanted to share it with the community in the event it could help others.

Use case

You want to capture form data directly in Salesforce from either a VisualForce page served Sites or from an externally hosted page, but the standard Web-to-Lead or Web-to-Case web handlers do not meet your exact requirements. You may also be using custom JavaScript forms that post data using AJAX, and do not want to blindly pass data to a form handler that will not provide a return to indicate success or exceptions.

Ultimately, we wanted to expose our form handler so it could also be accessed by any of our forms on the web ( Sites as well as others such as our WordPress blog, which uses an HTML / PHP-based form to collect data).

So, here’s what we did

To begin, you need to ensure that Sites is setup correctly if it is not already.  You can find information on creating and maintaining Sites here or here.  In our case, we created a “utility” Site so that we could keep the pages separate from our main Sites web pages.  We also concealed the Sites utility subdomain in our custom Site.URLRewriter implementation to avoid AJAX cross-domain issues, but that is a discussion for a future post.

You will need to code up a VisualForce Page and an Apex class to serve as a custom controller to capture the form data and cast values to specific fields in the target sObject.  The VisualForce page itself is very simple in its construct…essentially it will serve two purposes:

  1. Perform a specific Action that calls a PageReference method in the custom controller when the page is invoked.
  2. Return a value in a format that the process calling the form handler is expecting.  In our case, our AJAX method is expecting a JSON object with the result of the form submission (success or otherwise).

This is what the VisualForce page for the form handler that we use for looks like:

<apex:page  cache="false" controller="formHandlerSample" action="{!processForm}" showheader="false" contentType="application/jsonrequest">

	{success: {!success}}

The elements of this page to take note of:
  1. The ‘controller’ attribute is the custom Apex class that contains the logic that will process the contents of the web form
  2. The ‘action’ attribute is the PageReference method contained in the Apex class that will process the form data and generate the required return string
  3. Because our AJAX script is looking for a JSON object to be returned, we declared the contentType of ”application/jsonrequest.” You may find that you need to return XML, HTML, or other text, so update this attribute to suit your specific requirements.

The form handler code:

public class formHandlerSample {

	public <String, String> urlParams;
	public String Error {get; set;}
	public Lead formLead = new Lead();

	public formHandlerSample() {
		urlParams = ApexPages.currentPage().getParameters();

	public Boolean Success {
		get {

			if(Success == null) {
				Success = false;

		return Success;



	public void processLead(Map<String, String> formFields) {

		if(formFields.size() > 0) {

			try {

				for(String fieldKey : formFields.keySet()) {

					if(fieldKey != null && fieldKey != 'null'){

						if(fieldKey == 'FirstName'){
							formLead.FirstName = formFields.get(fieldKey);

						if(fieldKey == 'LastName'){
							formLead.LastName = formFields.get(fieldKey);

						if(fieldKey == 'Title'){
							formLead.Title = formFields.get(fieldKey);

						if(fieldKey == 'Company'){
							formLead.Company = formFields.get(fieldKey);

						if(fieldKey == 'Phone'){
							formLead.Phone = formFields.get(fieldKey);

						if(fieldKey == 'Email'){
							formLead.Email = formFields.get(fieldKey);

						if(fieldKey == 'Description'){
							formLead.Description = formFields.get(fieldKey);

				upsert formLead;
				Success = true;


			catch(System.Exception e) {
				System.debug('Houston, you have a problem: ' + e);
				Success = false;
				Error = String.ValueOf(e);


		else {
			Success = false;
			Error = 'No form fields received';


	public PageReference processForm(){
		return null;

Mike Topalovich Salesforce Technical Architect in Chicago
Mike Topalovich - Salesforce Certified Platform Developer I Mike Topalovich - Salesforce Certified Platform Developer II Mike Topalovich - Salesforce Certified Developer Mike Topalovich - Salesforce Certified Advanced Developer
Mike Topalovich - Salesforce Certified Mobile Solutions Architecture Designer Mike Topalovich - Salesforce Certified Platform App Builder Mike Topalovich - Salesforce Certified Administrator Mike Topalovich - Salesforce Certified Advanced Administrator
Mike Topalovich
Hi, I’m Mike. I help companies like yours do business in new ways with Salesforce.

I am a freelance Salesforce Developer, Architect, and CTO as well as a part time instructor for Salesforce University.

Connect with me today to discuss how I can become a part of your team on an ongoing retainer basis.
Mike Topalovich on EmailMike Topalovich on FlickrMike Topalovich on LinkedinMike Topalovich on RssMike Topalovich on Twitter

Comments Closed

Comments for this post are now closed.