Created
December 23, 2025 13:52
-
-
Save xlplugins/979329876ec2c9313beeef4ceccef752 to your computer and use it in GitHub Desktop.
Fluent Forms + FunnelKit Optin forms
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Fluent Forms submission -> FunnelKit Optin contact + optin entry + analytics tracking | |
| * With debug logging in key areas. | |
| */ | |
| /** | |
| * ONE-TIME cleanup: delete all opt-in conversions from BWF conversion tracking table. | |
| * Optin conversions are identified by `type = 1` (per schema). | |
| * | |
| * Usage: temporarily add this to a small mu-plugin or a custom plugin, | |
| * then visit wp-admin/?bwf_purge_optin_conversions=1 as an admin. | |
| */ | |
| add_action('fluentform/submission_inserted', function ($entryId, $formData, $form) { | |
| /* ------------------------------------------------------------ | |
| * 1) CONFIG | |
| * ------------------------------------------------------------ */ | |
| $target_fluent_form_ids = [8]; | |
| $wffn_optin_step_id = 7667; | |
| $field_map = [ | |
| 'email' => 'email', | |
| 'name' => 'names', | |
| 'phone' => 'phone', | |
| ]; | |
| // Toggle logs quickly | |
| $debug_enabled = true; | |
| // Log channel name (helps filter logs) | |
| $log_channel = 'wffn_fluent_optin_debug'; | |
| // Unified logger: FunnelKit logger if available; else error_log | |
| $log = function ($message, $context = []) use ($debug_enabled, $log_channel) { | |
| if (!$debug_enabled) { | |
| return; | |
| } | |
| $line = '[Fluent->WFFN Optin] ' . $message; | |
| if (!empty($context)) { | |
| // Avoid logging full form data in production. Keep it light. | |
| $line .= ' | ' . wp_json_encode($context); | |
| } | |
| if (class_exists('WFFN_Core') && isset(WFFN_Core()->logger)) { | |
| WFFN_Core()->logger->log($line, $log_channel, true); | |
| } else { | |
| error_log($line); | |
| } | |
| }; | |
| /* ------------------------------------------------------------ | |
| * 2) GUARDS + EARLY RETURN LOGGING | |
| * ------------------------------------------------------------ */ | |
| $form_id = isset($form->id) ? (int) $form->id : 0; | |
| if (!$form_id) { | |
| $log('Exit: Missing form_id', ['entryId' => (int) $entryId]); | |
| return; | |
| } | |
| if (!in_array($form_id, $target_fluent_form_ids, true)) { | |
| // Noisy if many forms exist; keep minimal. | |
| return; | |
| } | |
| if (!class_exists('WFFN_Core')) { | |
| $log('Exit: WFFN_Core not loaded', ['form_id' => $form_id, 'entryId' => (int) $entryId]); | |
| return; | |
| } | |
| if (!class_exists('WFFN_DB_Optin')) { | |
| $log('Exit: WFFN_DB_Optin not loaded', ['form_id' => $form_id, 'entryId' => (int) $entryId]); | |
| return; | |
| } | |
| $log('Hook triggered', [ | |
| 'form_id' => $form_id, | |
| 'entryId' => (int) $entryId, | |
| 'optin_id' => (int) $wffn_optin_step_id, | |
| ]); | |
| /* ------------------------------------------------------------ | |
| * 3) EXTRACT / SANITIZE VALUES | |
| * ------------------------------------------------------------ */ | |
| $email_key = $field_map['email'] ?? 'email'; | |
| $name_key = $field_map['name'] ?? 'names'; | |
| $phone_key = $field_map['phone'] ?? ''; | |
| $email = isset($formData[$email_key]) ? sanitize_email($formData[$email_key]) : ''; | |
| if (empty($email) || !is_email($email)) { | |
| $log('Exit: Missing/invalid email', [ | |
| 'email_key' => $email_key, | |
| 'email_raw' => isset($formData[$email_key]) ? (string) $formData[$email_key] : '', | |
| ]); | |
| return; | |
| } | |
| $first = ''; | |
| $last = ''; | |
| if (!empty($formData[$name_key]) && is_array($formData[$name_key])) { | |
| $first = isset($formData[$name_key]['first_name']) ? sanitize_text_field($formData[$name_key]['first_name']) : ''; | |
| $last = isset($formData[$name_key]['last_name']) ? sanitize_text_field($formData[$name_key]['last_name']) : ''; | |
| } elseif (!empty($formData[$name_key]) && is_string($formData[$name_key])) { | |
| $full = trim(wp_strip_all_tags($formData[$name_key])); | |
| if ($full !== '') { | |
| $parts = preg_split('/\s+/', $full, 2); | |
| $first = $parts[0] ?? ''; | |
| $last = $parts[1] ?? ''; | |
| } | |
| } | |
| $wffn_posted_data = [ | |
| 'email' => $email, | |
| 'optin_first_name' => $first, | |
| 'optin_last_name' => $last, | |
| ]; | |
| if (!empty($phone_key) && isset($formData[$phone_key])) { | |
| $wffn_posted_data['optin_phone'] = sanitize_text_field($formData[$phone_key]); | |
| } | |
| $log('Mapped fields', [ | |
| 'email' => $email, | |
| 'first' => $first, | |
| 'last' => $last, | |
| 'has_phone' => !empty($wffn_posted_data['optin_phone'] ?? ''), | |
| ]); | |
| /* ------------------------------------------------------------ | |
| * 4) FETCH funnel_id from optin step | |
| * ------------------------------------------------------------ */ | |
| $form_data = []; | |
| $form_data['step_id'] = (int) $wffn_optin_step_id; | |
| $funnel_id = get_post_meta($form_data['step_id'], '_bwf_in_funnel', true); | |
| if (empty($funnel_id)) { | |
| $log('Exit: funnel_id missing for step_id', [ | |
| 'step_id' => (int) $form_data['step_id'] | |
| ]); | |
| return; | |
| } | |
| $form_data['funnel_id'] = $funnel_id; | |
| $log('Resolved funnel', [ | |
| 'step_id' => (int) $form_data['step_id'], | |
| 'funnel_id' => (int) $funnel_id, | |
| ]); | |
| /* ------------------------------------------------------------ | |
| * 5) CREATE / UPDATE CONTACT (wrapped) | |
| * ------------------------------------------------------------ */ | |
| try { | |
| $user_id = get_current_user_id(); | |
| $bwf_contact = function_exists('bwf_get_contact') ? bwf_get_contact($user_id, $email) : new stdClass(); | |
| $log('Contact lookup', [ | |
| 'wp_user_id' => (int) $user_id, | |
| 'is_contact' => ($bwf_contact instanceof WooFunnels_Contact) ? 1 : 0, | |
| ]); | |
| if ($bwf_contact instanceof WooFunnels_Contact) { | |
| if (0 === (int) $bwf_contact->get_id()) { | |
| $bwf_contact->set_status(0); | |
| $bwf_contact->set_email($email); | |
| $log('New contact init', ['email' => $email]); | |
| } else { | |
| $log('Existing contact', ['cid' => (int) $bwf_contact->get_id()]); | |
| } | |
| if (!empty($first)) { | |
| $bwf_contact->set_f_name($first); | |
| } | |
| if (!empty($last)) { | |
| $bwf_contact->set_l_name($last); | |
| } | |
| $bwf_contact->save(true); | |
| $form_data['cid'] = (int) $bwf_contact->get_id(); | |
| $log('Contact saved', ['cid' => (int) $form_data['cid']]); | |
| } else { | |
| $form_data['cid'] = 0; | |
| $log('Contact object not available; continuing with cid=0'); | |
| } | |
| } catch (\Throwable $e) { | |
| $log('Error: contact create/update failed', [ | |
| 'message' => $e->getMessage(), | |
| 'file' => $e->getFile(), | |
| 'line' => $e->getLine(), | |
| ]); | |
| // You can return here if contact is mandatory for your reporting: | |
| // return; | |
| $form_data['cid'] = 0; | |
| } | |
| /* ------------------------------------------------------------ | |
| * 6) INSERT OPTIN ENTRY (wrapped) | |
| * ------------------------------------------------------------ */ | |
| try { | |
| $form_data['email'] = $email; | |
| $form_data['data'] = $wffn_posted_data; | |
| unset($form_data['data']['email']); | |
| $form_data['opid'] = WFFN_Core()->data->generate_transient_key(); | |
| $log('Optin insert start', [ | |
| 'cid' => (int) ($form_data['cid'] ?? 0), | |
| 'opid' => (string) $form_data['opid'], | |
| ]); | |
| $optin_entry_id = WFFN_DB_Optin::get_instance()->insert_optin($form_data); | |
| $log('Optin insert result', [ | |
| 'optin_entry_id' => is_numeric($optin_entry_id) ? (int) $optin_entry_id : (string) $optin_entry_id, | |
| ]); | |
| } catch (\Throwable $e) { | |
| $log('Error: insert_optin failed', [ | |
| 'message' => $e->getMessage(), | |
| 'file' => $e->getFile(), | |
| 'line' => $e->getLine(), | |
| ]); | |
| return; | |
| } | |
| /* ------------------------------------------------------------ | |
| * 7) UPDATE TRACKING / ANALYTICS (wrapped) | |
| * ------------------------------------------------------------ */ | |
| if (is_numeric($optin_entry_id) && (int) $optin_entry_id > 0) { | |
| $tracking_payload = [ | |
| 'cid' => (int) ($form_data['cid'] ?? 0), | |
| 'optin_entry_id' => (int) $optin_entry_id, | |
| 'fluent_entry_id' => (int) $entryId, | |
| 'fluent_form_id' => (int) $form_id, | |
| ]; | |
| $log('Tracking payload prepared', $tracking_payload); | |
| try { | |
| if (class_exists('BWF_Ecomm_Tracking_Common') && method_exists('BWF_Ecomm_Tracking_Common', 'update_optin_tracking_data')) { | |
| BWF_Ecomm_Tracking_Common::get_instance()->update_optin_tracking_data($wffn_optin_step_id, $tracking_payload); | |
| $log('Tracking updated'); | |
| } else { | |
| $log('Tracking skipped: BWF_Ecomm_Tracking_Common missing'); | |
| } | |
| } catch (\Throwable $e) { | |
| $log('Error: update_optin_tracking_data failed', [ | |
| 'message' => $e->getMessage(), | |
| 'file' => $e->getFile(), | |
| 'line' => $e->getLine(), | |
| ]); | |
| } | |
| $log('Done ✅', [ | |
| 'email' => $email, | |
| 'cid' => (int) ($form_data['cid'] ?? 0), | |
| 'optin_entry_id' => (int) $optin_entry_id, | |
| ]); | |
| } else { | |
| $log('Exit: optin_entry_id invalid', [ | |
| 'optin_entry_id' => is_scalar($optin_entry_id) ? (string) $optin_entry_id : 'non-scalar', | |
| ]); | |
| } | |
| }, 20, 3); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment