array( 'label' => 'Order Confirmation', 'description' => 'Sent immediately when a WooCommerce order payment is successfully done.', 'placeholders' => '{{1}} = Order ID, {{2}} = Order Amount', 'sample' => "Thank you for shopping with Admark šŸ™\n\nYour order has been successfully placed.\n\nšŸ“¦ Order ID: {{1}}\nšŸ’° Amount: ₹{{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'order_id', 2 => 'order_total' ), ), 'payment_confirmation' => array( 'label' => 'Payment Confirmation', 'description' => 'Sent when payment status changes to processing or completed successfully.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Order ID', 'sample' => "Hi {{1}}\n\nWe have received your payment successfully for Order ID {{2}} āœ…\n\nYour order is now being processed.", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'order_id' ), ), 'order_dispatch' => array( 'label' => 'Order Dispatch', 'description' => 'Sent when order status changes to Shipped or Dispatched.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Order ID, {{3}} = Tracking Link', 'sample' => "Good news {{1}} šŸŽ‰\n\nYour Admark order has been dispatched.\n\nšŸ“¦ Order ID: {{2}}\n🚚 Tracking Link: {{3}}", 'var_count' => 3, 'var_defaults' => array( 1 => 'customer_name', 2 => 'order_id', 3 => 'tracking_link' ), ), 'delivery_confirmation' => array( 'label' => 'Delivery Confirmation', 'description' => 'Sent immediately when order status changes to Completed.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Order ID', 'sample' => "Hi {{1}}\n\nYour Admark order ID {{2}} has been delivered successfully āœ…\n\nThank you for shopping with Admark šŸ™", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'order_id' ), ), 'feedback_request' => array( 'label' => 'Feedback / Review Request', 'description' => 'Sent automatically after delivery status triggers.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Review Link', 'sample' => "Namaste {{1}}\n\nWe hope you loved your purchase 😊\n\nPlease share your feedback:\n{{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'review_link' ), ), 'reorder_reminder' => array( 'label' => 'Repeat Purchase / Reorder', 'description' => 'Sent to customer if no new purchase is made within the configured days/months.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Shop Link', 'sample' => "Hello {{1}}\n\nRunning low on your favorite products?\n\nšŸ›’ Reorder here:\n{{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'shop_url' ), ), 'welcome' => array( 'label' => 'Welcome Message', 'description' => 'Sent ONLY FIRST TIME when a new customer profile registers or logs in.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Shop Link', 'sample' => "Namaste {{1}} šŸ‘‹\n\nWelcome to Admark Online Shopping.\n\nšŸ›’ Shop Now: {{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'shop_url' ), ), 'add_to_cart' => array( 'label' => 'Add to Cart Reminder', 'description' => 'Sent as per set delay time if products are added but not purchased.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Cart URL', 'sample' => "Hi {{1}} 😊\n\nYou left items in your cart. Complete your order here:\n{{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'cart_url' ), ), 'abandoned_cart' => array( 'label' => 'Abandoned Cart', 'description' => 'Sent after cart reminder delay limits trigger without checkout.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Cart URL', 'sample' => "Hello {{1}} šŸ›’\n\nYour selected items are waiting. Resume order here:\n{{2}}", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'cart_url' ), ), 'payment_failed' => array( 'label' => 'Payment Failed', 'description' => 'Sent immediately when an order payment fails.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Order ID', 'sample' => "Hi {{1}}\n\nWe were unable to process your payment for Order ID {{2}} āŒ. Please try again.", 'var_count' => 2, 'var_defaults' => array( 1 => 'customer_name', 2 => 'order_id' ), ), 'refund' => array( 'label' => 'Refund', 'description' => 'Sent immediately when a WooCommerce order is refunded.', 'placeholders' => '{{1}} = Customer Name, {{2}} = Order ID, {{3}} = Refund Amount', 'sample' => "Hi {{1}}\n\nYour refund for Order ID {{2}} has been processed āœ…\n\nAmount: ₹{{3}}", 'var_count' => 3, 'var_defaults' => array( 1 => 'customer_name', 2 => 'order_id', 3 => 'order_total' ), ), 'offer_campaign' => array( 'label' => 'Offer & Festival Campaign', 'description' => 'Promotional blast engine dashboard handler.', 'placeholders' => '{{1}} = Shop/Offer Link', 'sample' => "šŸŽ‰ Admark Festive Offer! Check deals here:\n{{1}}", 'var_count' => 1, 'var_defaults' => array( 1 => 'shop_url' ), ) ); } // Option getters function wats_get_api_key() { return trim((string)get_option('wats_api_key', '')); } function wats_get_phone_number_id() { return trim((string)get_option('wats_phone_number_id', '')); } function wats_get_selected_template() { return trim((string)get_option('wats_selected_template', '')); } function wats_get_event_template( $event ) { return trim((string)get_option('wats_tpl_' . $event, '')); } function wats_get_event_enabled( $event ) { return (bool)get_option('wats_enable_' . $event, 0); } function wats_get_event_delay( $event ) { $defaults = array( 'welcome' => array( 'value' => 0, 'unit' => 'minutes' ), 'add_to_cart' => array( 'value' => 20, 'unit' => 'minutes' ), 'abandoned_cart' => array( 'value' => 3, 'unit' => 'hours' ), 'feedback_request' => array( 'value' => 2, 'unit' => 'days' ), 'reorder_reminder' => array( 'value' => 1, 'unit' => 'months' ) ); $def = isset( $defaults[ $event ] ) ? $defaults[ $event ] : array( 'value' => 0, 'unit' => 'minutes' ); $val = (int) get_option( 'wats_delay_val_' . $event, $def['value'] ); $unit = sanitize_key( (string) get_option( 'wats_delay_unit_' . $event, $def['unit'] ) ); switch ( $unit ) { case 'hours': return $val * HOUR_IN_SECONDS; case 'days': return $val * DAY_IN_SECONDS; case 'months': return $val * 30 * DAY_IN_SECONDS; default: return $val * MINUTE_IN_SECONDS; } } // ==== VARIABLE MAPPING HELPERS ==== function wats_get_variable_options() { return array( 'customer_name' => 'Customer Name', 'phone' => 'Mobile Number', 'email' => 'Email', 'billing_address' => 'Billing Address', 'order_id' => 'Order ID', 'order_total' => 'Order Amount', 'product_names' => 'Product Name(s)', 'product_qty' => 'Product Quantity', 'tracking_link' => 'Tracking Link', 'shop_url' => 'Shop URL', 'cart_url' => 'Cart URL', 'review_link' => 'Review Link', ); } function wats_get_var_map( $event, $slot ) { $saved = trim( (string) get_option( 'wats_varmap_' . $event . '_' . $slot, '' ) ); if ( $saved !== '' ) { return $saved; } $events = wats_get_events(); return isset( $events[ $event ]['var_defaults'][ $slot ] ) ? $events[ $event ]['var_defaults'][ $slot ] : ''; } function wats_resolve_var( $key, $order = null, $user = null ) { switch ( $key ) { case 'customer_name': if ( $order ) { return trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() ); } if ( $user ) { return trim( $user->first_name . ' ' . $user->last_name ) ?: $user->display_name; } return ''; case 'phone': if ( $order ) { return $order->get_billing_phone(); } if ( $user ) { return (string) get_user_meta( $user->ID, 'billing_phone', true ); } return ''; case 'email': if ( $order ) { return $order->get_billing_email(); } if ( $user ) { return $user->user_email; } return ''; case 'billing_address': if ( $order ) { return wp_strip_all_tags( $order->get_formatted_billing_address() ); } return ''; case 'order_id': if ( $order ) { return (string) $order->get_id(); } return ''; case 'order_total': if ( $order ) { return html_entity_decode( wp_strip_all_tags( $order->get_formatted_order_total() ) ); } return ''; case 'product_names': if ( $order ) { $names = array(); foreach ( $order->get_items() as $item ) { $names[] = $item->get_name(); } return implode( ', ', $names ); } return ''; case 'product_qty': if ( $order ) { $qtys = array(); foreach ( $order->get_items() as $item ) { $qtys[] = (string) $item->get_quantity(); } return implode( ', ', $qtys ); } return ''; case 'tracking_link': if ( $order ) { $link = (string) $order->get_meta( '_wats_tracking_link' ); return $link !== '' ? $link : home_url(); } return home_url(); case 'shop_url': return function_exists( 'wc_get_page_id' ) ? ( get_permalink( wc_get_page_id( 'shop' ) ) ?: home_url( '/shop/' ) ) : home_url( '/shop/' ); case 'cart_url': return function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : home_url( '/cart/' ); case 'review_link': if ( $order ) { return get_permalink( $order->get_id() ) ?: home_url(); } return home_url(); default: return ''; } } // ==== SANITIZERS ==== function wats_sanitize_api_key( $value ) { return sanitize_text_field( (string) $value ); } function wats_sanitize_phone_number_id( $value ) { return preg_replace( '/\D+/', '', sanitize_text_field( (string) $value ) ); } function wats_sanitize_selected_template( $value ) { $val = sanitize_text_field( (string) $value ); if ( $val === '' ) { return ''; } $templates = get_transient( 'wats_templates_cache' ) ?: wats_fetch_templates(); return is_array( $templates ) && in_array( $val, $templates, true ) ? $val : ''; } function wats_sanitize_send_count( $value ) { return absint( $value ); } function wats_sanitize_send_log( $value ) { if ( ! is_array( $value ) ) { return array(); } $out = array(); foreach ( $value as $entry ) { if ( is_array( $entry ) && isset($entry['utc']) ) { $out[] = array( 'local' => sanitize_text_field($entry['local'] ?? ''), 'utc' => (int)$entry['utc'], 'event' => sanitize_text_field($entry['event'] ?? 'campaign'), 'recipient' => sanitize_text_field($entry['recipient'] ?? 'Unknown'), 'template' => sanitize_text_field($entry['template'] ?? '—') ); } } return count( $out ) > 5000 ? array_slice( $out, -5000 ) : $out; } function wats_normalize_phone( $raw ) { $digits = preg_replace( '/\D+/', '', (string) $raw ); if ( strlen( $digits ) === 11 && wats_str_starts_with( $digits, '0' ) ) { $digits = substr( $digits, 1 ); } if ( wats_str_starts_with( $digits, '91' ) && strlen( $digits ) === 12 ) { return $digits; } return strlen( $digits ) === 10 ? '91' . $digits : $digits; } function wats_build_csv_for_event( $event, $order = null, $user = null ) { $var_count = (int) get_option( 'wats_varcount_' . $event, 0 ); if ( $var_count <= 0 ) { $events = wats_get_events(); $var_count = isset( $events[ $event ]['var_count'] ) ? (int) $events[ $event ]['var_count'] : 2; } $vars = array(); for ( $i = 1; $i <= $var_count; $i++ ) { $map_key = wats_get_var_map( $event, $i ); $vars[] = $map_key !== '' ? wats_resolve_var( $map_key, $order, $user ) : ''; } return implode( ',', array_map( 'rawurlencode', $vars ) ); } function wats_build_url( $args ) { $params = array( 'api-key' => wats_get_api_key(), 'templateName' => $args['templateName'] ?? '', 'phoneNumber' => $args['phoneNumber'] ?? '', 'phoneNumberId' => wats_get_phone_number_id(), 'csvVariables' => $args['csvVariables'] ?? '', ); return add_query_arg( array_filter( $params ), WATS_API_BASE ); } // ==== UNIVERSAL MASTER LOGGING DISPATCH WRAPPER ==== function wats_send_template( $order, $event = 'order_confirmation', $user = null ) { try { $template = wats_get_event_template( $event ); if ( $template === '' && $event === 'order_confirmation' ) { $template = wats_get_selected_template(); } if ( empty( $template ) ) { return false; } $raw_phone = ''; if ( $order && class_exists( 'WC_Order' ) && ( $order instanceof WC_Order ) ) { $raw_phone = $order->get_billing_phone(); } elseif ( $user ) { $raw_phone = get_user_meta( $user->ID, 'billing_phone', true ); } if ( empty( $raw_phone ) ) { return false; } $phone = wats_normalize_phone( $raw_phone ); $csv = wats_build_csv_for_event( $event, $order, $user ); $response = wp_remote_get( wats_build_url( array( 'templateName' => $template, 'phoneNumber' => $phone, 'csvVariables' => $csv ) ), array( 'timeout' => 15 ) ); if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) == 200 ) { $count = (int) get_option( 'wats_send_count', 0 ); update_option( 'wats_send_count', $count + 1, false ); $log = get_option( 'wats_send_log', array() ); $log[] = array( 'local' => current_time( 'mysql' ), 'utc' => time(), 'event' => $event, 'recipient' => $phone, 'template' => $template ); update_option( 'wats_send_log', $log, false ); return true; } } catch ( Throwable $e ) {} return false; } // ==== WOOCOMMERCE AUTOMATION FLOW ENGINES ==== // Order & Payment Confirmation Sync Dispatches add_action( 'woocommerce_order_status_processing', 'wats_trigger_order_payment_success', 20, 1 ); add_action( 'woocommerce_order_status_completed', 'wats_trigger_order_payment_success', 20, 1 ); function wats_trigger_order_payment_success( $order_id ) { if ( ! $order_id ) { return; } $order = wc_get_order( $order_id ); if ( ! $order ) { return; } if ( wats_get_event_enabled( 'order_confirmation' ) && ! $order->get_meta( '_wats_order_confirmation_sent' ) ) { if ( wats_send_template( $order, 'order_confirmation' ) ) { $order->update_meta_data( '_wats_order_confirmation_sent', current_time( 'mysql' ) ); } } if ( wats_get_event_enabled( 'payment_confirmation' ) && ! $order->get_meta( '_wats_payment_confirmation_sent' ) ) { if ( wats_send_template( $order, 'payment_confirmation' ) ) { $order->update_meta_data( '_wats_payment_confirmation_sent', current_time( 'mysql' ) ); } } $order->save(); } // Order Dispatch Logic Hook add_action( 'woocommerce_order_status_shipped', 'wats_handle_order_dispatch', 10, 1 ); add_action( 'woocommerce_order_status_dispatched', 'wats_handle_order_dispatch', 10, 1 ); function wats_handle_order_dispatch( $order_id ) { if ( ! wats_get_event_enabled( 'order_dispatch' ) ) { return; } $order = wc_get_order( $order_id ); if ( $order && ! $order->get_meta( '_wats_dispatch_sent' ) ) { if ( wats_send_template( $order, 'order_dispatch' ) ) { $order->update_meta_data( '_wats_dispatch_sent', current_time( 'mysql' ) ); $order->save(); } } } // Delivery Confirmation & Delayed Feedback Automation Trigger add_action( 'woocommerce_order_status_completed', function( $order_id ) { if ( ! $order_id ) { return; } $order = wc_get_order( $order_id ); if ( ! $order ) { return; } if ( wats_get_event_enabled( 'delivery_confirmation' ) && ! $order->get_meta( '_wats_delivery_sent' ) ) { if ( wats_send_template( $order, 'delivery_confirmation' ) ) { $order->update_meta_data( '_wats_delivery_sent', current_time( 'mysql' ) ); } } if ( wats_get_event_enabled( 'feedback_request' ) && ! $order->get_meta( '_wats_feedback_scheduled' ) ) { $delay = wats_get_event_delay('feedback_request'); wp_schedule_single_event( time() + max(60, $delay), 'wats_send_feedback_cron', array( $order_id ) ); $order->update_meta_data( '_wats_feedback_scheduled', '1' ); } $order->save(); }, 10, 1 ); add_action( 'wats_send_feedback_cron', function( $order_id ) { $order = wc_get_order( $order_id ); if ( $order && ! $order->get_meta( '_wats_feedback_sent' ) ) { if ( wats_send_template( $order, 'feedback_request' ) ) { $order->update_meta_data( '_wats_feedback_sent', current_time( 'mysql' ) ); $order->save(); } } }, 10, 1 ); // ==== MASTER PAYMENT FAILED HANDLERS (CRITICAL HOOK SYNC) ==== add_action( 'woocommerce_order_status_failed', 'wats_handle_payment_failed_event', 10, 1 ); add_action( 'woocommerce_order_status_changed', 'wats_handle_payment_failed_status_changed', 10, 3 ); function wats_handle_payment_failed_event( $order_id ) { if ( ! wats_get_event_enabled( 'payment_failed' ) || ! $order_id ) { return; } $order = wc_get_order( $order_id ); if ( $order && ! $order->get_meta( '_wats_payment_failed_sent' ) ) { if ( wats_send_template( $order, 'payment_failed', null ) ) { $order->update_meta_data( '_wats_payment_failed_sent', current_time( 'mysql' ) ); $order->save(); } } } function wats_handle_payment_failed_status_changed( $order_id, $old_status, $new_status ) { if ( 'failed' === $new_status ) { wats_handle_payment_failed_event( $order_id ); } } // Order Refund Trigger Hook add_action( 'woocommerce_order_refunded', function( $order_id, $refund_id ) { if ( ! wats_get_event_enabled( 'refund' ) ) { return; } $order = wc_get_order( $order_id ); if ( $order && ! $order->get_meta( '_wats_refund_sent_' . $refund_id ) ) { if ( wats_send_template( $order, 'refund' ) ) { $order->update_meta_data( '_wats_refund_sent_' . $refund_id, current_time( 'mysql' ) ); $order->save(); } } }, 10, 2 ); // Welcome Message — ENFORCE ONCE FOR FIRST TIME LOGINS / REGISTRATIONS add_action( 'wp_login', 'wats_trigger_welcome_first_time', 10, 2 ); add_action( 'user_register', 'wats_trigger_welcome_first_time_reg', 10, 1 ); function wats_trigger_welcome_first_time_reg( $user_id ) { wats_execute_welcome_logic($user_id); } function wats_trigger_welcome_first_time( $user_login, $user ) { wats_execute_welcome_logic($user->ID); } function wats_execute_welcome_logic( $user_id ) { if ( ! wats_get_event_enabled( 'welcome' ) ) { return; } if ( get_user_meta( $user_id, '_wats_welcome_sent', true ) ) { return; } $user = get_userdata( $user_id ); if ( wats_send_template( null, 'welcome', $user ) ) { update_user_meta( $user_id, '_wats_welcome_sent', current_time('mysql') ); } } // Add to Cart & Abandoned Scheduler Core Hook add_action( 'woocommerce_add_to_cart', function() { $user_id = get_current_user_id(); if ( ! $user_id ) { return; } $args = array( $user_id ); if ( wats_get_event_enabled( 'add_to_cart' ) ) { $existing_cart = wp_next_scheduled( 'wats_send_cart_reminder', $args ); if ( $existing_cart ) { wp_unschedule_event( $existing_cart, 'wats_send_cart_reminder', $args ); } wp_schedule_single_event( time() + max( 60, wats_get_event_delay( 'add_to_cart' ) ), 'wats_send_cart_reminder', $args ); } if ( wats_get_event_enabled( 'abandoned_cart' ) ) { $existing_abandoned = wp_next_scheduled( 'wats_send_abandoned_cart', $args ); if ( $existing_abandoned ) { wp_unschedule_event( $existing_abandoned, 'wats_send_abandoned_cart', $args ); } wp_schedule_single_event( time() + max( 120, wats_get_event_delay( 'abandoned_cart' ) ), 'wats_send_abandoned_cart', $args ); } }, 10, 0 ); add_action( 'woocommerce_thankyou', function( $order_id ) { $order = wc_get_order( $order_id ); $user_id = $order ? $order->get_user_id() : 0; if ( $user_id ) { foreach ( array( 'wats_send_cart_reminder', 'wats_send_abandoned_cart' ) as $hook ) { $existing = wp_next_scheduled( $hook, array( $user_id ) ); if ( $existing ) { wp_unschedule_event( $existing, $hook, array( $user_id ) ); } } } }, 5, 1 ); add_action( 'wats_send_cart_reminder', function( $user_id ) { $user = get_userdata( $user_id ); wats_send_template( null, 'add_to_cart', $user ); }, 10, 1 ); add_action( 'wats_send_abandoned_cart', function( $user_id ) { $user = get_userdata( $user_id ); wats_send_template( null, 'abandoned_cart', $user ); }, 10, 1 ); // Reorder Reminder Core Engine if ( ! wp_next_scheduled( 'wats_reorder_reminder_daily_daemon' ) ) { wp_schedule_event( time(), 'daily', 'wats_reorder_reminder_daily_daemon' ); } add_action( 'wats_reorder_reminder_daily_daemon', function() { if ( ! wats_get_event_enabled( 'reorder_reminder' ) ) { return; } $delay_threshold_seconds = wats_get_event_delay( 'reorder_reminder' ); $template = wats_get_event_template( 'reorder_reminder' ); if ( empty($template) ) { return; } $users = get_users( array( 'fields' => array( 'ID' ), 'number' => 5000 ) ); foreach ( $users as $u ) { $last_pur = get_user_meta( $u->ID, '_wats_last_purchase_timestamp', true ); if ( ! empty($last_pur) && ( time() - (int)$last_pur >= $delay_threshold_seconds ) ) { $user = get_userdata($u->ID); if ( wats_send_template( null, 'reorder_reminder', $user ) ) { update_user_meta( $u->ID, '_wats_last_purchase_timestamp', time() ); } } } } ); add_action( 'woocommerce_thankyou', function( $order_id ) { $order = wc_get_order( $order_id ); $user_id = $order ? $order->get_user_id() : 0; if ( $user_id ) { update_user_meta( $user_id, '_wats_last_purchase_timestamp', time() ); } }, 20, 1 ); // ==== TEMPLATE CACHE MANAGEMENT ==== function wats_fetch_templates() { $api_key = wats_get_api_key(); if ( empty($api_key) ) { return array(); } $url = add_query_arg( array( 'api-key' => $api_key ), 'https://verifiedwhatsapp.admarksolution.com/templates' ); $response = wp_remote_get( $url, array( 'timeout' => 15 ) ); if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) != 200 ) { return array(); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); $out = array(); $var_counts = array(); if ( is_array( $data ) ) { foreach ( $data as $item ) { if ( is_string( $item ) ) { $out[] = $item; } elseif ( is_array( $item ) && isset( $item['name'] ) ) { $name = $item['name']; $out[] = $name; $count = 0; if ( isset( $item['components'] ) && is_array( $item['components'] ) ) { foreach ( $item['components'] as $comp ) { if ( strtoupper( $comp['type'] ?? '' ) === 'BODY' && isset( $comp['text'] ) ) { if ( preg_match_all( '/\{\{(\d+)\}\}/', $comp['text'], $m ) ) { $count = max( array_map( 'intval', $m[1] ) ); } } } } $var_counts[$name] = $count; } } } set_transient( 'wats_templates_cache', $out, 10 * MINUTE_IN_SECONDS ); set_transient( 'wats_template_vars_cache', $var_counts, 10 * MINUTE_IN_SECONDS ); return $out; } function wats_get_template_var_counts() { return get_transient( 'wats_template_vars_cache' ) ?: array(); } // ==== AJAX HANDLERS ==== add_action( 'wp_ajax_wats_get_template_vars', 'wats_ajax_get_template_vars_handler' ); add_action( 'wp_ajax_nopriv_wats_get_template_vars', 'wats_ajax_get_template_vars_handler' ); function wats_ajax_get_template_vars_handler() { check_ajax_referer( 'wats_ajax_nonce', 'nonce' ); $template_name = sanitize_text_field( $_GET['template'] ?? '' ); $api_key = wats_get_api_key(); $url = add_query_arg( array( 'name' => $template_name, 'api-key' => $api_key ), 'https://verifiedwhatsapp.admarksolution.com/template-byname' ); $response = wp_remote_get( $url, array( 'timeout' => 15 ) ); if ( is_wp_error( $response ) ) { wp_send_json_error(); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); $var_count = 0; if ( isset( $data['components'] ) ) { foreach ( $data['components'] as $comp ) { if ( strtoupper( $comp['type'] ?? '' ) === 'BODY' && isset( $comp['text'] ) ) { if ( preg_match_all( '/\{\{(\d+)\}\}/', $comp['text'], $m ) ) { $var_count = max( array_map( 'intval', $m[1] ) ); } } } } wp_send_json_success( array( 'var_count' => $var_count ) ); } add_action( 'wp_ajax_wats_get_campaign_customers', 'wats_ajax_get_campaign_customers_handler' ); add_action( 'wp_ajax_nopriv_wats_get_campaign_customers', 'wats_ajax_get_campaign_customers_handler' ); function wats_ajax_get_campaign_customers_handler() { check_ajax_referer( 'wats_ajax_nonce', 'nonce' ); $paged = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; $search = isset( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : ''; $number = 100; $args = array( 'number' => $number, 'offset' => ($paged - 1) * $number, 'fields' => array( 'ID', 'user_email', 'display_name' ) ); if ( ! empty( $search ) ) { $args['search'] = '*' . $search . '*'; } $user_query = new WP_User_Query( $args ); $customers = $user_query->get_results(); $list = array(); foreach ( $customers as $user ) { $phone = get_user_meta( $user->ID, 'billing_phone', true ); $list[] = array( 'id' => $user->ID, 'name' => $user->display_name ?: 'No Name', 'email' => $user->user_email, 'phone' => ! empty( $phone ) ? $phone : 'āš ļø No Phone Registered', 'no_phone' => empty( $phone ) ); } wp_send_json_success( array( 'customers' => $list, 'total_users' => $user_query->get_total(), 'page' => $paged, 'total_pages' => ceil( $user_query->get_total() / $number ) ) ); } // ==== LEFT BAR MENU SUB-LEVEL MANAGEMENT ==== add_action( 'admin_menu', function () { add_menu_page( 'Admark CRM', 'Admark CRM', 'manage_options', 'wats-settings', 'wats_render_settings_page', 'dashicons-whatsapp', 56 ); add_submenu_page( 'wats-settings', 'Settings', 'Settings', 'manage_options', 'wats-settings', 'wats_render_settings_page' ); add_submenu_page( 'wats-settings', 'Automation', 'Automation', 'manage_options', 'wats-automation', 'wats_render_automation_page' ); add_submenu_page( 'wats-settings', 'Message Templates', 'Message Templates', 'manage_options', 'wats-message-templates', 'wats_render_message_templates_page' ); add_submenu_page( 'wats-settings', 'Message Logs', 'Message Logs', 'manage_options', 'wats-message-logs', 'wats_render_message_logs_page' ); } ); add_action( 'admin_init', function () { register_setting( 'wats_settings_group', 'wats_api_key', array( 'sanitize_callback' => 'wats_sanitize_api_key' ) ); register_setting( 'wats_settings_group', 'wats_phone_number_id', array( 'sanitize_callback' => 'wats_sanitize_phone_number_id' ) ); register_setting( 'wats_settings_group', 'wats_selected_template', array( 'sanitize_callback' => 'wats_sanitize_selected_template' ) ); register_setting( 'wats_settings_group', 'wats_send_count', array( 'sanitize_callback' => 'wats_sanitize_send_count' ) ); register_setting( 'wats_settings_group', 'wats_send_log', array( 'sanitize_callback' => 'wats_sanitize_send_log' ) ); foreach ( array_keys( wats_get_events() ) as $event ) { register_setting( 'wats_automation_group', 'wats_enable_' . $event, array( 'sanitize_callback' => 'absint' ) ); register_setting( 'wats_automation_group', 'wats_tpl_' . $event, array( 'sanitize_callback' => 'sanitize_text_field' ) ); register_setting( 'wats_automation_group', 'wats_varcount_' . $event, array( 'sanitize_callback' => 'absint' ) ); register_setting( 'wats_automation_group', 'wats_delay_val_' . $event, array( 'sanitize_callback' => 'absint' ) ); register_setting( 'wats_automation_group', 'wats_delay_unit_' . $event, array( 'sanitize_callback' => 'sanitize_key' ) ); } } ); add_action( 'admin_enqueue_scripts', function( $hook_suffix ) { $pages = array( 'toplevel_page_wats-settings', 'admark-crm_page_wats-automation', 'admark-crm_page_wats-message-templates', 'admark-crm_page_wats-message-logs' ); if ( ! in_array( $hook_suffix, $pages, true ) ) { return; } wp_enqueue_style( 'admark-crm-admin', plugins_url( 'assets/admin.css', __FILE__ ), array(), wats_get_plugin_version() ); wp_enqueue_script( 'admark-crm-admin', plugins_url( 'assets/admin.js', __FILE__ ), array('jquery'), wats_get_plugin_version(), true ); $events = wats_get_events(); $saved_maps_js = array(); foreach ( $events as $ek => $ev ) { $saved_maps_js[ $ek ] = array(); for ( $i = 1; $i <= 10; $i++ ) { $saved_maps_js[ $ek ][ $i ] = wats_get_var_map( $ek, $i ); } } wp_localize_script( 'admark-crm-admin', 'wats_setup_vars', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wats_ajax_nonce' ), 'tpl_var_counts' => wats_get_template_var_counts(), 'field_options' => wats_get_variable_options(), 'saved_maps' => $saved_maps_js ) ); } ); function wats_render_nav( $active ) { $tabs = array( 'wats-settings' => 'Settings', 'wats-automation' => 'Automation', 'wats-message-templates' => 'Message Templates', 'wats-message-logs' => 'Message Logs' ); echo ''; } function wats_render_settings_page() { $selected = wats_get_selected_template(); $total_sent = (int) get_option( 'wats_send_count', 0 ); $today_iso = current_time( 'Y-m-d' ); ?>

Admark CRM

v
Total Messages Sent
Active Default Template
Messages in Range
→ 0

API Configuration

API Key
Phone ID
'Welcome Delay', 'add_to_cart' => 'Cart Reminder Timer', 'abandoned_cart' => 'Abandoned Delay', 'feedback_request' => 'Feedback Delay', 'reorder_reminder' => 'Reorder Reminder Interval' ); ?>

Admark CRM

v

Offer & Festival Campaign Hub

Load your entire customer list, select a template profile, map your custom variables, and broadcast messages instantly to your chosen audience.

1. Target Customers0 Customers Selected
2. Campaign Template

Automation Flow

🌐 Visit
→
šŸ›’ Cart
→
ā° Abandoned
→
āœ… Order
→
šŸ’³ Payment
→
🚚 Dispatch
→
šŸ“¦ Delivered
→
⭐ Feedback
$ev ) : $enabled = wats_get_event_enabled($ek); $cur_tpl = wats_get_event_template($ek); ?>

Sample Structure placeholders:

Admark CRM

v

Message Dispatch Logs (History)

TimestampTrigger EventRecipientTemplate
No delivery history logs stored.
array( 'ID' ), 'number' => 15000 ) ); foreach ( $all_users as $u ) { $id_array[] = $u->ID; } } else { $id_array = explode( ',', $customers_raw ); } $success_count = 0; $log = get_option( 'wats_send_log', array() ); if ( is_array( $id_array ) && ! empty( $id_array ) ) { foreach ( $id_array as $uid ) { $user = get_userdata( intval( $uid ) ); if ( ! $user ) { continue; } $phone = get_user_meta( $user->ID, 'billing_phone', true ); if ( empty( $phone ) ) { continue; } $csv_resolved = array(); if ( is_array( $varmaps ) ) { foreach ( $varmaps as $slot => $key_field ) { $csv_resolved[] = ! empty( $key_field ) ? wats_resolve_var( $key_field, null, $user ) : ''; } } $csv_string = implode( ',', array_map( 'rawurlencode', $csv_resolved ) ); $response = wp_remote_get( wats_build_url( array( 'templateName' => $template, 'phoneNumber' => wats_normalize_phone( $phone ), 'csvVariables' => $csv_string ) ), array( 'timeout' => 15 ) ); if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) == 200 ) { $success_count++; $log[] = array( 'local' => current_time( 'mysql' ), 'utc' => time(), 'event' => 'campaign_direct', 'recipient' => wats_normalize_phone( $phone ), 'template' => $template ); } } } if ( $success_count > 0 ) { update_option( 'wats_send_count', (int) get_option( 'wats_send_count', 0 ) + $success_count, false ); update_option( 'wats_send_log', $log, false ); wp_send_json_success( $success_count . ' messages have been broadcasted and triggered immediately!' ); } else { wp_send_json_error( 'Failed to send messages. Please verify template connectivity configurations.' ); } } ); function wats_render_message_templates_page() { $events = wats_get_events(); ?>

Admark CRM

v2.0.0

Sample Message Templates

$ev ) : ?>