Showing posts with label Tutorial. Show all posts
Showing posts with label Tutorial. Show all posts

Wednesday, August 31, 2011

Creating an APEX trigger in Salesforce.com

To start off the first day of DreamForce 2011 I am posting a "how to" on creating an APEX trigger in Salesforce.com.  Recently the business approached me with a need.  Currently we get leads from a vendor via the web-to-lead process.  This process works great but the business wanted a way for the leads that are created to show up in the associated agent's calendar.

In scoping out how to meet the need of the business I had to research what fields the vendor is populating and what fields are required and so forth.  First off, I determined that the best process to display an activity in the agent's calendar was to create a trigger on the lead object that can create an entry into the event object.  The fields that the vendor is populating that would provide value to this process are: FirstName, LastName, remote_Rep_Assigned__c (custom field that the vendor puts the name of the assigned agent and must match the name of a Salesforce user), LeadSource, Appointment_Date_Time__c (custom field that the vendor puts the event date/time in UTC time), and company.

Requirements:
- Setup the trigger to only create leads when the LeadSource has a specific value.
- Query the users object to match the provided name of the agent provided to by the vendor to a Salesforce user
- If a Salesforce user match is not found do not create an event
- The Appointment_Date_Time__c field is not required, if this field does not have a value do not create an event

This is a basic example of creating an APEX trigger which may be a good start in learning the basics for more advanced coding.

