Many businesses run their website on WordPress and their follow-up in GoHighLevel. The weak point is usually the gap between the two: form submissions land in an inbox, someone copies them into the CRM, and the fast follow-up GoHighLevel is good at starts hours late.
This guide shows how to send a WordPress form to GoHighLevel the moment it is submitted, using GoHighLevel’s Inbound Webhook trigger and a short PHP snippet. It also covers the no-code option for Elementor Pro forms, how to map the fields, and how to test it properly.
How it works
- A visitor submits a form on your WordPress site.
- WordPress sends the submitted fields as JSON to a unique GoHighLevel webhook URL.
- The Inbound Webhook trigger starts a workflow, which creates or updates the contact and runs your follow-up.
The website stays exactly as it is. Only the destination of the data changes.
Step 1: create the Inbound Webhook trigger
- In the sub-account, create a new workflow and choose the Inbound Webhook trigger.
- Copy the unique webhook URL it shows. Treat it as private: anyone with the URL can send data into the workflow.
- Leave the trigger open — you will send a test request in a moment so GoHighLevel can see the fields.
Step 2 (Elementor Pro): no code needed
If your forms are built with Elementor Pro, you do not need any code. Edit the form, add Webhook under Actions After Submit, paste the GoHighLevel URL into the Webhook section and save. Elementor sends the field values with each submission. Give every field a clear ID (for example email, phone, message) so it is easy to map later.
Step 2 (Contact Form 7): add a PHP snippet
Contact Form 7 does not send webhooks on its own, but it fires an action after every successful submission that we can hook into. Add this to a small custom plugin or your child theme’s functions.php. Store the webhook URL in wp-config.php, not in the code.
// wp-config.php
define( 'GHL_WEBHOOK_URL', 'https://services.leadconnectorhq.com/hooks/your-unique-webhook-url' );
// functions.php (child theme) or a small plugin
add_action( 'wpcf7_mail_sent', function ( $contact_form ) {
if ( ! defined( 'GHL_WEBHOOK_URL' ) ) {
return;
}
$submission = WPCF7_Submission::get_instance();
if ( ! $submission ) {
return;
}
$data = $submission->get_posted_data();
// Map your form's field names to clear keys for GoHighLevel.
$payload = array(
'first_name' => sanitize_text_field( $data['your-name'] ?? '' ),
'email' => sanitize_email( $data['your-email'] ?? '' ),
'phone' => sanitize_text_field( $data['your-phone'] ?? '' ),
'message' => sanitize_textarea_field( $data['your-message'] ?? '' ),
'form_name' => $contact_form->title(),
'page_url' => esc_url_raw( $submission->get_meta( 'url' ) ),
);
$response = wp_remote_post( GHL_WEBHOOK_URL, array(
'timeout' => 10,
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( $payload ),
) );
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) >= 300 ) {
error_log( 'GHL webhook failed for form "' . $contact_form->title() . '": ' . print_r( $response, true ) );
}
} );Change the keys inside $data[...] to match the field names in your form — your-name, your-email and so on are Contact Form 7’s defaults. The snippet only runs after the email notification succeeds, so it follows the same validation as the form itself.
A generic version for any form or custom code
If you have your own form handler, the same idea fits in a reusable function you can call from anywhere:
function gnx_send_to_ghl( array $fields ) {
if ( ! defined( 'GHL_WEBHOOK_URL' ) || empty( $fields['email'] ) && empty( $fields['phone'] ) ) {
return false; // need at least one way to identify the contact
}
$response = wp_remote_post( GHL_WEBHOOK_URL, array(
'timeout' => 10,
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( $fields ),
) );
return ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) < 300;
}
// Example: inside your own form handler, after validation
gnx_send_to_ghl( array(
'first_name' => 'Sam',
'email' => 'sam@example.com',
'source' => 'pricing-page',
) );Step 3: send a test and map the fields
- Submit the form on your site with test details.
- Back in the workflow, the Inbound Webhook trigger should show the received fields. Select the test request so GoHighLevel knows the structure.
- Add a Create/Update Contact action and map
email,phoneandfirst_nameto the contact fields. Map anything else — the message, the page URL, the form name — to custom fields or a note. - Add your follow-up: a tag, a pipeline opportunity, an internal notification and the first message to the lead.
- Publish the workflow, then submit the form again and confirm the contact appears with every field filled in.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Nothing arrives in GoHighLevel | The snippet is not running, or the URL is wrong | Check the PHP error log and confirm the constant is defined |
| Contact created with empty fields | Field names in the snippet do not match the form | Compare the keys with the form’s field names |
| Duplicate contacts | Create Contact used instead of Create/Update | Use the Create/Update action, matching on email or phone |
| Workflow runs but no messages send | Missing SMS consent or A2P registration | See our SMS compliance guide |
| Works in testing, fails later | The workflow was unpublished or the trigger changed | Monitor key workflows — see our monitoring guide |
Good practice
- Send only what you need. Do not forward passwords, card details or sensitive personal data to a webhook.
- Collect consent on the form. If the workflow will text the lead, the form needs clear SMS consent wording.
- Keep a copy. Leave the form’s normal email notification switched on as a backup while you test.
- Rotate the URL if it leaks. Delete the trigger and create a new one; the old URL stops working.
Prefer to replace the WordPress forms altogether? Our GoHighLevel and WordPress guide compares embedding GoHighLevel forms with keeping your own. For two-way integrations, see the GoHighLevel API guide.
Frequently asked questions
Will this slow down my form?
The request takes a moment after submission. The 10-second timeout stops a slow response from holding the page up for long; for very busy sites, the request can be moved to a background job.
Can I send to different workflows from different forms?
Yes. Create one inbound webhook per workflow and choose the URL based on the form’s ID or title.
Is the webhook URL secret?
Treat it that way. Keep it in wp-config.php, and replace it if it is ever exposed.
Does this work with Gravity Forms or WPForms?
Yes. Both offer webhook add-ons, or you can call the generic function above from their after-submission hooks.
This guide is part of our GoHighLevel Setup Guides series — setup guides covering the whole topic.



