Captures partial form data when users leave without submitting. PRO feature.
Implementation
The frontend script listens for field interactions, debounces autosave while the visitor is still on the page, and also sends a final beacon on pagehide, beforeunload, or hidden visibilitychange:
$( document ).on( 'input change', '.formforge-form input, .formforge-form textarea, .formforge-form select', function() {
scheduleAbandonmentPartial( $( this ).closest( '.formforge-form' ) );
} );
$( window ).on( 'pagehide beforeunload', function() {
$( '.formforge-form' ).each( function() {
sendAbandonmentPartial( $( this ), true );
} );
} );Only real field names are collected. Form metadata fields such as formforge_form_id, formforge_nonce, formforge_token, formforge_timestamp, formforge_lang, and the honeypot are excluded; actual user fields named formforge_field_* are included. Each browser form instance gets a session_id; repeated autosaves update the same abandoned row, and a successful submission deletes the matching abandoned row before returning success.
Querying Abandoned Submissions
$abandoned = FORMFORGE_Abandonment::get_abandoned( $form_id, 50 );
foreach ( $abandoned as $sub ) {
$data = json_decode( $sub->data, true );
echo "Abandoned at: {$sub->created_at}n";
foreach ( $data as $key => $val ) {
echo " {$key}: {$val}n";
}
}Follow-Up Emails
$abandoned = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}formforge_submissions
WHERE form_id = %d AND status = 'abandoned'
AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)",
$form_id
) );
foreach ( $abandoned as $sub ) {
$data = json_decode( $sub->data, true );
foreach ( $data as $key => $value ) {
if ( filter_var( $value, FILTER_VALIDATE_EMAIL ) ) {
wp_mail( $value, 'Did you forget something?', 'You started our form...' );
break;
}
}
}—