There are a few ways to go about coding, and testing your code.  My preferred method is to use the eclipse IDE with the force.com addin.  You can see instructions on the different methods currently available (http://wiki.developerforce.com/index.php/Force.com_IDE_Installation) (though in DreamForce today we saw the new web-based APEX code interface).  You will also either need to create a force.com developer account (free) or if you have an enterprise license create a sandbox for development.  You will not be able to code directly to your production site for security and performance purposes.

Parts of the instructions will be specific to eclipse though the Force IDE has a similar process.  Open eclipse, go to File->New->Project.  Open the Force.com folder and select "Force.com Project" and click next.  For the "Project Name" I entered "CreateEventFromLead".  You will need to know your user name, password and security token along with selecting the appropriate account type.  If your login information is correct you should get a screen to allow you which meta data objects to download (this is needed to help with progamming).  The default should be "APEX and VisualForce" leave this marked and click "Finish"  The interface will take a few moments to download the necessary meta data and setup the work space.

Once the desktop is created, you should see a new package in the "package explorer" tab called "CreateEventFromLead" (or what ever name you named it).  Open the folder called "src".  Right click on the "triggers" folder and select Force.com->New Apex Trigger.  You will see the trigger configuration window.  I gave the trigger the name of CreateEventFromLead, in the object drop down selected Lead and selected the "After Insert" option (we only want this trigger to trigger after a new lead is created).

You should now have a new sheet with the shell of the trigger statement in it.  Now starts the fun part.  One thing to note is that it is possible for a trigger to be processed for multiple leads at the same time.  This is very different if you are use to the normal RDMS environments where a trigger and ran for each insert statement.  In Salesforce for batch jobs a trigger could process multiple insert statements at the same time.  This is a performance and efficiency element.  Because of this we must setup the trigger to be able to process multiple items so a loop is needed.  We will start off with adding a "for" loop.  Our trigger statement should look similar to the following.
trigger CreateEventFromLead on Lead (after insert) {
 // Create a for loop to cycle through the number of leads inserted.
 //  Documention that I have come across says that typically only one record is
 //  inserted at a time except for bulk operations
 for (Lead lead : System.Trigger.new) {

 } // End of for (Lead lead : System.Trigger.new) statement
} // End of trigger CreateEventFromLead
Next I need to get the full name for the contact in the lead.  Because the FirstName field is not required I need to create a variable for this value and then perform some checks to get the info.  First I create a variable named "leadName" and then create an "if"/"else" structure to populate the variable based upon whether the FirstName field is populated.
 string leadName;
  // Check to see if the lead "name" value is null
  if(lead.FirstName == null) { // Check to see if the first Name value is null
   // If the First Name value is null the only put the last name
   //  into the variable
   leadName = lead.LastName;
  } else { // If the first and last name fields have a value then populate the variable with both values
   leadName = lead.FirstName + ' ' + lead.LastName;
  }
After this I needed to create a variable to store events records that we want to create so that we can insert them into the event object in Salesforce.
// Create a new variable to store events that need to be created
list<event> newEvents = new list<event>();
// Insert newEvents collection into salesforce.com
insert newEvents;
We now come to the first check.  We run a query to search for any user objects that match the agent name that the vendor provided in the Remote_Rep_Assigned__c field.  In between the variable declaration and the insert statement we will add the following code.

// Create a for loop to query salesforce to get a user record that matches the
  //  value in the Remote_Rep_Assigned field
  for (User user : [SELECT Id FROM User WHERE Name = :lead.Remote_Rep_Assigned__c LIMIT 1]) {
   // Create a variable to store the user Id value from the user record
   Id userId = user.Id;

   // If the userId variable has a value then continue with the code
   if(userId != null) {

   } // End of if(userId != null) statement
  } // End of for (User user... statement
We now come to the part to put in our business rules on when to create the event.  We should be to the part where we have a valid user.  Based upon the requirements from the business we only want create an event if the LeadSource has a certain value, for this exersize we will use the value of "Inbound".  We also have the rule to only create the event if there is a value in the Appointment_Date_Time__c.  Within the "If" structure to see if there is a userId we want to add the following.  First we create a boolean variable and set it to False.  We will use this variable while we go through our business rules to see if we want to create the event.
// Create a variable to set whether an event should be created based upon the collowing conditions
    boolean createEvent = false;

    // This is the condition logic to determine whether an event should be created
    //  If an additional conditions should be created use the following template
    //  Replace the pattern [value] with the value of the lead source that should be pulled into this process
    // ***********
    // else if(leadSource == '[value]') {
    //   createEvent = true;
    // }
    // ***********
    if(leadSource == 'Inbound') {
     // Set createEvent variable to true which will cause the event to be generated
     createEvent = true;
    } // End of if(leadSource == 'West') statement

    if(lead.Appointment_Date_Time__c == null) {
     createEvent = false;
    } // End of if(lead.Appointment_Date_Time__c == null) statement
If our lead object passes all the business rule checks then we want to create the event.  First we put in an "if" structure to check our variable to see if the process should create the event.  If the checks are valid then we create a new event and assign some values.  I also added a try/catch structure just to make sure we do not get any errors (though we should have enough checks in place to not need this it is good to be on the safe side.
// If one of the conditions set the createEvent variable to True then execute the code to create the event
    if(createEvent) {
     // With the newEvents variable that was setup to store new events
     //  We call the "add" function. This function takes a parameter for an event variable
     //  We create a new event variable within the add function call.  The new
     //  Event variable creation process takes parameters to populate certain values with values
     //  that we pass to it.
     try {
      newEvents.add(new Event(
       // Pass the Id value for the user that matched what the third party sent to the owner Id
       //  This will assign the event to the user so that it shows up on their calendar in salesforce.com
       OwnerId = userId,
       // Pass the appointment datetime value passed from the third party in the lead
       //  to the event's date/time value
       ActivityDateTime = lead.Appointment_Date_Time__c,
       // Pass the Id of the lead to the WhoId value for the event.  This will assign the event
       //  to the lead so that it shows up in the lead view as well as allowing the lead info to be
       //  visible in the event details
       WhoId = lead.Id,
       // Passes the duration value of the event.  The third party does not pass a value
       //  so we are defaulting this value to 60 minutes
       DurationInMinutes = 60,
       // Passes a custom value into the subject line of the event to provide needed details
       //  for the owner of the event
       Subject = 'Call ' + leadName + ' with ' + lead.Company
       ) // End of new event
      ); // End of newEvent add funciton
     }
     catch(Exception e){
      system.debug(e + ' user id:' + userId + ' DateTime:' + lead.Appointment_Date_Time__c + ' lead Id:' + lead.Id);
     }
    } // End of if(CreateEvent) statement

This the completion of the trigger code.  Now comes the pain.  In order to be able to prepare the code for production we have to create test cases the cover at least 75% of the code.  There is a lot of information out on the web on how to do this but I still had a hard time with it.  I did a lot of testing and playing around until I was able to come up with test cases that would work.  In fact I spent more time on the test cases than I did on the actual code.

First, you right click on the "classes" and select Force.com->New APEX Class.  Give it a name, I called it ConvertEventFromLeadTest and gave it the template "Test Class".  This will create the class shell and include the @isTest assignment to the class.  The purpose of this test class is to pass values to the trigger to make sure that everything test out.  You should try to make it as dynamic as possible so that it can fit any scenario.  This class has the comments in the code sufficient to explain what is going on.  The big element was creating a loop for a controlled number of test records that would force the LeadSource to be the one we want in some situations and under others to pick one of the other defined LeadSources.
@isTest
private class CreateEventFromLeadTest {
    static testMethod void myUnitTest() {
        // Perform our data preparation.
     List<lead> leads = new List<lead>{};
     List<schema.picklistentry> leadSources = Lead.LeadSource.getDescribe().getPicklistValues();
     User user = [SELECT Id, Name FROM User WHERE IsActive = true LIMIT 1];
     string userName = user.Name;
    
     Integer iPicklist = 0;
    
     for(Schema.Picklistentry pick : leadSources) {
      iPicklist++;
     }
    
     Integer leadSourceCounter = 0;
     for(Integer i = 0; i < 60; i++){
      Integer days = Math.round(Math.random()*10.0);
    
      date dt;
      date tday = date.today();
    
         Lead l = new Lead();
         if(i<10) {
          l.FirstName = 'test';
          l.LastName = 'lead ' + i;
          l.LeadSource = 'Inbound';
         }
         else {
          l.LastName = 'test lead ' + i;
          l.LeadSource = leadSources[leadSourceCounter].getLabel();
         }
         Integer remainder = math.mod(i, 2);
         if(remainder==0) {
          dt = tday.addDays(days);
         }
         else {
          dt = null;
         }
         l.Email = 'test' + i + '@test.com';
        
         if(leadSourceCounter > iPicklist-1) {
          leadSourceCounter = 0;
         }
         l.Remote_Rep_Assigned__c = userName;
         l.Appointment_Date_Time__c = dt;
         l.Company = 'test company ' + i;
         l.Description = 'This Lead is probably left over from testing. It should probably be deleted.';
         leads.add(l);
        
       leadSourceCounter++;
     }

     // Start the test, this changes governor limit context to
     // that of trigger rather than test.
     test.startTest();
 
     // Insert the Lead records that cause the trigger to execute.
     insert leads;
 
     // Stop the test, this changes limit context back to test from trigger.
     test.stopTest();
 
     // Query the database for the newly inserted records.
     List<lead> insertedLeads = [SELECT FirstName, LastName, Description
                                       FROM Lead
                                       WHERE Id IN :leads];
 
     // Assert that the Description fields contains the proper value now.
     for(Lead l : insertedLeads){
       System.assertEquals(
         'This Lead is probably left over from testing. It should probably be deleted.',
         l.Description);
     }
 
     // Query the database for the newly inserted records.
     List<event> insertedEvents = [SELECT Subject
                                       FROM Event
                                       WHERE WhoId IN :leads];
 
     // Assert that the Description fields contains the proper value now.
     for(Event e : insertedEvents){
       System.assert(true);
     }
    }
}
Once the test class is done, you can right click on the class and select Force.com->Run Tests.  This will run the test cases against the trigger and provide all the results.  If everything is successful you are now ready to package the code for production.

Monday, February 7, 2011

Create a Dynamic Menu in HTML

Recently I was asked by a co worker to assist in creating a navigation menu for a web site.  The requirement was that it needed to be able to read from an XML file (specifically a sitemap file from Visual Studio).  You may be wondering why we did not use the menu object within Visual Studio.  Visual Studio has a lot of useful objects for creating fast and robust web pages though there are times where it is better to use other methodologies.  One of those is when it comes to speed and simplicity.  Using the menu object can at times slow down the rendering of a page and the transitions can at times be slow.  There is a lot of over-head involved and if all of those features are not needed it is better to just use HTML, javascript and CSS.

Since I am not one for recreating the wheel, I looked into my “bag of tricks” and found a link to a solution that I came across previously that could help to fulfill this need, or at least partially with some modifications.  There is a great article provided by “Dynamic Drive” for a “Smooth Navigation Menu.”  This a very good set of code that is very flexible in allowing a person to present a menu in a lot of different ways.  I am not going to go into all the code that is used to create this solution, just the options that are there to configure it.  This is a very light weight and fast solution.  Now you may be thinking if this article is so good then why continue reading this one.  And the reason is that I added some enhancements to this.  The solution does not have the ability to read in an XML file.  It is based upon the use of a prebuilt un-order list html block.

First off, I changed some of the names in the solution to better fit our naming conventions (smoothddmenu to dynamicmenu in the js file and the name of the div to menu-ajax).  If you are not strong in javascript then I do not recommend doing this, though if you are like me and want to have all naming conventions through out your environment to be consistent and are comfortable with javascript then have at it.

After cleaning up some of the names in the file it was time to add some new functions to the script file to handle the xml reading and parsing.  At the end of the script file add the variable below to define the xml activeobject object.
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
Next we need to create a function that will return the readystate for the xmldoc read.
function verify() {
        if(xmlDoc.readyState!=4)
                return false;
}
This will provide the libraries needed to work with a XML file.  Next you will need a function to load a XML file using a file name into the variable.  This function makes sure that async is turned off, sets the readystatechange value to verify and then loads the file with the path provided in the function call.
function loadXML(xmlFile) {
        xmlDoc.async="false";
        xmlDoc.onreadystatechange=verify;
        xmlDoc.load(xmlFile);
}
Next we need to create the function that will parse the XML document.  The smooth menu needs an un-ordered list HTML block so we need to take the XML document and render it as an un-ordered HTML block.  Also there are three key attributes in the xml elements that we will be using, url, title and description.  These will be put into “a” HTML tag within the “li” elements in the un-ordered HTML block.  The url element value will be used as the href, the title will be used as the value displayed and the description will be the title (html not XML – used as a hover over description for the item) attributes for the tags.  I am going to use a VC style sitemap file for a source though it is not important what you use to make the file or ever what the names of the tags are as long as the elements are the same.
function readXML(xdoc) {
        if(xdoc.hasChildNodes()) {
        if(xdoc.getAttribute("title") != null)
        {
                    document.write("<li>");
                    document.write("<a href='");
            document.write(xdoc.getAttribute("url"));
                    document.write("' title='");
            document.write(xdoc.getAttribute("description"));
            document.write("' >");
                    document.write(xdoc.getAttribute("title"));
                    document.write("</a>");
        }
            document.write("<ul>");
                var nodes=xdoc.childNodes.length;
                for(var i=0; i<xdoc.childNodes.length; i++)
        {
                        readXML(xdoc.childNodes(i));
        }
            document.write("</ul>");
        if(xdoc.getAttribute("title") != null)
        {
                    document.write("</li>");
        }
        }
        else
    {
        if(xdoc.getAttribute("title") != null)
        {
                    document.write("<li>");
                    document.write("<a href='");
            document.write(xdoc.getAttribute("url"));
                    document.write("' title='");
            document.write(xdoc.getAttribute("description"));
            document.write("' >");
                    document.write(xdoc.getAttribute("title"));
                    document.write("</a>");
                    document.write("</li>");
        }
    }
}
Lastly, we need a function that will initialize the functions we just created that the HTML document can call and pass the file name.  This will pass the file name, call the function to load that file to the variable, and then pass a XMLDocumentElement to the parsing function.
function initXML(file) {
        loadXML(file);
        var xdoc=xmlDoc.documentElement;
        readXML(xdoc);
}
Now that the additions to the js script have been added it is time to create the HTML file for your web page.  First you need to add your document type declaration (this is not required though it is best practice and helps browsers to more easily render your page which will increase speed to load the page).  Then create the “HEAD” tags with the links to the CSS and java script files.  If you read the smooth menu article there are three files to download and it would be good to download a copy of the jquery script.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22>
<html xmlns="http://www.w3.org/1999/xhtml%22 lang="en" xml:lang="en">
<head>
<title>menu sample</title>
<link rel="stylesheet" type="text/css" href="menu.css" />
<link rel="stylesheet" type="text/css" href="menu-v.css" />
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="menu.js">
</head>
<body>
</body>
</html>
As you can see from the below code there is not much to this page so far, in fact you will not see anything.  Next we need to create the XML file so that we have something to parse.  I created a file called SiteMap.xml which has the following in it.  This file is stored in the same folder at the HTML that I will render it on.
<?xml version="1.0" encoding="utf-8"?>
<siteMap>
  <siteMapNode url="#" title="Home" description="" />
  <siteMapNode url="#" title="Links" description="">
    <siteMapNode url="http://www.dynamicdrive.com/dynamicindex1/ddsmoothmenu.htm%22 title="Dynamic Drive" description="" />
    <siteMapNode url="http://w3schools.com%22/ title="w3schools" description="" />
  </siteMapNode>
  <siteMapNode url="#" title="List 1" description="">
    <siteMapNode url="#" title="List Item 1" description="" />
    <siteMapNode url="#" title="List Item 2" description="" />
    <siteMapNode url="#" title="List 2" description="" >
       <siteMapNode url="#" title="List Item 3" description="" />
       <siteMapNode url="#" title="List Item 4" description="" />
       <siteMapNode url="#" title="List Item 5" description="" />
       <siteMapNode url="#" title="List Item 6" description="" />
    </siteMapNode>
  </siteMapNode>
</siteMap>
Back to our HTML file, between the “BODY” tags you will need to add a division block (identified by “DIV” tags).  Within the division you will need a script block that will call the initXML function and pass the name of the sitemap.xml file.
<div id="menu-ajax">
<script language="JavaScript">
    initXML("SiteMap.xml");
</script>
<noscript>
<a href="link to site map for search engines and user with JS disabled">Site map</a>
</noscript>
</div>
If you were to run the HTML file now it will not have the menu but will display an un-order list HTML block (see below).
image
We now need to add a script block in the “HEAD” block that will change our un-ordered list to the menu object that we want.  Within the smooth menu code there is a variable called ddsmoothmenu (if you made changes like I did then you may need to change some of these values).  The variable has a function called “init” which is what we want to call.  We are also passing some values to the function that would control the behavior of how this is displayed.  I will not go into all the parameters and what they mean.  The descriptions should be sufficient enough.
<script type="text/javascript">
smoothmenu.init({
mainmenuid: "menu-ajax", //menu DIV id
orientation: 'h', //Horizontal or vertical menu: Set to "h" or "v"
classname: 'ddsmoothmenu', //class added to menu's outer DIV
contentsource: "markup" //"markup" or ["container_id", "path_to_menu_file"]
})
</script>
Once this has been added, if you run the HTML file it should look similar to the following.
image

Friday, January 7, 2011

Create an external SalesForce Web to Lead form

No matter how good or flexible a CRM tool is, there are times where you will want/need a process of automating the entering of leads from an external source.  In our environment it is cost prohibitive to give all our employees in the contact centers SalesForce licenses.  So we created some web-to-lead web pages that will allow those agents to enter lead info and have it pushed to SalesForce for tracking and lead management.  For organizations where at times there is a need to contract with external sources like West for lead generation who have their own system and you do not want to purchase licenses for then they can also use this process to create lead entries in your SalesForce environment.

SalesForce has a web-to-lead process that works quite nicely.  I will walk you through the process of creating a web to lead document and then making it usable.

Go to the “setup” of you SalesForce instance.  In the “App Setup” open the “Customize” section then open “Leads” then click on “Web-to-lead”.  There are some basic settings that you can configure from this screen.  You can turn on or off the web-to-lead feature, assign the default lead creator and assign default email templates for auto responses.  From this screen click on the “Create Web-to-lead Form” button.

image

The next screen you can select the elements that you want visible for the user to populate.  I am going to leave the defaults for simplicity though you can select any of the standard objects or custom objects you have created in the leads object.  The bottom URL box is used to provide the address that you want the user to see after the lead has been posted.

A note about how this process works.  When the user “submits” the form with the filled in information the page and its data is forwarded to SalesForce where the data is processed and then the page redirects to the provided URL.  There is nothing to denote to the user whether the post to SalesForce was successful or not.  Typically there are not any issues though we have seen times when leads were not always getting through.

image

Once you click “Next” you are taken to the screen where the HTML needed to post the lead is created.  The generated code is very simplistic and there are no formatting applied.  It works but is ugly and not very usable.  Copy the code and paste it into your preferred HTML editor.  My preference is notepad though there are many very good free html editors available.  Click “finished” when you are done copying the html code.

image

I saved the code as webtolead.html.  A sample of what is generated is below.  The hidden web elements are very important and the names of the elements are very important and must not change or data will not transmit properly to SalesForce.

image

This web form is rendered as below.

image

Let’s see if if this page works.  I filled out the page using the values in the image below.

image

Sometimes it can take a bit for the lead to show up in the list.  I logged into my development site and opened my leads and I can see the new lead in the list.  As you can see all the info that I entered in the web-to-lead form populated in the lead record perfectly.  One thing to note is that there are a lot of assignment and workflow rules that you can apply to these to determine how they are assigned.  I will not get into those at this time.

image

This is functional but is not user friendly, there is no branding applied and it opens the possibility of entering bad data since there are no controls associated to it.  I will show some basic techniques to jazz this up though this is not a full tutorial on HTML development since that would take a lot more room and concentration for that effort.

There have been times when there was a need to troubleshoot the code because we would submit a lead but it would not show up in SalesForce.  There are some options that we can turn on to help with that troubleshooting.  Below are the tags that can be added anywhere within the form tags.
<input type="hidden" name="debug" value="1" />
<input type="hidden" name="debugEmail" value=youremail@email.com />
Adding these tags will present the following page when submitting the lead instead of redirecting to the redirect URL.  Also an email will be sent to the address provided in the second debug tag.  This email will have a link to the lead record in SalesForce.

image

For the rest of this tutorial I will be removing the debug tags for ease of use.

The first thing to do is add some of the elements that are needed for a properly designed web page (it will work as is but best practice is to add some additional elements). If you are not familiar with HTML this may be a little hard to follow.  Each web page should contain a tag that tells the web browser what type of document it is and the format that it is organized in.  For more information about this you can browse the internet for additional elements.  Below are the elements that I chose to use.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22>
<html xmlns="http://www.w3.org/1999/xhtml%22>
Next a closing “</html> tag needs to be added to the very end of the code.

The next element that should be added is the "head” element.  This is the section where you define what titles show, links to scripts, style files, page icons and so forth.  The first “notes” section that is generated can be removed and in its place the <head> tag should be added.  After that tag we want to add a title tag to customize the page a little. 
<title>Web-to-lead eForm</title>
That would leave the entry that starts with “<META” to come next.  After that the next message can be removed and replaced with the closing “</head>” tag.

The next section that normally comes in the body of the page.  We already have a form defined in the generated code.  We need to add the tag <body> just prior to the <form> tag and then add the closing </body> tag just after the closing </form> tag and before the closing </html> tag.

So far all the changes we have made are administrative with the exception of the title and do not do much to pretty up the page though they help the browser to better be able to read the html and set the stage for additional changes.

First thing that I like to do is add a little branding.  Branding is important because it helps to let the user know what company this lead form is for.  I found an image of a tree that I had on my desktop and I am going to use that as my image and I am going to add a header name that corresponds to the image for my fictitious company The Gnarled Tree.  Below the <body> tag that we created previously I added the following code which consists of a table, one row, three cells, and image in the first cell, the header in the second cell and nothing in the third (it is used primarily for spacing purposes).
<table width="100%">
<tr>
<td width="128">
<img src="gnarledtree.png" alt="GnarledTree" />
</td>
<td width="*" align="center"> <h2>The Gnarled Tree</h2>
</td>
<td width="128">
</td>
</tr>
</table>
With the changes the page now looks like the following.

image

Next I would organize the entry fields in to a format that is appealing and user friendly.  I like to organize fields by subject type into sections.  I made two tables one with contact details and the other with company details.  All of the information between the two form tags now looks like the below.

<input type=hidden name="oid" value="00DC0000000PU9Q">
<input type=hidden name="retURL" value="http://salesforce.com%22/>
<b>Contact Information</b>
<table>
<tr>
<td align="center"><label for="first_name">First Name</label></td>
<td align="center"><label for="last_name">Last Name</label></td>
<td align="center"><label for="email">Email</label></td>
</tr>
<tr>
<td><input  id="first_name" maxlength="40" name="first_name" size="20" type="text" /></td>
<td><input  id="last_name" maxlength="80" name="last_name" size="20" type="text" /></td>
<td><input  id="email" maxlength="80" name="email" size="20" type="text" /></td>
</tr>
</table>
<br />
<b>Company Information</b>
<table>
<tr>
<td align="center"><label for="company">Company</label></td>
<td align="center"><label for="city">City</label></td>
<td align="center"><label for="state">State/Province</label></td>
</tr>
<tr>
<td><input  id="company" maxlength="40" name="company" size="20" type="text" /></td>
<td><input  id="city" maxlength="40" name="city" size="20" type="text" /></td>
<td><input  id="state" maxlength="20" name="state" size="20" type="text" /></td>
</tr>
</table>
<br />
<input type="submit" name="submit">
The rendered output looks like the below.

image

Next I want to control what values are displayed in the State Province field.  I will be removing the current input tag with the name “state” (<input  id="state" maxlength="20" name="state" size="20" type="text" />).  In its place I am going to add a drop down list with a few states that I want displayed.  Below is a sample of what will be added in the place of the input tag that was just removed.  It is very important to make sure that the id and name fields have the exact name that the tag that was removed had.  If not the value will not be transferred to SalesForce.
<select id="state" name="state">
  <option value="select">[Select State]</option>
  <option value="AZ">Arizona</option>
  <option value="CA">California</option>
  <option value="FL">Florida</option>
  <option value="TX">Texas</option>
</select>
Below is the new rendered form.

image

The next element that I want to add is some scripting to validate the fields to make sure that required fields have a proper value.  This script will disable the “submit query” button if the requirements have not been met and highlight the fields in yellow that are required and have not been filled out yet.  To start with we need to create a script section with in the “head” tags that we created earlier.  Just prior to the </head> reference add the following lines:
<script language="javascript" type="text/javascript">
</script>
Next we need to modify one of the elements that was generated by SalesForce.  We will need to reference the “submit” button though it does not currently have an id that we can use to access it so that we can enable or disable it depending upon whether the user has entered valid information.

We want to give the “id” attribute the same value as the tag’s name.  It should look something like the following.
<input type="submit" name="submit" id="submit">
We are going to add all of our scripting that we need to create within this section.  The first function that we are going to add is the “load” function.  Within the “script” tags add the following lines:
function Load()
{
}
This function is named “load” and we are going to leave it blank for now.  We will be adding to it in a moment.  We next need to add an ID attribute to this tag to give it an ID that scripting can access. 

Right now adding this function does not do anything because there is nothing that is executing it.  Find the “body” open tag and within it we need to assign the “load” function call to one of the event attributes.  Below is an example of how your “body” open tag should look.
<body onload="Load();">
Next we need to create a function that executes when ever the user does something in the web page.  Under the “load” function we want to create a new function called “pageupdate”  This function will be called whenever any action on the form is performed.  For now we are not going to put anything in the function we will be adding something in a moment.  The function should look similar to the below.
function pageUpdate()
{
}
Similar to the “load” function this function is not doing anything until we assign it to an action.  We are going to assign this function to an action attribute in the “body” tag.  See below for an example of the change.
<body onload="Load();" onkeypress="pageUpdate();" onfocusin="pageUpdate();">
This will execute the function any time the user pushes a button on the page.  Be VERY carful what you put into this function or functions that this function calls.  Since this executes every time an action occurs it happens a lot.  I accidentally added an alert function (pops up a message) when I was testing this and the message would not stop coming up and I had to kill my browser session to stop the messaging.

Also because “select” HTML tags (or drop down lists) react a little different it is good to update that tag by adding the “pageupdate” function to its onchange event.  It should look similar to below.
<select id="state" name="state" onchange="pageUpdate();">
  <option value="select">[Select State]</option>
  <option value="AZ">Arizona</option>
  <option value="CA">California</option>
  <option value="FL">Florida</option>
  <option value="TX">Texas</option>
</select>
Before we make the validation function we need to decide which elements we want to require the user to enter a value into.  I want to require all but company name.  Also, I am a big fan of having a visual indicator that a field is required.  Some people like to put a red asterisk or note by required fields.  I like to change the back ground to yellow.  If you are the type that likes to show the red asterisk or note then you will need to create additional labels with that info and hide them on load and then display them on need in the validation function.  I am fond of the yellow color represented by the internet number of FFFF80.  Below is an example of the my validation function.
function validate()
{
    var reqColor = "#FFFF80"
    var regColor = "#FFFFFF"
    document.getElementById("first_name").style.backgroundColor=regColor;
    document.getElementById("last_name").style.backgroundColor=regColor;
    document.getElementById("email").style.backgroundColor=regColor;
    document.getElementById("city").style.backgroundColor=regColor;
    document.getElementById("state").style.backgroundColor=regColor;
   
    var valid = true;
    if(document.getElementById("first_name").value=="")
    {
        document.getElementById("first_name").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("last_name").value=="")
    {
        document.getElementById("last_name").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("email").value=="")
    {
        document.getElementById("email").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("city").value=="")
    {
        document.getElementById("city").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("state").value=="select")
    {
        document.getElementById("state").style.backgroundColor=reqColor;
        valid = false;
    }
           
    if(valid)
        document.getElementById("submit").disabled=false;
    else
        document.getElementById("submit").disabled=true;
}
Lets walk through this function.  First I create two functions to store the color values for the background, white for valid or yellow for required.  Then I go through each of the elements that are “required” and set their back ground to white in case things have changed since the function was last called.  Next I create a variable to store a true/false value so that I know whether all the validation criteria has passed or if any fail.  The next part is a series of checks that see if the value for each of the fields that are “required” have a value.  If they do not then we set the “valid” variable to false to prevent the submit button from being executed.  A screenshot of our initial screen is below.

image

As you can see all of our required fields are highlighted yellow and our “submit query” button is disabled.  If I fill in all the required values then the colors change and the “submit query” button is now enabled.

image

The final code from this tutorial is below.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22>
<html xmlns="http://www.w3.org/1999/xhtml%22>
<head>
<title>Web-to-lead eForm</title>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">
<script language="javascript" type="text/javascript">
function Load()
{
    validate();
}
function pageUpdate()
{
    validate();
}
function validate()
{
    var reqColor = "#FFFF80"
    var regColor = "#FFFFFF"
    document.getElementById("first_name").style.backgroundColor=regColor;
    document.getElementById("last_name").style.backgroundColor=regColor;
    document.getElementById("email").style.backgroundColor=regColor;
    document.getElementById("city").style.backgroundColor=regColor;
    document.getElementById("state").style.backgroundColor=regColor;
   
    var valid = true;
    if(document.getElementById("first_name").value=="")
    {
        document.getElementById("first_name").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("last_name").value=="")
    {
        document.getElementById("last_name").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("email").value=="")
    {
        document.getElementById("email").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("city").value=="")
    {
        document.getElementById("city").style.backgroundColor=reqColor;
        valid = false;
    }
    if(document.getElementById("state").value=="select")
    {
        document.getElementById("state").style.backgroundColor=reqColor;
        valid = false;
    }
           
    if(valid)
        document.getElementById("submit").disabled=false;
    else
        document.getElementById("submit").disabled=true;
}
</script>
</head>
<body onload="Load();" onkeypress="pageUpdate();" onfocusin="pageUpdate();">
<table width="100%">
<tr>
<td width="128">
<img src="gnarledtree.png" alt="GnarledTree" />
</td>
<td width="*" align="center"> <h2>The Gnarled Tree</h2>
</td>
<td width="128">
</td>
</tr>
</table>
<form action="https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8" method="POST">
<input type=hidden name="oid" value="00DC0000000PU9Q">
<input type=hidden name="retURL" value="http://salesforce.com%22/>
<b>Contact Information</b>
<table>
<tr>
<td align="center"><label for="first_name">First Name</label></td>
<td align="center"><label for="last_name">Last Name</label></td>
<td align="center"><label for="email">Email</label></td>
</tr>
<tr>
<td><input  id="first_name" maxlength="40" name="first_name" size="20" type="text" /></td>
<td><input  id="last_name" maxlength="80" name="last_name" size="20" type="text" /></td>
<td><input  id="email" maxlength="80" name="email" size="20" type="text" /></td>
</tr>
</table>
<br />
<b>Company Information</b>
<table>
<tr>
<td align="center"><label for="company">Company</label></td>
<td align="center"><label for="city">City</label></td>
<td align="center"><label for="state">State/Province</label></td>
</tr>
<tr>
<td><input  id="company" maxlength="40" name="company" size="20" type="text" /></td>
<td><input  id="city" maxlength="40" name="city" size="20" type="text" /></td>
<td>
<select id="state" name="state" onchange="pageUpdate();">
  <option value="select">[Select State]</option>
  <option value="AZ">Arizona</option>
  <option value="CA">California</option>
  <option value="FL">Florida</option>
  <option value="TX">Texas</option>
</select>
</td>
</tr>
</table>
<br />
<input type="submit" name="submit" id="submit">
</form>
</body>
</html>
Thanks for reading this and hopefully it provides helps in your web-to-lead web page development.  Obviously there are a lot more that can be done to help usability.