Contact Form 7 Redirect After Submit: Use the Mail Sent Event
On this page, 9 sections
To redirect after a Contact Form 7 submission, listen for the wpcf7mailsent DOM event and set window.location inside the handler. The event fires only when the form’s mail was sent, so the redirect never runs on a validation error or a failed mail.
The old advice was to paste on_sent_ok into the form’s Additional Settings tab. The plugin’s own validator now flags on_sent_ok as a deprecated setting, and the official redirect page says that method is no longer recommended. The DOM event is the current route.
I read the plugin source (version 6.2.2) and the official redirect page on 11 October 2026. I did not run any of this on a live site, so everything below is “the source says”, not “I watched it happen”.
What the plugin does after you click submit
In 6.2.2 the front end script posts the form to the plugin’s REST route, contact-forms/{id}/feedback. The reply carries a status value. The script maps mail_sent to the word “sent” and mail_failed to “failed”, then dispatches a browser event named wpcf7mail plus that word.
So there are two separate events for the two mail outcomes: wpcf7mailsent and wpcf7mailfailed. Validation problems fire wpcf7invalid. Spam flags fire wpcf7spam. A form with an unticked acceptance box fires wpcf7unaccepted. Only wpcf7mailsent means the message left the server.
That is the useful part. A redirect that listens to the generic submit event sends people to your thank-you page even when the mail failed. Listening to wpcf7mailsent removes that whole class of bug.
The listener
The official page gives a snippet with a three second delay. I changed two things: it checks the form ID, and it uses location.assign. The ID check matters because the event bubbles to document and every Contact Form 7 form on the page triggers it.
document.addEventListener( 'wpcf7mailsent', function ( event ) {
if ( Number( event.detail.contactFormId ) !== 7 ) {
return;
}
setTimeout( function () {
window.location.assign( 'https://example.com/thank-you/' );
}, 3000 ); // Wait 3 seconds so the visitor sees the success message.
}, false );
Replace 7 with your form’s ID, which is in the shortcode ([contact-form-7 id="7"]) and in the form list. The event detail also carries unitTag, inputs, formData and apiResponse, so you can branch on a field value as well.
The delay is optional. Without it the success message never renders, which is fine if the thank-you page says the same thing. The official page waits 3 seconds in its example.
To watch the event fire without redirecting, temporarily replace the redirect line with console.log( event.detail );. Submit the form with the browser console open. If the detail object prints, the redirect line will work. If nothing prints, the plugin script did not load or the listener was added after the page had finished loading.
Where to put it
The official page says to embed the snippet in your theme’s template file. A theme update will overwrite that, so I would put it in a child theme or a small plugin. Here it is as a PHP function that prints the script in the footer.
<?php
add_action( 'wp_footer', function () {
?>
<script>
document.addEventListener( 'wpcf7mailsent', function ( event ) {
if ( Number( event.detail.contactFormId ) !== 7 ) {
return;
}
window.location.assign( 'https://example.com/thank-you/' );
}, false );
</script>
<?php
} );
The listener sits on document, so it does not matter that the plugin’s own script loads separately. It only has to exist before the first submit.
If you cache pages, the footer script is cached with them. After you add the snippet and see nothing change, the likely cause is a stale cache layer, not the code. Which caching layer is failing walks through telling them apart.
Letting the server choose the URL
Sometimes the destination depends on the submission: a different thank-you page per product, say. You can attach the URL on the server and read it in the browser. The plugin runs the REST reply through the wpcf7_feedback_response filter, which receives the response array and the result array.
<?php
add_filter( 'wpcf7_feedback_response', function ( $response, $result ) {
if ( isset( $result['status'] ) && 'mail_sent' === $result['status'] ) {
$response['redirect_to'] = home_url( '/thank-you/' );
}
return $response;
}, 10, 2 );
document.addEventListener( 'wpcf7mailsent', function ( event ) {
var url = event.detail.apiResponse && event.detail.apiResponse.redirect_to;
if ( url ) {
window.location.assign( url );
}
}, false );
I test $result['status'] because that is the stable key. The older wpcf7_ajax_json_echo filter has been deprecated since version 5.2, so do not build on it.
Anything you put in $response is visible to the visitor in the browser’s network tab, so keep private values out of it. A destination URL is fine.
Why the redirect does not fire
- The mail failed. The event is
wpcf7mailfailed, so nothing redirects. Fix the mail first. If the form just spins, that is a different problem, covered in Contact Form 7 keeps spinning. - The script did not load. The plugin’s JavaScript loading goes through the
wpcf7_load_jsfilter. A theme or plugin that returns false there removes the front end script, and the form falls back to a full page reload. The Contact Form 7 page refresh problem is in How to fix Contact Form 7 page refresh after submit. - The ID does not match. If you filter by
contactFormIdand typed the wrong number, the handler returns silently. Log the value in the console to see it. - An old
on_sent_okline is still there. Open the form’s Additional Settings tab. The plugin’s validator flags that line as deprecated. Delete it and use the event instead.
How this was checked
I read the official redirect page and the 6.2.2 plugin files on 11 October 2026: includes/js/index.js for the events and the REST route, includes/rest-api.php for the filter, includes/config-validator/additional-settings.php for the deprecated settings, and the readme for the version.
I ran node --check on the JavaScript and php -l on the PHP. I did not submit a form or run the redirect on a live site. I could not fetch the plugin’s DOM events page, because it sits behind a Cloudflare challenge, so the event list comes from the source instead.
One correction to common advice: some posts say on_sent_ok was removed. The documentation I read says “no longer recommended”, and the 6.2.2 validator flags it as deprecated. I use those two words and nothing stronger.
Questions people ask
Do I need a thank-you page to track conversions?
Not for Google Analytics, according to the official redirect page. It says a thank-you page is not required for tracking. It describes the redirect as needed only for a tiny share of sites.
Can I redirect to a different page per form?
Yes. Check event.detail.contactFormId and pick the URL from a small object keyed by form ID. One listener can handle every form on the site.
Does the redirect work with the REST API disabled?
No. The form posts to a REST route, so if that route is blocked, the form never reaches a result and no event fires. That is the spinner problem, not a redirect problem.
Do this today
Open your form’s Additional Settings tab, delete any on_sent_ok line, and add the wpcf7mailsent listener with your form ID. Submit once with a real email address and confirm you land on the thank-you page.
Resources
- Contact Form 7: Redirecting to Another URL After Submissions, read 11 October 2026
- Contact Form 7 6.2.2 source,
includes/js/index.js, read 11 October 2026 - Contact Form 7 6.2.2 source,
includes/config-validator/additional-settings.phpandincludes/rest-api.php, read 11 October 2026