'7 days', 14 => '14 days', 28 => '28 days', 60 => '60 days', 90 => '90 days', 0 => 'Manual-only', ]; } } if (!function_exists('matewa_get_lead_history_retention_days')) { function matewa_get_lead_history_retention_days() { $retention_days = absint(get_option('matewa_lead_history_retention_days', 28)); $allowed_days = array_map('absint', array_keys(matewa_lead_history_retention_options())); return in_array($retention_days, $allowed_days, true) ? $retention_days : 28; } } if (!function_exists('matewa_save_lead_history_retention_days')) { function matewa_save_lead_history_retention_days($retention_days) { $retention_days = absint($retention_days); $allowed_days = array_map('absint', array_keys(matewa_lead_history_retention_options())); if (!in_array($retention_days, $allowed_days, true)) { $retention_days = 28; } return update_option('matewa_lead_history_retention_days', $retention_days, false); } } if (!function_exists('matewa_lead_history_retention_label')) { function matewa_lead_history_retention_label($retention_days = null) { $retention_days = null === $retention_days ? matewa_get_lead_history_retention_days() : absint($retention_days); $options = matewa_lead_history_retention_options(); return $options[$retention_days] ?? $options[28]; } } if (!function_exists('matewa_lead_history_record_timestamp')) { function matewa_lead_history_record_timestamp($record) { if (!is_array($record)) { return 0; } $timestamp_fields = ['created_at', 'captured_at', 'received_at', 'last_activity', 'timestamp', 'time']; foreach ($timestamp_fields as $field) { if (!isset($record[$field]) || '' === $record[$field]) { continue; } if (is_numeric($record[$field])) { $timestamp = absint($record[$field]); } else { $timestamp = strtotime(sanitize_text_field((string) $record[$field])); $timestamp = false === $timestamp ? 0 : absint($timestamp); } if (0 < $timestamp) { return $timestamp; } } return 0; } } if (!function_exists('matewa_prune_lead_history_raw_records')) { function matewa_prune_lead_history_raw_records() { $retention_days = matewa_get_lead_history_retention_days(); $now = current_time('timestamp'); update_option('matewa_lead_history_retention_last_run', current_time('mysql'), false); if (0 === $retention_days) { update_option('matewa_lead_history_retention_last_removed', 0, false); return 0; } $records = get_option(MATEWA_LEAD_HISTORY_RAW_RECORDS_OPTION, []); if (!is_array($records) || empty($records)) { update_option('matewa_lead_history_retention_last_removed', 0, false); return 0; } $cutoff_timestamp = $now - ($retention_days * DAY_IN_SECONDS); $kept = []; $removed = 0; foreach ($records as $record_key => $record) { $record_timestamp = matewa_lead_history_record_timestamp($record); if (0 < $record_timestamp && $record_timestamp < $cutoff_timestamp) { $removed++; continue; } $kept[$record_key] = $record; } if ($removed > 0) { update_option(MATEWA_LEAD_HISTORY_RAW_RECORDS_OPTION, $kept, false); } update_option('matewa_lead_history_retention_last_removed', $removed, false); return $removed; } } if (!function_exists('matewa_lead_history_maybe_schedule_retention')) { function matewa_lead_history_maybe_schedule_retention() { if (!function_exists('wp_next_scheduled') || !function_exists('wp_schedule_event')) { return; } if (!wp_next_scheduled(MATEWA_LEAD_HISTORY_RETENTION_HOOK)) { wp_schedule_event(time() + HOUR_IN_SECONDS, 'daily', MATEWA_LEAD_HISTORY_RETENTION_HOOK); } } } if (!function_exists('matewa_clear_lead_history_retention_cleanup')) { function matewa_clear_lead_history_retention_cleanup() { if (!function_exists('wp_clear_scheduled_hook')) { return; } wp_clear_scheduled_hook(MATEWA_LEAD_HISTORY_RETENTION_HOOK); } } add_action('init', 'matewa_lead_history_maybe_schedule_retention'); add_action(MATEWA_LEAD_HISTORY_RETENTION_HOOK, 'matewa_prune_lead_history_raw_records'); if (defined('MATEWA_MAIN_FILE') && function_exists('register_deactivation_hook')) { register_deactivation_hook(MATEWA_MAIN_FILE, 'matewa_clear_lead_history_retention_cleanup'); } if (!function_exists('matewa_lead_history_sanitise_page_path')) { function matewa_lead_history_sanitise_page_path($page_path) { $page_path = is_scalar($page_path) ? trim((string) $page_path) : ''; if ('' === $page_path) { return ''; } $parsed_path = (string) wp_parse_url($page_path, PHP_URL_PATH); if ('' === $parsed_path && false === strpos($page_path, '?') && false === strpos($page_path, '#')) { $parsed_path = $page_path; } $parsed_path = sanitize_text_field(wp_unslash((string) $parsed_path)); $parsed_path = preg_replace('#/+#', '/', $parsed_path); $parsed_path = '/' . ltrim($parsed_path, '/'); $parsed_path = strtok($parsed_path, '?#'); $parsed_path = false === $parsed_path ? '/' : $parsed_path; if ('' === $parsed_path || '/' === trim($parsed_path)) { return '/'; } return substr($parsed_path, 0, 180); } } if (!function_exists('matewa_lead_history_sanitise_page_title')) { function matewa_lead_history_sanitise_page_title($page_title, $page_path = '') { $page_title = is_scalar($page_title) ? sanitize_text_field(wp_unslash((string) $page_title)) : ''; $page_title = trim(preg_replace('/\s+/', ' ', $page_title)); if ('' !== $page_title) { return substr($page_title, 0, 120); } $page_path = matewa_lead_history_sanitise_page_path($page_path); if ('/' === $page_path) { return 'Homepage'; } return '' !== $page_path ? $page_path : 'Unknown page'; } } if (!function_exists('matewa_lead_history_normalise_page_row')) { function matewa_lead_history_normalise_page_row($row, $fallback_path = '') { $row = is_array($row) ? $row : []; $page_path = matewa_lead_history_sanitise_page_path($row['page_path'] ?? $fallback_path); if ('' === $page_path) { return []; } return [ 'page_path' => $page_path, 'page_title' => matewa_lead_history_sanitise_page_title($row['page_title'] ?? '', $page_path), 'widget_opens' => absint($row['widget_opens'] ?? 0), 'completed_leads' => absint($row['completed_leads'] ?? 0), 'last_activity' => !empty($row['last_activity']) ? sanitize_text_field((string) $row['last_activity']) : '', ]; } } if (!function_exists('matewa_get_lead_history_page_activity')) { function matewa_get_lead_history_page_activity() { $raw = get_option(MATEWA_LEAD_HISTORY_PAGE_ACTIVITY_OPTION, []); $raw = is_array($raw) ? $raw : []; $rows = []; foreach ($raw as $page_key => $row) { $normalised = matewa_lead_history_normalise_page_row($row, (string) $page_key); if (empty($normalised['page_path'])) { continue; } $rows[$normalised['page_path']] = $normalised; } return $rows; } } if (!function_exists('matewa_save_lead_history_page_activity')) { function matewa_save_lead_history_page_activity(array $rows) { return update_option(MATEWA_LEAD_HISTORY_PAGE_ACTIVITY_OPTION, $rows, false); } } if (!function_exists('matewa_reset_lead_history_page_activity')) { function matewa_reset_lead_history_page_activity() { delete_option(MATEWA_LEAD_HISTORY_PAGE_ACTIVITY_OPTION); return true; } } if (!function_exists('matewa_record_lead_history_page_event')) { function matewa_record_lead_history_page_event(array $increments = []) { $page_path = matewa_lead_history_sanitise_page_path($increments['page_path'] ?? ''); $widget_opens = absint($increments['widget_opens'] ?? 0); $completed_leads = absint($increments['completed_leads'] ?? 0); if ('' === $page_path || (0 === $widget_opens && 0 === $completed_leads)) { return false; } $rows = matewa_get_lead_history_page_activity(); $page_row = isset($rows[$page_path]) ? matewa_lead_history_normalise_page_row($rows[$page_path], $page_path) : matewa_lead_history_normalise_page_row(['page_path' => $page_path], $page_path); $page_title = matewa_lead_history_sanitise_page_title($increments['page_title'] ?? ($page_row['page_title'] ?? ''), $page_path); $page_row['page_path'] = $page_path; $page_row['page_title'] = $page_title; $page_row['widget_opens'] = absint($page_row['widget_opens'] ?? 0) + $widget_opens; $page_row['completed_leads'] = absint($page_row['completed_leads'] ?? 0) + $completed_leads; $page_row['last_activity'] = current_time('mysql'); $rows[$page_path] = $page_row; uasort($rows, function ($a, $b) { $a_score = absint($a['widget_opens'] ?? 0) + absint($a['completed_leads'] ?? 0); $b_score = absint($b['widget_opens'] ?? 0) + absint($b['completed_leads'] ?? 0); if ($a_score === $b_score) { return strcmp((string) ($b['last_activity'] ?? ''), (string) ($a['last_activity'] ?? '')); } return $b_score <=> $a_score; }); if (count($rows) > 40) { $rows = array_slice($rows, 0, 40, true); } return matewa_save_lead_history_page_activity($rows); } } if (!function_exists('matewa_prepare_lead_history_page_rows')) { function matewa_prepare_lead_history_page_rows($limit = 4) { $rows = matewa_get_lead_history_page_activity(); uasort($rows, function ($a, $b) { $a_opens = absint($a['widget_opens'] ?? 0); $b_opens = absint($b['widget_opens'] ?? 0); if ($a_opens === $b_opens) { $a_leads = absint($a['completed_leads'] ?? 0); $b_leads = absint($b['completed_leads'] ?? 0); if ($a_leads === $b_leads) { return strcmp((string) ($b['last_activity'] ?? ''), (string) ($a['last_activity'] ?? '')); } return $b_leads <=> $a_leads; } return $b_opens <=> $a_opens; }); $prepared = []; foreach ($rows as $row) { $row = matewa_lead_history_normalise_page_row($row); if (empty($row['page_path'])) { continue; } $activity = 'None recorded'; if (!empty($row['last_activity'])) { $activity_ts = strtotime($row['last_activity']); if (false !== $activity_ts) { $activity = date_i18n(get_option('date_format', 'j M Y'), $activity_ts); } } $prepared[] = [ 'page_path' => $row['page_path'], 'page_title' => $row['page_title'], 'widget_opens' => absint($row['widget_opens']), 'completed_leads' => absint($row['completed_leads']), 'last_activity' => $activity, ]; if (count($prepared) >= absint($limit)) { break; } } return $prepared; } } if (!function_exists('matewa_lead_history_current_month_key')) { function matewa_lead_history_current_month_key() { return (string) date_i18n('Y-m', current_time('timestamp')); } } if (!function_exists('matewa_lead_history_current_year_key')) { function matewa_lead_history_current_year_key() { return (string) date_i18n('Y', current_time('timestamp')); } } if (!function_exists('matewa_lead_history_current_week_key')) { function matewa_lead_history_current_week_key() { return (string) date_i18n('o-W', current_time('timestamp')); } } if (!function_exists('matewa_lead_history_empty_month_row')) { function matewa_lead_history_empty_month_row() { return [ 'completed_leads' => 0, 'whatsapp_handoffs' => 0, 'lead_emails_sent' => 0, 'phone_only_leads' => 0, 'widget_opens' => 0, 'last_activity' => '', ]; } } if (!function_exists('matewa_lead_history_normalise_month_row')) { function matewa_lead_history_normalise_month_row($row) { $row = is_array($row) ? $row : []; return [ 'completed_leads' => absint($row['completed_leads'] ?? $row['leads'] ?? 0), 'whatsapp_handoffs' => absint($row['whatsapp_handoffs'] ?? $row['whatsapp'] ?? 0), 'lead_emails_sent' => absint($row['lead_emails_sent'] ?? $row['emails'] ?? 0), 'phone_only_leads' => absint($row['phone_only_leads'] ?? $row['phone_only'] ?? 0), 'widget_opens' => absint($row['widget_opens'] ?? $row['opens'] ?? 0), 'last_activity' => !empty($row['last_activity']) ? sanitize_text_field((string) $row['last_activity']) : '', ]; } } if (!function_exists('matewa_lead_history_empty_aggregates')) { function matewa_lead_history_empty_aggregates() { return [ 'year_key' => matewa_lead_history_current_year_key(), 'week_key' => matewa_lead_history_current_week_key(), 'yearly_total' => 0, 'month_total' => 0, 'week_total' => 0, 'whatsapp_handoffs' => 0, 'lead_emails_sent' => 0, 'phone_only_leads' => 0, 'widget_opens' => 0, 'last_activity' => '', 'monthly' => [], ]; } } if (!function_exists('matewa_get_lead_history_aggregates')) { function matewa_get_lead_history_aggregates() { $raw = get_option('matewa_lead_history_aggregates', []); $raw = is_array($raw) ? $raw : []; $current_year = matewa_lead_history_current_year_key(); $current_week = matewa_lead_history_current_week_key(); $current_month = matewa_lead_history_current_month_key(); $history = matewa_lead_history_empty_aggregates(); $stored_year = !empty($raw['year_key']) ? sanitize_text_field((string) $raw['year_key']) : $current_year; $stored_week = !empty($raw['week_key']) ? sanitize_text_field((string) $raw['week_key']) : $current_week; $history['year_key'] = $stored_year; $history['week_key'] = $stored_week; $history['yearly_total'] = absint($raw['yearly_total'] ?? 0); $history['week_total'] = absint($raw['week_total'] ?? 0); $history['whatsapp_handoffs'] = absint($raw['whatsapp_handoffs'] ?? 0); $history['lead_emails_sent'] = absint($raw['lead_emails_sent'] ?? 0); $history['phone_only_leads'] = absint($raw['phone_only_leads'] ?? 0); $history['widget_opens'] = absint($raw['widget_opens'] ?? $raw['opens'] ?? 0); $history['last_activity'] = !empty($raw['last_activity']) ? sanitize_text_field((string) $raw['last_activity']) : ''; $monthly = is_array($raw['monthly'] ?? null) ? $raw['monthly'] : []; foreach ($monthly as $month_key => $month_row) { $month_key = preg_match('/^\d{4}-\d{2}$/', (string) $month_key) ? (string) $month_key : ''; if ('' === $month_key) { continue; } $history['monthly'][$month_key] = matewa_lead_history_normalise_month_row($month_row); } if ($stored_year !== $current_year) { $history['year_key'] = $current_year; $history['yearly_total'] = 0; } if ($stored_week !== $current_week) { $history['week_key'] = $current_week; $history['week_total'] = 0; } $current_month_row = isset($history['monthly'][$current_month]) ? matewa_lead_history_normalise_month_row($history['monthly'][$current_month]) : matewa_lead_history_empty_month_row(); $history['monthly'][$current_month] = $current_month_row; $history['month_total'] = absint($current_month_row['completed_leads']); return $history; } } if (!function_exists('matewa_save_lead_history_aggregates')) { function matewa_save_lead_history_aggregates(array $history) { $history['year_key'] = !empty($history['year_key']) ? sanitize_text_field((string) $history['year_key']) : matewa_lead_history_current_year_key(); $history['week_key'] = !empty($history['week_key']) ? sanitize_text_field((string) $history['week_key']) : matewa_lead_history_current_week_key(); if (!is_array($history['monthly'] ?? null)) { $history['monthly'] = []; } return update_option('matewa_lead_history_aggregates', $history, false); } } if (!function_exists('matewa_lead_history_latest_activity')) { function matewa_lead_history_latest_activity(array $history) { $latest_ts = 0; $latest = ''; $monthly = is_array($history['monthly'] ?? null) ? $history['monthly'] : []; foreach ($monthly as $row) { $activity = !empty($row['last_activity']) ? sanitize_text_field((string) $row['last_activity']) : ''; $ts = '' !== $activity ? strtotime($activity) : false; if (false !== $ts && $ts > $latest_ts) { $latest_ts = (int) $ts; $latest = $activity; } } return $latest; } } if (!function_exists('matewa_lead_history_month_label')) { function matewa_lead_history_month_label($month_key, $format = 'M Y') { $month_key = preg_match('/^\d{4}-\d{2}$/', (string) $month_key) ? (string) $month_key : matewa_lead_history_current_month_key(); $ts = strtotime($month_key . '-01 00:00:00'); return false !== $ts ? date_i18n($format, $ts) : $month_key; } } if (!function_exists('matewa_prepare_lead_history_month_rows')) { function matewa_prepare_lead_history_month_rows(array $history, $limit = 6) { $rows = []; $current_month_key = matewa_lead_history_current_month_key(); $monthly = is_array($history['monthly'] ?? null) ? $history['monthly'] : []; if (!isset($monthly[$current_month_key])) { $monthly[$current_month_key] = [ 'completed_leads' => absint($history['month_total'] ?? 0), 'whatsapp_handoffs' => 0, 'lead_emails_sent' => 0, 'phone_only_leads' => 0, 'widget_opens' => 0, 'last_activity' => sanitize_text_field((string) ($history['last_activity'] ?? '')), ]; } krsort($monthly); foreach ($monthly as $month_key => $month_row) { $month_key = preg_match('/^\d{4}-\d{2}$/', (string) $month_key) ? (string) $month_key : ''; if ('' === $month_key) { continue; } $month_row = matewa_lead_history_normalise_month_row($month_row); $activity = ''; if ('' !== $month_row['last_activity']) { $activity_ts = strtotime($month_row['last_activity']); if (false !== $activity_ts) { $activity = date_i18n(get_option('date_format', 'j M Y'), $activity_ts); } } $row_widget_opens = absint($month_row['widget_opens'] ?? 0); $row_whatsapp_handoffs = absint($month_row['whatsapp_handoffs']); $row_handoff_rate = 0; $row_handoff_state = 'waiting'; $row_handoff_label = 'Waiting'; if (0 < $row_widget_opens) { if ($row_whatsapp_handoffs > $row_widget_opens) { $row_handoff_state = 'calibrating'; $row_handoff_label = 'Calibrating'; } else { $row_handoff_rate = (int) round(($row_whatsapp_handoffs / max(1, $row_widget_opens)) * 100); $row_handoff_state = 'ready'; $row_handoff_label = (string) $row_handoff_rate . '%'; } } $rows[] = [ 'month_key' => $month_key, 'month_label' => matewa_lead_history_month_label($month_key, 'M Y'), 'completed_leads' => absint($month_row['completed_leads']), 'whatsapp_handoffs' => $row_whatsapp_handoffs, 'lead_emails_sent' => absint($month_row['lead_emails_sent']), 'phone_only_leads' => absint($month_row['phone_only_leads']), 'widget_opens' => $row_widget_opens, 'handoff_rate' => $row_handoff_rate, 'handoff_rate_state' => $row_handoff_state, 'handoff_rate_label' => $row_handoff_label, 'last_activity' => '' !== $activity ? $activity : 'None recorded', ]; if (count($rows) >= absint($limit)) { break; } } return $rows; } } if (!function_exists('matewa_record_lead_history_event')) { function matewa_record_lead_history_event(array $increments = []) { $completed_leads = absint($increments['completed_leads'] ?? 0); $whatsapp_handoffs = absint($increments['whatsapp_handoffs'] ?? 0); $lead_emails_sent = absint($increments['lead_emails_sent'] ?? 0); $phone_only_leads = absint($increments['phone_only_leads'] ?? 0); $widget_opens = absint($increments['widget_opens'] ?? 0); $page_path = matewa_lead_history_sanitise_page_path($increments['page_path'] ?? ''); $page_title = matewa_lead_history_sanitise_page_title($increments['page_title'] ?? '', $page_path); $updates_lead_activity = (0 < $completed_leads || 0 < $whatsapp_handoffs || 0 < $lead_emails_sent || 0 < $phone_only_leads); if (0 === $completed_leads && 0 === $whatsapp_handoffs && 0 === $lead_emails_sent && 0 === $phone_only_leads && 0 === $widget_opens) { return false; } $history = matewa_get_lead_history_aggregates(); $current_year = matewa_lead_history_current_year_key(); $current_week = matewa_lead_history_current_week_key(); $current_month = matewa_lead_history_current_month_key(); $now = current_time('mysql'); if (($history['year_key'] ?? '') !== $current_year) { $history['year_key'] = $current_year; $history['yearly_total'] = 0; } if (($history['week_key'] ?? '') !== $current_week) { $history['week_key'] = $current_week; $history['week_total'] = 0; } if (!is_array($history['monthly'] ?? null)) { $history['monthly'] = []; } $month_row = isset($history['monthly'][$current_month]) ? matewa_lead_history_normalise_month_row($history['monthly'][$current_month]) : matewa_lead_history_empty_month_row(); $month_row['completed_leads'] = absint($month_row['completed_leads']) + $completed_leads; $month_row['whatsapp_handoffs'] = absint($month_row['whatsapp_handoffs']) + $whatsapp_handoffs; $month_row['lead_emails_sent'] = absint($month_row['lead_emails_sent']) + $lead_emails_sent; $month_row['phone_only_leads'] = absint($month_row['phone_only_leads']) + $phone_only_leads; $month_row['widget_opens'] = absint($month_row['widget_opens'] ?? 0) + $widget_opens; if ($updates_lead_activity) { $month_row['last_activity'] = $now; } $history['monthly'][$current_month] = $month_row; $history['yearly_total'] = absint($history['yearly_total'] ?? 0) + $completed_leads; $history['month_total'] = absint($month_row['completed_leads']); $history['week_total'] = absint($history['week_total'] ?? 0) + $completed_leads; $history['whatsapp_handoffs'] = absint($history['whatsapp_handoffs'] ?? 0) + $whatsapp_handoffs; $history['lead_emails_sent'] = absint($history['lead_emails_sent'] ?? 0) + $lead_emails_sent; $history['phone_only_leads'] = absint($history['phone_only_leads'] ?? 0) + $phone_only_leads; $history['widget_opens'] = absint($history['widget_opens'] ?? 0) + $widget_opens; if ($updates_lead_activity) { $history['last_activity'] = $now; } $saved = matewa_save_lead_history_aggregates($history); if ('' !== $page_path && function_exists('matewa_record_lead_history_page_event')) { matewa_record_lead_history_page_event([ 'page_path' => $page_path, 'page_title' => $page_title, 'widget_opens' => $widget_opens, 'completed_leads' => $completed_leads, ]); } return $saved; } } if (!function_exists('matewa_record_lead_history_widget_open')) { function matewa_record_lead_history_widget_open(array $meta = []) { return matewa_record_lead_history_event([ 'widget_opens' => 1, 'page_path' => $meta['page_path'] ?? '', 'page_title' => $meta['page_title'] ?? '', ]); } } if (!function_exists('matewa_record_lead_history_phone_only_lead')) { function matewa_record_lead_history_phone_only_lead(array $lead = []) { return matewa_record_lead_history_event([ 'completed_leads' => 1, 'whatsapp_handoffs' => 0, 'lead_emails_sent' => 1, 'phone_only_leads' => 1, 'page_path' => $lead['page_path'] ?? '', 'page_title' => $lead['page_title'] ?? '', ]); } } if (!function_exists('matewa_record_lead_history_completed_lead')) { function matewa_record_lead_history_completed_lead(array $lead = []) { $handoff_method = sanitize_key((string) ($lead['handoff_method'] ?? '')); $has_whatsapp_handoff = in_array($handoff_method, ['now', 'later', 'whatsapp', 'app', 'web', 'browser', 'native'], true); return matewa_record_lead_history_event([ 'completed_leads' => 1, 'whatsapp_handoffs' => $has_whatsapp_handoff ? 1 : 0, 'lead_emails_sent' => 1, 'page_path' => $lead['page_path'] ?? '', 'page_title' => $lead['page_title'] ?? '', ]); } }