Skip to content

Instantly share code, notes, and snippets.

@xlplugins
Created December 23, 2025 13:52
Show Gist options
  • Select an option

  • Save xlplugins/979329876ec2c9313beeef4ceccef752 to your computer and use it in GitHub Desktop.

Select an option

Save xlplugins/979329876ec2c9313beeef4ceccef752 to your computer and use it in GitHub Desktop.
Fluent Forms + FunnelKit Optin forms
/**
* 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