Here’s another forms use-case for WordPress. You have a form built with Contact Form 7, WP Forms, Gravity Forms, etc. However, when the form is submitted, you also want to send the form data to a third party, like Salesforce, SugarCRM, Marketo, etc. Luckily, the form plugins I mentioned allow us to “hook in” to the processing flow.
In this tutorial, I’ll show you a quick way to send Contact Form 7(CF7) submission data to Salesforce. We’ll be using some core WordPress functions to help with the integration. The code is pretty straightforward, so we’ll just put it in our child theme’s1You are using a child theme, right? functions.php file.
“Plugin Overhead”
There are a few existing plugins to handle third-party integrations with WordPress form builders. They give you options like dynamic field mapping, which third-party to send data to, and some other goodies. We could easily spend more time writing code to create these features, but it’s just more of what I like to call “plugin overhead.”
“Plugin overhead” simply refers to the code and/or data overhead required to create a plugin. For starters, there’s more code required just to have a snippet function as a plugin. Next, there’s the database query overhead needed to check if the plugin is active. Further, each custom setting or option stored in the database requires more queries.
In the case of our integration, we’ll forego dynamic, stored settings to keep our code lightweight. As I mentioned, we’ll just pop the snippet into a functions.php file. It can easily be activated or deactivated by commenting the snippet or even just the add_action
line.
Our Plan of Attack
For CF7, the action we want to hook into is wpcf7_before_send_mail
. This action is fired after submission and validation, but before the email confirmations are sent out. So, we know the form data is validated before sending to the third party.
We’ll be sending data to Salesforce’s Web-to-Case endpoint. We can “POST” the form submission data utilizing WordPress’s wp_remote_post
function. This function is just a wrapper for PHP’s native cURL library, but it defaults a few things to keep our code very clean.
Finally, if there’s an error in POSTing our data to Salesforce, we’ll alert someone via email of the issue.
CF7 Form Basics
Getting started, we need to create our hook skeleton.
<?php
add_filter( 'wpcf7_before_send_mail*', 'de_wpcf7_salesforce' );
function de_wpcf7_salesforce( $contact_form ) {
}
?>
This code just establishes that we want to hook into the wpcf7_before_send_mail
action with a custom function called de_wpcf7_salesforce
. We then declare the de_wpcf7_salesforce
function. The only parameter being passed to our function is the CF7 $contact_form
object containing all the properties of the current form being submitted.
Let’s add some code to our custom function to get the form submission data.
<?php
add_filter( 'wpcf7_before_send_mail*', 'de_wpcf7_salesforce' );
function de_wpcf7_salesforce( $contact_form ) {
global $wpdb;
if ( ! isset( $contact_form->posted_data ) && class_exists( 'WPCF7_Submission' ) ) {
$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
$form_data = $submission->get_posted_data();
}
} else {
return $contact_form;
}
}
?>
Here we’ve added some checks to ensure we can pull the form data from the WPCF7_Submission
instance. If successful, we store the submitted data in a local $form_data
variable to be used later. If not, we bail early so CF7 can continue its work.
Now that we have access to the submitted form field values, we can begin compiling the data for our POST request.
<?php
add_filter( 'wpcf7_before_send_mail*', 'de_wpcf7_salesforce' );
function de_wpcf7_salesforce( $contact_form ) {
global $wpdb;
if ( ! isset( $contact_form->posted_data ) && class_exists( 'WPCF7_Submission' ) ) {
$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
$form_data = $submission->get_posted_data();
}
} else {
return $contact_form;
}
$body = array(
'orgid' => 'XXXXXXXXXXXXXXX',
'recordType' => 'XXXXXXXXXXXXXXX',
'retURL' => '/',
'name' => $form_data['name'],
'email' => $form_data['email'],
'comments' => $form_data['comments'],
);
}
?>
The $body
array is what we’ll pass as the body
parameter to the wp_remote_post
function. It contains some crucial data. The orgid
and recordType
keys are required by Salesforce and are unique to your organization and the specific Web-to-Case. Replace the “XXXXXXXXXXXXXXX” placeholders with the values from your case.2To make it easier, just use the “Web-to-Case HTML Generator”. You’ll see the two hidden fields for “orgid” and “recordType”. You can also copy the form’s action
to use as the $url
parameter used later. The retURL
parameter may or may not be required, but its value is inconsequential given that CF7 will be handling the redirect.3Since we’re doing a POST in the background processing, all we’ll be looking for is a 200 code in the response. Any retURL
value can be sent because it won’t be used in our response processing.
The other parameters in our body are name
, email
, and comments
. These are the actual case data to be sent from the CF7 form to Salesforce. Whatever fields the Salesforce case requires should be included in the $body
array. For each key, we are getting its value from the submitted CF7 form data. As an example, the name
value is set to the value for $form_data['name']
. The key names need not match, but it’s probably a good idea to do so when building the Salesforce case and CF7 form fields, just to prevent confusion.
On that note, if you have a lot of fields and you’re certain that the field names are identical in Salesforce and CF7, you can just iterate over $form_data
and append each key-value pair to the $body
array like so:
$body = array(
'orgid' => 'XXXXXXXXXXXXXXX',
'recordType' => 'XXXXXXXXXXXXXXX',
'retURL' => '/'
);
foreach ( $form_data as $key => $value ) {
$body[$key] = $value;
}
Sending The Data To Salesforce
As mentioned, we can use wp_remote_post
to POST to Salesforce. We only need to set the parameters for that function and execute it.
<?php
add_filter( 'wpcf7_before_send_mail*', 'de_wpcf7_salesforce' );
function de_wpcf7_salesforce( $contact_form ) {
global $wpdb;
if ( ! isset( $contact_form->posted_data ) && class_exists( 'WPCF7_Submission' ) ) {
$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
$form_data = $submission->get_posted_data();
}
} else {
return $contact_form;
}
$body = array(
'orgid' => 'XXXXXXXXXXXXXXX',
'recordType' => 'XXXXXXXXXXXXXXX',
'retURL' => '/',
'name' => $form_data['name'],
'email' => $form_data['email'],
'comments' => $form_data['comments'],
);
$url = 'https://webto.salesforce.com/servlet/servlet.WebToCase?encoding=UTF-8';
$params = array(
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded'
),
'body' => $body
);
$response = wp_remote_post( $url, $params );
}
?>
On line 26, we’re setting the remote Salesforce URL to POST our data to. In this example using Web-to-Case, so the URL is https://webto.salesforce.com/servlet/servlet.WebToCase?encoding=UTF-8
. Be sure to include the encoding on the end, or the request will fail.
We then create an array to set the parameters for the wp_remote_post
function. Included are headers
and body
.4There are many more optional parameters available. See the WordPress HTTP API documentation for details.
The headers
parameter can be used to add any necessary request headers. In our case, all we need is to set the Content-Type
to application/x-www-form-urlencoded
. This ensures our form data will be encoded properly in transport.
We also pass our $body
array as the body
parameter. Finally, we execute wp_remote_post
and save its return value to a $response
variable to use later.
We could stop at this point, knowing that our form submission was sent to Salesforce. However, we have no idea if the request was received. We should add some sort of error handling. Fortunately, wp_remote_post
returns a WP_Error
instance if the request failed. Let’s check for that in the $response
and send an email with the error message to someone important.
<?php
add_filter( 'wpcf7_before_send_mail*', 'de_wpcf7_salesforce' );
function de_wpcf7_salesforce( $contact_form ) {
global $wpdb;
if ( ! isset( $contact_form->posted_data ) && class_exists( 'WPCF7_Submission' ) ) {
$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
$form_data = $submission->get_posted_data();
}
} else {
return $contact_form;
}
$body = array(
'orgid' => 'XXXXXXXXXXXXXXX',
'recordType' => 'XXXXXXXXXXXXXXX',
'retURL' => '/',
'name' => $form_data['name'],
'email' => $form_data['email'],
'comments' => $form_data['comments'],
);
$url = 'https://webto.salesforce.com/servlet/servlet.WebToCase?encoding=UTF-8';
$params = array(
'headers' => array(
'Content-Type' => 'application/x-www-form-urlencoded'
),
'body' => $body
);
$response = wp_remote_post( $url, $params );
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
$to = '[email protected]';
$subject = 'CF7 -> Salesforce POST Failed';
$body = 'Error message: '.$error_message;
$headers = array( 'Content-Type: text/html; charset=UTF-8' );
wp_mail( $to, $subject, $body, $headers );
}
}
?>
Again, we’re using WordPress core functions to help us write cleaner code. is_wp_error
checks for WP_Error
in the $response
, and if it is, we setup an email to relay the specific error message using wp_mail
.
With that our code is complete! We have a working connector for Contact Form 7 submissions and Salesforce. This method can easily be adapted for any WordPress form builder, as long as it has hooks to interject in submission processing. Also, the data can be POSTed to any third-party offering an API.
References
1 | You are using a child theme, right? |
---|---|
2 | To make it easier, just use the “Web-to-Case HTML Generator”. You’ll see the two hidden fields for “orgid” and “recordType”. You can also copy the form’s action to use as the $url parameter used later. |
3 | Since we’re doing a POST in the background processing, all we’ll be looking for is a 200 code in the response. Any retURL value can be sent because it won’t be used in our response processing. |
4 | There are many more optional parameters available. See the WordPress HTTP API documentation for details. |
David: Thanks for posting this info. I am trying this on a site I am working on at https://www.aqcind.com/contact/sf-basic-test/ (this is a really basic CF7 form I want to test with). I can get the web-to-lead working on my site outside of cf7 (test pg here: https://www.aqcind.com/web-to-lead-test.php), but using your code above isn’t working – the form submits, but nothing shows up in my leads table in Salesforce. I have updated the $url value to https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8 (want to go to Leads and note Case). The orgid field is correct. Any other ideas on why this would work?
Eric,
Have you tried the logging at the bottom of the article?
Is the “recordType” required? Thank you
I believe so.