An ask for a contact form that sends data to pardot turned out to be a fun little plug-in.
Code first;
<?php | |
/** | |
* custom CF7 to Pardot Form Handler | |
* | |
* @package custom-cf7-pardot-form-handler | |
* @copyright 2023 Derak Kilgo | |
* @license GPL v2 or later | |
* | |
* Plugin Name: custom CF7 to Pardot Form Handler | |
* Description: Relay form data from a Contact Form 7 form to a Pardot Custom Form Handler endpoint. | |
* Version: 0.0.1 | |
* Author: Derak Kilgo | |
* Requires PHP: 5.6 | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
*/ | |
if (!defined('ABSPATH')) { | |
exit; | |
} | |
add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'custom_cf7pfh_add_action_links' ); | |
function custom_cf7pfh_add_action_links ( $actions ) { | |
$mylinks = array( | |
'<a href="https://gist.github.com/derak-kilgo/d561ca19764058a9d40a9dd9b11ed817">Docs</a>', | |
); | |
$actions = array_merge( $actions, $mylinks ); | |
return $actions; | |
} | |
add_action('wpcf7_submit','custom_cf7pfh_send',10,2); | |
/** | |
* Action to hook into when contact 7 forms are submitted. Form must include a "custom_pardot_form_action_url" arg. | |
* Example $result - {"contact_form_id":9999,"status":"mail_sent","message":"Thank you for your message. It has been sent.","posted_data_hash":"a685e3d41dxxxxxxxxxxxxxxxxx"} | |
* | |
* @param WPCF7_ContactForm $contact_form | |
* @param array $result The result of submitting the form along with status and result messaging. | |
* @return void | |
*/ | |
function custom_cf7pfh_send($contact_form,$result){ | |
//based on flamingo.php by Takayuki Miyoshi | |
$submission = WPCF7_Submission::get_instance(); | |
if ( ! $submission or ! $posted_data = $submission->get_posted_data() ) { | |
//do nothing. No submission obj means we can't get posted data. | |
return; | |
} | |
$tmpSettings = $contact_form->additional_setting('custom_pardot_form_action_url',1); | |
if(empty($tmpSettings[0])){ | |
//do nothing. We don't have an action to take. | |
return; | |
} | |
$pardot_action_url = (string) $tmpSettings[0]; | |
unset($tmpSettings); | |
//Send data to the form endpoint. | |
//@see https://help.salesforce.com/s/articleView?id=000383081&type=1 | |
// $wp_remote_post_result = wp_remote_post($pardot_action_url,array( | |
// 'method' => 'POST', | |
// 'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'), | |
// 'body' => $posted_data | |
// )); | |
$wp_remote_post_result = custom_post_to_url($pardot_action_url,$posted_data); | |
if(defined('WP_DEBUG') && WP_DEBUG === true) { | |
$data = [ | |
'timestamp' => microtime(true), | |
'posted_data' => $posted_data, | |
'pardot_action_url' => $pardot_action_url, | |
'remote_post_result' => $wp_remote_post_result | |
]; | |
$json = print_r($data, true); | |
file_put_contents(__DIR__ . '/output.log', $json . "\n\n\n", FILE_APPEND); | |
/* end debugging */ | |
} | |
} | |
/** | |
* Send POST form data to pardot. | |
* WordPress wp_remote_post() doesn't seem to work with pardot. | |
* | |
* @param $target_url | |
* @param $post_data | |
* @return array | |
*/ | |
function custom_post_to_url ($target_url,$post_data){ | |
//This works around some gotchas with pardot form handlers. | |
//pardot does not support multi-part form. | |
//@see https://help.salesforce.com/s/articleView?id=000383081&type=1 | |
//@see http://php.net/manual/en/function.curl-setopt.php CURLOPT_POSTFIELDS | |
//Portions of this code generated by insomnia/2023.5.8 | |
$curl = curl_init(); | |
$post_string = http_build_query($post_data); | |
curl_setopt_array($curl, [ | |
CURLOPT_URL => $target_url, | |
CURLOPT_RETURNTRANSFER => true, | |
CURLOPT_ENCODING => "", | |
CURLOPT_MAXREDIRS => 10, | |
CURLOPT_TIMEOUT => 30, | |
CURLINFO_HEADER_OUT=>true, | |
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, | |
CURLOPT_CUSTOMREQUEST => "POST", | |
CURLOPT_POSTFIELDS => $post_string, | |
CURLOPT_HTTPHEADER => [ | |
"Content-Type: application/x-www-form-urlencoded", | |
"User-Agent: customPardotFormRelay/0.0.1" | |
], | |
]); | |
//Capture response headers safely. See RFC822 RFC2616 RFC7230 | |
//@see https://stackoverflow.com/a/41135574 | |
$response_headers = []; | |
// this function is called by curl for each header received | |
curl_setopt($curl, CURLOPT_HEADERFUNCTION, | |
function($curl, $header) use (&$response_headers) | |
{ | |
$len = strlen($header); | |
$header = explode(':', $header, 2); | |
if (count($header) < 2) // ignore invalid headers | |
return $len; | |
$response_headers[strtolower(trim($header[0]))][] = trim($header[1]); | |
return $len; | |
} | |
); | |
//Make request | |
$response = curl_exec($curl); | |
$err = curl_error($curl); | |
//Collect output | |
$out = array(); | |
$out['response_body'] = curl_exec($curl); | |
//NOTE: this may need to be updated in the future to use CURLINFO_RESPONSE_CODE instead. | |
$out['response_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE); | |
$out['response_headers'] = $response_headers; | |
$out['error'] = curl_error($curl); | |
$out['request_headers'] = curl_getinfo($curl,CURLINFO_HEADER_OUT); | |
curl_close($curl); | |
return $out; | |
} |
Plug-in hooks into the ‘wpcf7_submit’ action which occurs after a form is submitted successfully and makes a secondary request to a pardot form handler endpoint.
Config is done in contact form 7 using “additional settings”.
Usage:
- Install this plugin and contact form 7.
- Make a new contact form.
- Make sure the input ‘name’ attributes match your pardot field handles.
- On the forms’ Additional Settings page, add the handler url from pardot.
Example:custom_pardot_form_action_url: "https://example.com/l/999/99-99-99/abcd"
- Save your form.
Note: If WP_DEBUG is enabled; the plug-in will attempt to write to plugins/output.log
This is useful when trying to debug issues with the form handler.
Note: “custom_pardot_form_action_url” must be present for data to be sent to pardot.
Plug-in ignores any forms which don’t have this.
So what was fun about this?
I was aware of another project by the same author called “Flamingo”. It directs the form data to a database. I enjoyed picking that plug-in apart. There were hints there that are not in the ContactForm7 docs. I guess I was surprised there wasn’t something that already did this and amused that it wasn’t that hard to piece together.
Enjoy.