Contents
In this tutorial we will go through how to create a JSON POST request to a webhook endpoint using php CURL, in this particular case we will use a Zapier Webhook endpoint but you can use any other webhook endpoint (CRM, business systems, etc).
Zapier has made it easier for non-coders to create seamless solutions to business problems, but there are always times when a little bit of code is required to join together a few systems. Contact form 7 is one of the most popular contact forms available for use on WordPress yet it has always required extra plugins to extend it’s basic functionally.
Implementation time: 30 minutes
Prerequisites
- Contact Form 7 Plugin installed
- Zapier Account
- Access to your WordPress functions.php file
CF7 to Zapier Webhook implementation
Create a new Webhook Zap Trigger
- Open up Zapier and create a new Zap
- Search for the trigger Webhook
- For the type of webhook select Catch Hook
- Make a copy of the webhook URL and keep it private
Update your WordPress Functions.php File
This is the part where all the real magic happens. After someone submits a CF7 form, the below segment of PHP code will kick in to trigger a CURL POST to your Webhook endpoint.
- Open up your WordPress Functions.php file using your favorite FTP client, or through the WordPress admin interface
- Replace the values in the script below with your own values set in CF7.
- (Example: [your-name] might be just [name] and should be updated)
- Paste the code at the end of your Functions.php file and hit save.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
// Create the new wordpress action hook before sending the email from CF7 add_action( 'wpcf7_before_send_mail', 'my_conversion' ); function my_conversion( $contact_form ) { $submission = WPCF7_Submission::get_instance(); // Get the post data and other post meta values if ( $submission ) { $posted_data = $submission->get_posted_data(); $remote_ip = $submission->get_meta( 'remote_ip' ); $url = $submission->get_meta( 'url' ); $timestamp = gmdate("Y-m-d H:i:s", $submission->get_meta( 'timestamp' )); $title = wpcf7_special_mail_tag( '', '_post_title', '' ); // If you have checkboxes or other multi-select fields, make sure you convert the values to a string $mycheckbox1 = implode(", ", $posted_data["checkbox-465"]); $mycheckbox2 = implode(", ", $posted_data["checkbox-466"]); // Exclude any email addresses (eg: email addresses you use to test forms) if ( !in_array($posted_data["your-email"], array('[email protected]','[email protected]','[email protected]'), true ) ) { // Split the first and last names if ($posted_data["your-name"]){ $name = trim($posted_data["your-name"]); $last_name = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name); $first_name = trim( preg_replace('#'.$last_name.'#', '', $name ) ); // Set default value for last name if none is provided if ($last_name == NULL ){ $last_name = "Not Provided"; } } // Encode the data in a new array in JSON format $data = json_encode(array( "email" => "{$posted_data["your-email"]}", "first-name" => "$first_name", "last-name" => "$last_name", "full-name" => "{$posted_data["your-name"]}", "phone" => "{$posted_data["tel-212"]}", "checkbox1" => "$mycheckbox1", "checkbox2" => "$mycheckbox2", "id" => "{$posted_data["submit_time"]}", "Submitted" => "$timestamp", "From URL" => "$url", "From Referer" => "{$posted_data["referer-page"]}", "From IP" => "$remote_ip", "Page Title" => "$title" )); // Finally send the data to Zapier or your other webhook endpoint $ch = curl_init("https://hooks.zapier.com/hooks/catch/00000/1e459f/"); // replace with your Zapier webook curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,5); //Optional timeout value curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Optional timeout value $result = curl_exec($ch); curl_close($ch); return; } } } |
Testing the webhook
To test that the webhook is working, submit a form just like a visitor to your website would. Open up Zapier and hit ‘Continue’ to take you to the next step. If everything is working how it should, the values you set should appear. (yours will look different depending on the field values you are passing)
What to do with the POST data?
Zapier is flexible to the point that you can do whatever you want after the data has been captured. In our particular case, the data is sent to a CRM but you could use it to trigger a number of different actions depending what how you want to post-process the form data you’ve just received.
Please leave a comment below if you have tried to implement this but cannot get it to work or if you have any other improvements to the code which could benefit others!
Hi thanks for the tutorial.
I can implement the above no problem but when creating a trigger to collect the post data from a form will I have to write my own functions or code to collect the form data or will it appear as nice pre-populated dropdowns in zapier like when connecting a facebook lead form or other similar thing?
Thanks for your help
Hi Nigel,
Sorry for the late reply – If you are using the Zapier webhook, it will appear as a nice drop down list to use.
After creating the PHP function, you would test it out by submitting a form on CF7. Then switching over to Zapier, you should be able to “test your webhook” which will pull the values from the form. Provided you don’t rename the variables, they will always be the same moving forward and stay static. Like the lead form, you can drop down and select the variables to be used in other Zaps.
Please comment with a screenshot if this is not the case.
Hello. Thanks for this nice post.
After I submit my form, I got an 500 Error.
I check all the syntax and everything looks good. I do what you say.
Did this happen to you some time ?
Hi Neftali,
I’ve just sent you an email – Please send me a copy of the code you’re using. I’ll double check it out for you.
Best,
Moomaster
Hi Moo Master – thanks for a great tutorial.
I’ve managed to create the zap and connect to CF7. Submitting the form on the website results in a new job being created in Servicem8.
The problem I have is that although the process is working, CF7 isn;t returning a success message to the submitter of the form. Clicking the ‘Submit’ button results in the form looking like it is constantly loading – no success message returned. However the form does actually process the job successfully. It just doesn’t look that way to the person submitting the form.
Any advice appreciated!
Hi Daniel,
I’ve seen this sort of behavior before. Generally it’s when a function hasn’t fully completed and there has been some sort of internal error.
My suggestion would be to strip down the code to it’s bare basics (i.e, remove the curl component, remove the json encode component, etc) and test while adding little bits back at a time.
Alternatively, send myself a pastebin of the code you’re using. I’ll have a look through and see if I can spot the problem.
Best,
Moomaster
Hi MooMaster,
Thanks so much for your reply. If you had a moment to have a look at the code that would be amazing:
// Create the new wordpress action hook before sending the email from CF7
add_action( ‘wpcf7_before_send_mail’, ‘my_conversion’ );
function my_conversion( $contact_form ) {
$submission = WPCF7_Submission::get_instance();
// Get the post data and other post meta values
if ( $submission ) {
$posted_data = $submission->get_posted_data();
$remote_ip = $submission->get_meta( ‘remote_ip’ );
$url = $submission->get_meta( ‘url’ );
$timestamp = gmdate(“Y-m-d H:i:s”, $submission->get_meta( ‘timestamp’ ));
$title = wpcf7_special_mail_tag( ”, ‘_post_title’, ” );
// If you have checkboxes or other multi-select fields, make sure you convert the values to a string
$mycheckbox1 = implode(“, “, $posted_data[“checkbox-465”]);
$mycheckbox2 = implode(“, “, $posted_data[“checkbox-466”]);
// Exclude any email addresses (eg: email addresses you use to test forms)
if ( !in_array($posted_data[“your-email”], array(‘[email protected]’,’[email protected]’,’[email protected]’), true ) ) {
// Split the first and last names
if ($posted_data[“your-name”]){
$name = trim($posted_data[“your-name”]);
$last_name = (strpos($name, ‘ ‘) === false) ? ” : preg_replace(‘#.*\s([\w-]*)$#’, ‘$1’, $name);
$first_name = trim( preg_replace(‘#’.$last_name.’#’, ”, $name ) );
// Set default value for last name if none is provided
if ($last_name == NULL ){
$last_name = “Not Provided”;
}
}
// Encode the data in a new array in JSON format
$data = json_encode(array(
“email” => “{$posted_data[“your-email”]}”,
“first-name” => “$first_name”,
“last-name” => “$last_name”,
“full-name” => “{$posted_data[“your-name”]}”,
“phone” => “{$posted_data[“phone”]}”,
“checkbox1” => “$mycheckbox1”,
“checkbox2” => “$mycheckbox2”,
“id” => “{$posted_data[“submit_time”]}”,
“Submitted” => “$timestamp”,
“From URL” => “$url”,
“From Referer” => “{$posted_data[“referer-page”]}”,
“From IP” => “$remote_ip”,
“Page Title” => “$title”
));
// Finally send the data to Zapier or your other webhook endpoint
$ch = curl_init(“https://hooks.zapier.com/hooks/catch/2288866/5o59kg/”); // replace with your Zapier webook
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt( $ch, CURLOPT_HTTPHEADER, array(‘Content-Type:application/json’));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,5); //Optional timeout value
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Optional timeout value
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
}
Thanks so much for your time.
Hi Moomaster
Thanks so much for taking the time to reply. Would it be possible to send me an email so I can contact you offline? I’d like to pay you to help me fix this on my site.
Thanks,
Daniel.
I had the same problem where the CF7 Success message didn’t display. I removed the “return $result;” line, and it worked just fine.
Awesome!
This worked for me. Amazing tutorial 10/10
Thanks for the positive feedback Robert!! Let me know if you have any additional questions.
This is a bit over my head. Before I send this to my developer i had a question.
I want to automate a report (or spreadsheet) of CF7 entries. I want to do this instead of manually exporting from CF7.
Can this be done using this webhook?
Hi Bill,
Once the data has been pushed to Zapier, it is possible that you could then send it to a cloud SQL database that you then run reporting on.
An alternative might be to use the CFDB Plugin to track all you form submissions and then use the “Export” function in the plugin to export to JSON. This JSON URL could then be used as a data source in Excel to run your reporting.
Hope this helps.
Hi! Excelente post! I created a simple plugin to handle this as well: https://wordpress.org/plugins/cf7-to-zapier/
This is solid! Question – does this code pertain to ONE contact form, or all contact forms I might create? We have multiple forms, so would I use the encoding section to add in each and every input field for every form, or should I create multiple arrays for multiple forms?
Or, maybe I should just duplicate this code for each and every form I have?
Thank you, this is great!
Tom
Hi Tom,
It will be for all your contact forms, but of course you could check for the form ID if you want to include/exclude certain forms.
Because it is for all forms, it is suggest that you use the same field names wherever possible on your forms. Example: [first-name] is used on all your contact forms. This makes it easier to ensure the mapping is always consistent.
But there will be times that you have unique form fields for different forms. In which case you should add these into the array which is posted. If the field isn’t present, then a null value for that field is pushed.
Hope this helps.
Best,
MooMaster
Hi Tom,
I recommend getting the form id and checking which form you have because each form will have unique fields
add_action( ‘wpcf7_before_send_mail’, ‘my_conversion’ );
function my_conversion( $contact_form ) {
$submission = WPCF7_Submission::get_instance();
$form_id = $contact_form->posted_data[‘_wpcf7’];
// Get the post data and other post meta values
if ( $form_id == 1940 ) {
$posted_data = $submission->get_posted_data();
//Rest of code below…
Thanks again for this. Second question: I’d like to hit multiple webhooks using curl_multi_init, but my form gets stuck on submission, and the webhooks aren’t catching the POST. Any ideas for troubleshooting? Thanks!
Here’s my code:
$ch1 = curl_init(“/”);
$ch2 = curl_init (“/”);
curl_setopt($ch1, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch1, CURLOPT_HTTPHEADER, array(‘Content-Type:application/json’));
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT , 5); //Optional timeout value
curl_setopt($ch1, CURLOPT_TIMEOUT, 5); //Optional timeout value
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch2, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch2, CURLOPT_HTTPHEADER, array(‘Content-Type:application/json’));
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_CONNECTTIMEOUT , 5); //Optional timeout value
curl_setopt($ch2, CURLOPT_TIMEOUT, 5); //Optional timeout value
$mh = curl_multi_init();
curl_multi_add_handle ($mh, $ch1);
curl_multi_add_handle ($mh, $ch2);
$active = null;
//execute the handles
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//close the handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
return $mrc;
}
}
}
Actually, a follow up post…the curl_multi_init code above DID work; however on the front end the loading wheel just kept spinning, and no successful message was ever displayed. So there must be a bug somewhere in the return function towards the bottom? Any ideas?
I had the same problem where the CF7 Success message didn’t display. I removed the “return $result;” line, and it worked just fine.
Hi Jarom,
Thanks for your input – my guess is something has changed in the new version of CF7 that didn’t like the return $result function.
Can you maybe try without the $result part, just return; ?
Best
MooMaster
Hi Moo Master,
Today, I had successful tests with both “return $result;” and “return;”
At one point, when I removed the $result from the return and it fixed the problem with the form not showing the success message, but I have updated some plugins since that time and maybe that issue is now fixed.
However, I checked my error logs and found another problem that might be behind the issues Tom was having. These two lines were generating errors:
“id” => “{$posted_data[“submit_time”]}”,
“From Referer” => “{$posted_data[“referer-page”]}”,
From the error log:
[15-Feb-2018 16:06:50 UTC] PHP Notice: Undefined index: submit_time …
[15-Feb-2018 16:06:50 UTC] PHP Notice: Undefined index: referer-page …
I believe the solution Tom needs is to remove these other two fields. I checked the post data, and the only fields being passed besides my custom CF7 fields are as follows:
[_wpcf7] => 1940
[_wpcf7_version] => 5.0
[_wpcf7_locale] => en_US
[_wpcf7_unit_tag] => wpcf7-f1940-o2
[_wpcf7_container_post] => 0
It seems if some of the default fields have changed, and referer-page and submit_time are no longer part of the “$submission = WPCF7_Submission::get_instance();” data.
Hi guys…I’ve been here before, so just as a heads up, I’m using the curl_multi function as described above. Works great!
But now I need to in fact filter for different form IDs, to hit different webhooks. But I can keep the curl_multi function for one of the forms. My code is below. The form submits and returns a success message, but my webhooks aren’t triggering.
Any ideas on what I’m doing wrong? Thank you!
Code moved to Pastebin
Hi Tom,
Just at a glance, I can see a problem on line 9.
if (form_id == 11021) {
should be $form_idAs for the rest, I would suggest to do a test first. Fill your array with some dummy values for testing.
$data = json_encode(array(
"email" => "[email protected]",
See if it hits your webhook or if nothing is being sent.
I would also test by removing all your IF conditions. Just to ensure that nothing is stopping the POST from taking place.
OK, going off your second recommendation, I discovered that this line is causing the data not to post:
$form_id = $contact_form->posted_data[‘_wpcf7’];
Which is line 6. Remove that, and the single curl init action works (I didn’t test it with the multi curl.)
Perhaps CF7 has recently put out some update with that hook/function/whatever that is called.
What I’m trying to accomplish is: 1) filter for form ID, 2) use curl_init on my forms, with the exception of 1 form, in which I will run the curl multi.
What do you guys think?
What do you guys think?
Hey all, I was able to figure this out just by toying with it. I learned that CF7 form are custom post types (didn’t know that), so I tapped into the form ID by replacing this:
$form_id = $contact_form->posted_data[‘_wpcf7’];
With this:
$form_id = $contact_form->id();
And then accessing it with IF condition:
if ($form_id = 11021) { //do things }
Thanks again for the great tutorial. Minimizing plugins means minimizing load times! 🙂