8

I have a website form using HTML and jQuery/Javascript on my own domain that I want to post to Salesforce (web2lead or not, as long as it gets there) using an ajax call. I keep getting the Access-Control-Allow-Origin error. How do I accomplish this functionality?


I've been reading up and have seen a couple things:

  1. IFrame Hacks
  2. CORS (Possible probably if I can set Salesforce Access-Control-Allow-Origin headers to my domain in a custom APEX page)
  3. Reverse Proxies

I'm currently sending it by having the javascript submit to a local PHP file with cURL, but I'm trying to keep the whole thing contained in jQuery/Javascript without extraneous files so I can implement it as a widget "on the fly".

  • Web-to-Lead seems like a straightforward option, is there a reason this won't work for you? – greenstork Apr 4 '14 at 17:21
  • I'm using Web-to-Lead right now. But cross-domain submission of the form data via javascript isn't allowed. – Vap0r Apr 4 '14 at 17:29
  • Why do you need to submit the form via JS, why can't you just submit the form with an HTTP post? – greenstork Apr 4 '14 at 17:36
  • JS uses HTTP Post to submit the form. And because the entire form is written as a javascript widget. And also because finding out how to input data externally using JS might lead me to find out how to do it to any Salesforce list, including Leads, Accounts, and custom created lists, which would be extremely versatile and absolutely useful. – Vap0r Apr 4 '14 at 17:39
8
+50

You can do this from JavaScript using Web-to-Lead (as suggested in a comment by greenstork):

function webToLead(firstName, lastName, email) {
    var form = document.createElement("form");
    form.method = "POST";
    form.action = "https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8";   

    // Your org ID
    var elementOID = document.createElement("input");  
    elementOID.name="oid";
    elementOID.value='YOUR_ORG_ID';
    elementOID.setAttribute("type", "hidden");
    form.appendChild(elementOID);  

    // SFDC redirects to retURL in the response to the form post
    var elementRetURL = document.createElement("input"); 
    elementRetURL.name="retURL";
    elementRetURL.value='http://yoursite.com/somepath/somepage.html';
    elementRetURL.setAttribute("type", "hidden");
    form.appendChild(elementRetURL);

    // These fields are optional debugging elements. Uncomment
    // these lines if you wish to test in debug mode.
    // var elementDebug = document.createElement("input"); 
    // elementDebug.name="debug";
    // elementDebug.value='1';
    // elementDebug.setAttribute("type", "hidden");
    // form.appendChild(elementDebug);  

    // var elementDebugEmail = document.createElement("input"); 
    // elementDebugEmail.name="debugEmail";
    // elementDebugEmail.value='you@yourdomain.com';
    // elementDebugEmail.setAttribute("type", "hidden");
    // form.appendChild(elementDebugEmail);  

    // Whatever params you want;
    // generate a form from Customize | Leads | Web-to-Lead to figure out more
    var elementFirstName = document.createElement("input"); 
    elementFirstName.name="first_name";
    elementFirstName.value=firstName;
    elementFirstName.setAttribute("type", "hidden");
    form.appendChild(elementFirstName);  

    var elementLastName = document.createElement("input");  
    elementLastName.name="last_name";
    elementLastName.value=lastName;
    elementLastName.setAttribute("type", "hidden");
    form.appendChild(elementLastName);

    var elementEmail = document.createElement("input"); 
    elementEmail.name="email";
    elementEmail.value=email;
    elementEmail.setAttribute("type", "hidden");
    form.appendChild(elementEmail);  

    document.body.appendChild(form);

    form.submit();
}

Web-to-case should also work.

Same origin policy prevents you from calling the APIs directly from JavaScript loaded from your own domain. There really isn't any way around it, apart from using a proxy in the same origin.

  • 1
    If you're using jQuery $.post(), it's using XmlHttpRequest to submit the form, which is subject to same origin policy. A plain JavaScript form.submit() can go cross-origin. See stackoverflow.com/questions/9033513/… – metadaddy Apr 7 '14 at 17:23
  • 1
    Awesome will definitely try this. Will mark as answer as soon as it works, might even award bounty since I've been banging my head up against a wall with this. – Vap0r Apr 7 '14 at 17:52
  • 1
    Copy my code, change the OID and debug email, and work from there. It's always easier to start from something that's working! – metadaddy Apr 7 '14 at 21:18
  • 1
    Thanks, it works! Just need to change form.action to "webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8"; – BBK Dec 15 '19 at 23:52
  • 1
    Thanks for that update, @BBK - I just updated my answer. – metadaddy Dec 17 '19 at 0:10
1

Secure Web2Lead with jQuery, Php and cUrl

Javascript is helpfull in this way, but to avoid spam and hijacking of your form you better use php + cUrl. The critical Javascript part is the visibale oID. Just complement the data with the oID on the server side and send them with cUrl to the salsforce database.

More security provide a session and a unique token. To do that include on your html form document the following code on the beginning of the document:

PHP Example: index.php

<?php

   session_start();

   function createToken() {

    if(isset($_SESSION['_token'])){ 
      return $_SESSION['_token']; 
    }else{ 
      $token = md5(uniqid(microtime(),true));
      $_SESSION['_token'] = $token;
      return $token;
    }

  };

?>

Call the createToken function from the PHP Example on a hidden input field:

Form Example: index.php

<form action="action.php" method="POST">

 <input type="hidden" name="token" id="token" value="<?= createToken() ?>" />

 <button type="submit">Send</button>

</form>

With Javascript preventDefault() we block the native behaviour of the Web Browser and replace it with a jQuery Ajax Request.

jQuery Example: index.php

$('form').submit(function(event){ 

  event.preventDefault();

  var form = $(event.target);

  $.ajax({
        type: form.attr('method'),
        url:  form.attr('action'),
        data: form.serialize(),
        dataType : 'json',
        success: function(data){
              console.log(data);
          }
      });
});

On the server side we create the receive Php Script. This file reads out your from data and build a valid string for salesforce. By the way we perform the token check and compare the data with our oID.

PHP Example: action.php - token

    session_start();

    function verifyToken() {

    if( !isset($_SESSION['_token']) ) 
      { return false; }

    if( !isset($_POST['token']) ) 
      { return false; }

    if( $_SESSION['_token']!=$_POST['token'] ) 
      { return false; }

    return true;

    };

If the posted data pass our token check we can start building the cUrl string. And again we do a little bit more security. We add an password for writing Leads to the salesforce database.

PHP Example: action.php - cUrl

    if( verifyToken()===true ){

       $_oid = 'YOUR-OID';
       $_sic = urlencode('YOUR-PASSWORD');

       $fields = array (
         'oid' => $_oid,
         'sic' => $_sic
       );

       $fields_string = null;

       foreach( $fields as $key=>$value ){
         if( !isset($fields[$key]) || empty($fields[$key])) {}else{ 
           $fields_string .= $key.'='.$value.'&'; 
         }
       }
       rtrim( $fields_string, '&' );

       $_server = 'https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8';

       $curl = curl_init($_server);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_URL, $_server);
        curl_setopt($curl, CURLOPT_POST,count($fields));
        curl_setopt($curl, CURLOPT_POSTFIELDS, $fields_string);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);

        $response = curl_exec($curl);
        curl_close($curl);

    };

In the last Step we Login into our Salesforce Account. There we create a new Lead Field for the password and a validation rule for this field. In our example the field called 'sic'. An hint: Limit the character input to your password length. The rule for the validation has to look like this:

SFDC Example:

SIC__c  = "YOUR_PASSWORD"

Hope this small Tutorial was helpfull. May success will be with you. Regards

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.