Plugin Directory

Changeset 3240206


Ignore:
Timestamp:
02/13/2025 03:09:47 PM (14 months ago)
Author:
usermaven
Message:

tagging version 1.1.3

Location:
usermaven
Files:
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • usermaven/tags/1.1.3/README.txt

    r3221608 r3240206  
    66Tested up to: 6.7.1
    77Requires PHP: 5.6
    8 Stable tag: 1.1.1
     8Stable tag: 1.1.3
    99License: Massachusetts Institute of Technology (MIT) license
    1010License URI: https://opensource.org/licenses/MIT
  • usermaven/tags/1.1.3/includes/class-usermaven-api.php

    r3217559 r3240206  
    99        $this->api_key = get_option('usermaven_api_key');
    1010        $this->api_url = "$tracking_host/api/v1/s2s/event";
     11    }
     12
     13    public function identify($user_data, $company_data = []) {
     14        $url = $this->api_url . "?token=$this->api_key.$this->server_token";
     15       
     16        // Get current timestamp in milliseconds
     17        $current_timestamp_ms = round(microtime(true) * 1000);
     18        $doc_encoding = get_bloginfo('charset');
     19
     20        $data = [
     21            'api_key' => $this->api_key,
     22            'event_type' => 'user_identify',
     23            '_timestamp' => (string)$current_timestamp_ms,
     24            'user' => $user_data,
     25            'company' => [
     26                'id' => $company_data['id'] ?? '',
     27                'name' => $company_data['name'] ?? '',
     28            ],
     29            'src' => 'http',
     30            'url' => $_SERVER['HTTP_REFERER'] ?? '',
     31            'page_title' => wp_get_document_title(),
     32            'doc_path' => $_SERVER['REQUEST_URI'] ?? '',
     33            'doc_host' => $_SERVER['HTTP_HOST'] ?? '',
     34            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
     35            'user_language' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
     36            'doc_encoding' => (string) $doc_encoding,
     37        ];
     38
     39        $response = wp_remote_post($url, [
     40            'body' => json_encode($data),
     41            'headers' => ['Content-Type' => 'application/json']
     42        ]);
     43
     44        if (is_wp_error($response)) {
     45            error_log('Usermaven API Error: ' . $response->get_error_message());
     46            return false;
     47        }
     48
     49        $body = wp_remote_retrieve_body($response);
     50        $result = json_decode($body, true);
     51        return $result['status'] === 'ok';
    1152    }
    1253
  • usermaven/tags/1.1.3/includes/class-usermaven-woocommerce.php

    r3221608 r3240206  
    3131     */
    3232    private function init_hooks() {
     33        // Track on WooCommerce specific login
     34        add_action('woocommerce_login_credentials', array($this, 'identify_wc_user'), 10, 2);
     35   
    3336        // Product Viewing
    3437        add_action('template_redirect', array($this, 'track_product_view'));
    35 
     38   
    3639        // Cart Actions
    3740        add_action('woocommerce_add_to_cart', array($this, 'track_add_to_cart'), 10, 6);
    3841        add_action('woocommerce_cart_item_removed', array($this, 'track_remove_from_cart'), 10, 2);
    3942        add_action('woocommerce_after_cart_item_quantity_update', array($this, 'track_cart_update'), 10, 4);
    40 
    41         // Checkout Process
    42         add_action('woocommerce_before_checkout_form', array($this, 'track_initiate_checkout'), 10);
    43         add_action('woocommerce_checkout_order_processed', array($this, 'track_order_submission'), 10, 3);
    44        
     43   
     44        // Checkout Process - Consolidated tracking
     45        // add_action('woocommerce_before_checkout_form', array($this, 'track_initiate_checkout'), 10); // Removed this because it was not triggering for custom checkout pages
     46        add_action('wp', array($this, 'maybe_track_checkout_init'));
     47        // add_action('woocommerce_checkout_order_processed', array($this, 'track_order_submission'), 10, 3); // Removed this because it was not triggering for custom checkout pages
     48        add_action('woocommerce_new_order', array($this, 'track_order_submission'), 10, 1);
     49   
    4550        // Order Status and Completion
    4651        // add_action('woocommerce_payment_complete', array($this, 'track_order_completed'));
     
    5459        add_action('woocommerce_order_status_refunded', array($this, 'track_order_refunded'), 10, 2);
    5560        add_action('woocommerce_order_status_draft', array($this, 'track_order_draft'), 10, 1);
    56 
     61   
    5762        // Track customer creation
    5863        add_action('woocommerce_created_customer', array($this, 'track_customer_created'), 10, 3);
    59 
    60         // Reset the tracking flag when the cart is updated or order completes/fails
    61         add_action('woocommerce_cart_updated', array($this, 'reset_initiate_checkout_tracking'));
    62         add_action('woocommerce_thankyou', array($this, 'track_order_thankyou'), 10);
     64   
     65        // Reset tracking state for cart updates
     66        add_action('woocommerce_cart_updated', array($this, 'reset_checkout_tracking'));
     67        add_action('woocommerce_cart_emptied', array($this, 'reset_checkout_tracking'));
     68        add_action('woocommerce_after_cart_item_quantity_update', array($this, 'reset_checkout_tracking'));
     69       
     70        // Reset tracking for order completion/failure
    6371        add_action('woocommerce_order_status_completed', array($this, 'reset_initiate_checkout_tracking'));
    6472        add_action('woocommerce_order_status_failed', array($this, 'reset_initiate_checkout_tracking'));
    65 
    66 
     73       
     74        // Track order thank you page
     75        add_action('woocommerce_thankyou', array($this, 'track_order_thankyou'), 10);
     76   
    6777        // Initialize cart abandonment tracking
    6878        add_action('woocommerce_init', function() {
    6979            $this->init_cart_abandonment_tracking();
    7080        });
    71 
     81   
    7282        // Add session cleanup on successful order
    7383        add_action('woocommerce_checkout_order_processed', function() {
     
    7686            WC()->session->set('last_activity', null);
    7787        });
    78 
     88   
    7989        // Wishlist Integration (if using WooCommerce Wishlist)
    8090        if (class_exists('YITH_WCWL')) {
     
    8494        }
    8595    }
     96
     97    /**
     98     * Identify user on WooCommerce login
     99     */
     100    public function identify_wc_user($credentials) {
     101        if (!empty($credentials['user_login'])) {
     102            $user = get_user_by('login', $credentials['user_login']);
     103            if ($user) {
     104                $this->send_user_identify_request($user);
     105            }
     106        }
     107        return $credentials;
     108    }
     109
     110    /**
     111     * Send identify call to Usermaven API
     112     *
     113     * @param WP_User $user User object
     114     */
     115    private function send_user_identify_request($user) {
     116        if (!$user) {
     117            return;
     118        }
     119
     120        // Get WooCommerce customer
     121        $customer = new WC_Customer($user->ID);
     122       
     123        // Get custom user data
     124        $roles = $user->roles;
     125        $primary_role = !empty($roles) ? $roles[0] : '';
     126
     127        // Get the anonymous_id from cookie if available
     128        $eventn_cookie_name = '__eventn_id_' . $this->api_key;
     129        $usermaven_cookie_name = 'usermaven_id_' . $this->api_key;
     130        $anonymous_id = '';
     131
     132        if (isset($_COOKIE[$eventn_cookie_name])) {
     133            $anonymous_id = $_COOKIE[$eventn_cookie_name];
     134        } elseif (isset($_COOKIE[$usermaven_cookie_name])) {
     135            $anonymous_id = $_COOKIE[$usermaven_cookie_name];
     136        }
     137
     138        $user_id = $user->ID;
     139        $user_email = $user->user_email;
     140
     141        // if user id is null use email as user id
     142        if (empty($user_id)) {
     143            $user_id = $user_email;
     144        }
     145
     146        // Prepare user data
     147        $user_data = array(
     148            'anonymous_id' => $anonymous_id,
     149            'id' => (string) $user_id,
     150            'email' => (string) $user_email,
     151            'created_at' => date('Y-m-d\TH:i:s', strtotime($user->user_registered)),
     152            'first_name' => $user->first_name,
     153            'last_name' => $user->last_name,
     154            'custom' => array(
     155                'role' => $primary_role,
     156                'username' => $user->user_login,
     157                'display_name' => $user->display_name,
     158                'billing_country' => $customer->get_billing_country(),
     159                'shipping_country' => $customer->get_shipping_country(),
     160                'is_paying_customer' => (bool) $customer->get_is_paying_customer()
     161            )
     162        );
     163
     164        // Prepare company data if available
     165        $company_data = array();
     166        $company_name = $customer->get_billing_company();
     167        if (!empty($company_name)) {
     168            $company_data = array(
     169                'id' => 'wc_' . md5($company_name . $customer->get_billing_email()),
     170                'name' => $company_name,
     171                'created_at' => date('Y-m-d\TH:i:s', strtotime($user->user_registered)),
     172                'custom' => array(
     173                    'billing_country' => $customer->get_billing_country(),
     174                    'billing_city' => $customer->get_billing_city(),
     175                    'billing_postcode' => $customer->get_billing_postcode()
     176                )
     177            );
     178        }
     179
     180        // Send identify request using the API
     181        $this->api->identify($user_data, $company_data);
     182    }
     183
    86184
    87185    /**
     
    407505
    408506    /**
    409      * Track checkout initiation
    410      */
    411     public function track_initiate_checkout() {
     507     * Single entry point for tracking checkout initialization
     508     * This ensures we don't have multiple competing triggers
     509     */
     510    public function maybe_track_checkout_init() {
     511        // Early exit conditions
    412512        if (WC()->cart->is_empty()) {
    413513            return;
    414514        }
    415    
     515
     516        // Get a unique identifier for current cart state
     517        $cart_hash = WC()->cart->get_cart_hash();
     518       
     519        // Get stored tracking data
     520        $tracked_cart_hash = WC()->session->get('usermaven_tracked_cart_hash');
     521        $last_tracked_time = WC()->session->get('usermaven_last_checkout_track_time');
     522        $current_time = time();
     523
     524        // Check if this specific cart state has been tracked recently
     525        if ($tracked_cart_hash === $cart_hash &&
     526            $last_tracked_time &&
     527            ($current_time - $last_tracked_time) < 300) { // 5 minutes threshold
     528            return;
     529        }
     530
     531        if (is_cart()) {
     532            return;
     533        }
     534
     535        // Check if we're actually on a checkout page/process
     536        $is_checkout_context = (
     537            // Only track on actual checkout page, not cart page
     538            (function_exists('is_checkout') && is_checkout()) ||
     539            // For custom checkout pages
     540            (has_shortcode(get_post()->post_content ?? '', 'woocommerce_checkout')) ||
     541            // For AJAX checkout requests
     542            (isset($_REQUEST['wc-ajax']) && $_REQUEST['wc-ajax'] === 'checkout')
     543        );
     544
     545        if (!$is_checkout_context) {
     546            return;
     547        }
     548
     549        $this->track_initiate_checkout($cart_hash);
     550        WC()->session->set('usermaven_initiate_checkout_tracked', true);
     551    }
     552
     553    /**
     554     * Track checkout initiation with duplicate prevention
     555     */
     556    private function track_initiate_checkout($cart_hash) {
    416557        // Prevent duplicate tracking
    417558        if (WC()->session->get('usermaven_initiate_checkout_tracked')) {
    418559            return;
    419560        }
    420    
     561
    421562        $cart = WC()->cart;
    422563        $items = array();
    423    
     564
    424565        // Get WC Countries object for location handling
    425566        $wc_countries = new WC_Countries();
     
    430571                continue;
    431572            }
    432    
     573
    433574            // Get the parent product if this is a variation
    434575            $parent_product = $product;
     
    436577                $parent_product = wc_get_product($product->get_parent_id());
    437578            }
    438    
     579
    439580            // Get product categories from parent product
    440581            $categories = array();
     
    443584                $categories = wp_list_pluck($terms, 'name');
    444585            }
    445    
     586
    446587            // Process variation attributes - keeping attribute_ prefix
    447588            $variation_attributes = array();
     
    451592                }
    452593            }
    453    
     594
    454595            // Get and validate prices
    455596            $unit_price = $product->get_price();
    456597            $unit_price = $unit_price === '' ? 0.0 : (float) $unit_price;
    457    
     598
    458599            $items[] = array(
    459600                'product_id' => (int) $parent_product->get_id(),
     
    465606                'line_tax' => (float) $cart_item['line_tax'],
    466607                'categories' => array_map('strval', $categories),
    467                 'variation_id' => !empty($cart_item['variation_id']) ? (int) $cart_item['variation_id'] : null,
     608                'variation_id' => isset($cart_item['variation_id']) ? (int) $cart_item['variation_id'] : null,
    468609                'variation_attributes' => $variation_attributes,
    469610                'is_on_sale' => (bool) $product->is_on_sale(),
     
    471612            );
    472613        }
    473    
     614           
    474615        $billing_country_code = WC()->customer->get_billing_country();
    475616        $shipping_country_code = WC()->customer->get_shipping_country();
    476    
     617
    477618        $event_attributes = array(
    478619            // Cart Financial Details
     620            'cart_hash' => $cart_hash,
    479621            'total' => (float) $cart->get_total('numeric'),
    480622            'subtotal' => (float) $cart->get_subtotal(),
     623            'cart_tax' => (float) $cart->get_cart_tax(),
    481624            'tax' => (float) $cart->get_total_tax(),
    482625            'shipping_total' => (float) $cart->get_shipping_total(),
    483626            'discount_total' => (float) $cart->get_discount_total(),
    484627            'currency' => (string) get_woocommerce_currency(),
    485            
     628
    486629            // Cart Contents
    487630            'items_count' => (int) $cart->get_cart_contents_count(),
     
    489632            'items' => $items,
    490633            'weight_total' => (float) $cart->get_cart_contents_weight(),
    491            
     634
    492635            // Applied Discounts
    493636            'coupons' => array_map('strval', $cart->get_applied_coupons()),
    494637            'coupon_discount' => (float) $cart->get_discount_total(),
    495638            'tax_discount' => (float) $cart->get_discount_tax(),
    496            
     639
    497640            // Shipping Information
    498641            'needs_shipping' => (bool) $cart->needs_shipping(),
     
    508651            'shipping_country_code' => (string) $shipping_country_code,
    509652            'shipping_country_name' => (string) ($shipping_country_code ? $wc_countries->countries[$shipping_country_code] : ''),
     653            'payment_methods' => array_keys(WC()->payment_gateways->get_available_payment_gateways()),
    510654           
    511655            // Additional Context
    512656            'device_type' => (string) (wp_is_mobile() ? 'mobile' : 'desktop'),
    513657            'referrer' => (string) (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''),
    514             'timestamp' => current_time('mysql'),
     658            'timestamp' => (string) current_time('mysql'),
    515659            'checkout_page' => (string) (is_checkout() ? 'standard' : 'custom'),
    516660            'user_agent' => (string) (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''),
    517             'cart_hash' => (string) WC()->cart->get_cart_hash()
    518         );
    519        
     661        );
     662
     663        // Send the event
    520664        $this->send_event('initiated_checkout', $event_attributes);
    521        
    522         // Set the session variable to prevent duplicate tracking
    523         WC()->session->set('usermaven_initiate_checkout_tracked', true);
     665
     666        // Update tracking state
     667        WC()->session->set('usermaven_tracked_cart_hash', $cart_hash);
     668        WC()->session->set('usermaven_last_checkout_track_time', time());
     669    }
     670
     671    /**
     672     * Reset tracking state when cart is updated
     673     */
     674    public function reset_checkout_tracking() {
     675        WC()->session->set('usermaven_tracked_cart_hash', null);
     676        WC()->session->set('usermaven_last_checkout_track_time', null);
    524677    }
    525678
     
    8691022
    8701023    /**
    871      * Track order submission with full details
    872      *
    873      * @param int $order_id The WooCommerce order ID
    874      * @param array $posted_data Posted checkout form data
    875      * @param WC_Order $order The WooCommerce order object
    876      */
    877     public function track_order_submission($order_id, $posted_data, $order) {
    878         if (!$order_id || !$order) {
    879             return;
    880         }
    881 
     1024     * Early tracking for order submission to catch all checkout types
     1025     */
     1026    public function track_order_submission($order_id) {
     1027        error_log('track_order_submission early triggered for order: ' . $order_id);
     1028
     1029        WC()->session->set('usermaven_initiate_checkout_tracked', null);
     1030
     1031        if (!$order_id) {
     1032            return;
     1033        }
     1034
     1035        $order = wc_get_order($order_id);
     1036        if (!$order) {
     1037            return;
     1038        }
     1039
     1040        // Check if this order has already been tracked
     1041        $tracked = get_post_meta($order_id, '_usermaven_order_tracked', true);
     1042        if ($tracked) {
     1043            return;
     1044        }
     1045
     1046        // Reset checkout tracking
     1047        $this->reset_checkout_tracking();
     1048
     1049        // Rest of your tracking code
    8821050        $location_details = $this->get_location_details($order);
    8831051        $items = $this->get_formatted_order_items($order);
    8841052
    885         // Get common attributes
     1053        // event attributes
    8861054        $event_attributes = array_merge(
    8871055            $this->get_common_order_attributes($order, $location_details),
     
    9061074
    9071075        $this->send_event('order_submitted', $event_attributes);
     1076
     1077        // Mark this order as tracked
     1078        update_post_meta($order_id, '_usermaven_order_tracked', true);
    9081079    }
    9091080   
     
    15741745            WC()->session->set('landing_page', $_SERVER['REQUEST_URI']);
    15751746        }
    1576    
     1747
    15771748        // Do NOT update last_activity on every page load — only when user interacts with the cart or starts checkout.
    15781749        // This prevents continuous resets that block abandonment detection.
  • usermaven/tags/1.1.3/includes/class-usermaven.php

    r3221608 r3240206  
    8181            $this->version = USERMAVEN_VERSION;
    8282        } else {
    83             $this->version = '1.1.1';
     83            $this->version = '1.1.3';
    8484        }
    8585        $this->plugin_name = 'usermaven';
  • usermaven/tags/1.1.3/usermaven.php

    r3221608 r3240206  
    1919 * Description:       The Easiest Website and Product Analytics Platform
    2020
    21  * Version:           1.1.1
     21 * Version:           1.1.3
    2222 * Author:            Usermaven
    2323 * Author URI:        https://usermaven.com/
     
    3838 * Rename this for your plugin and update it as you release new versions.
    3939 */
    40 define( 'USERMAVEN_VERSION', '1.1.1' );
     40define( 'USERMAVEN_VERSION', '1.1.3' );
    4141
    4242/**
  • usermaven/trunk/README.txt

    r3221608 r3240206  
    66Tested up to: 6.7.1
    77Requires PHP: 5.6
    8 Stable tag: 1.1.1
     8Stable tag: 1.1.3
    99License: Massachusetts Institute of Technology (MIT) license
    1010License URI: https://opensource.org/licenses/MIT
  • usermaven/trunk/includes/class-usermaven-api.php

    r3217559 r3240206  
    99        $this->api_key = get_option('usermaven_api_key');
    1010        $this->api_url = "$tracking_host/api/v1/s2s/event";
     11    }
     12
     13    public function identify($user_data, $company_data = []) {
     14        $url = $this->api_url . "?token=$this->api_key.$this->server_token";
     15       
     16        // Get current timestamp in milliseconds
     17        $current_timestamp_ms = round(microtime(true) * 1000);
     18        $doc_encoding = get_bloginfo('charset');
     19
     20        $data = [
     21            'api_key' => $this->api_key,
     22            'event_type' => 'user_identify',
     23            '_timestamp' => (string)$current_timestamp_ms,
     24            'user' => $user_data,
     25            'company' => [
     26                'id' => $company_data['id'] ?? '',
     27                'name' => $company_data['name'] ?? '',
     28            ],
     29            'src' => 'http',
     30            'url' => $_SERVER['HTTP_REFERER'] ?? '',
     31            'page_title' => wp_get_document_title(),
     32            'doc_path' => $_SERVER['REQUEST_URI'] ?? '',
     33            'doc_host' => $_SERVER['HTTP_HOST'] ?? '',
     34            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
     35            'user_language' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '',
     36            'doc_encoding' => (string) $doc_encoding,
     37        ];
     38
     39        $response = wp_remote_post($url, [
     40            'body' => json_encode($data),
     41            'headers' => ['Content-Type' => 'application/json']
     42        ]);
     43
     44        if (is_wp_error($response)) {
     45            error_log('Usermaven API Error: ' . $response->get_error_message());
     46            return false;
     47        }
     48
     49        $body = wp_remote_retrieve_body($response);
     50        $result = json_decode($body, true);
     51        return $result['status'] === 'ok';
    1152    }
    1253
  • usermaven/trunk/includes/class-usermaven-woocommerce.php

    r3221608 r3240206  
    3131     */
    3232    private function init_hooks() {
     33        // Track on WooCommerce specific login
     34        add_action('woocommerce_login_credentials', array($this, 'identify_wc_user'), 10, 2);
     35   
    3336        // Product Viewing
    3437        add_action('template_redirect', array($this, 'track_product_view'));
    35 
     38   
    3639        // Cart Actions
    3740        add_action('woocommerce_add_to_cart', array($this, 'track_add_to_cart'), 10, 6);
    3841        add_action('woocommerce_cart_item_removed', array($this, 'track_remove_from_cart'), 10, 2);
    3942        add_action('woocommerce_after_cart_item_quantity_update', array($this, 'track_cart_update'), 10, 4);
    40 
    41         // Checkout Process
    42         add_action('woocommerce_before_checkout_form', array($this, 'track_initiate_checkout'), 10);
    43         add_action('woocommerce_checkout_order_processed', array($this, 'track_order_submission'), 10, 3);
    44        
     43   
     44        // Checkout Process - Consolidated tracking
     45        // add_action('woocommerce_before_checkout_form', array($this, 'track_initiate_checkout'), 10); // Removed this because it was not triggering for custom checkout pages
     46        add_action('wp', array($this, 'maybe_track_checkout_init'));
     47        // add_action('woocommerce_checkout_order_processed', array($this, 'track_order_submission'), 10, 3); // Removed this because it was not triggering for custom checkout pages
     48        add_action('woocommerce_new_order', array($this, 'track_order_submission'), 10, 1);
     49   
    4550        // Order Status and Completion
    4651        // add_action('woocommerce_payment_complete', array($this, 'track_order_completed'));
     
    5459        add_action('woocommerce_order_status_refunded', array($this, 'track_order_refunded'), 10, 2);
    5560        add_action('woocommerce_order_status_draft', array($this, 'track_order_draft'), 10, 1);
    56 
     61   
    5762        // Track customer creation
    5863        add_action('woocommerce_created_customer', array($this, 'track_customer_created'), 10, 3);
    59 
    60         // Reset the tracking flag when the cart is updated or order completes/fails
    61         add_action('woocommerce_cart_updated', array($this, 'reset_initiate_checkout_tracking'));
    62         add_action('woocommerce_thankyou', array($this, 'track_order_thankyou'), 10);
     64   
     65        // Reset tracking state for cart updates
     66        add_action('woocommerce_cart_updated', array($this, 'reset_checkout_tracking'));
     67        add_action('woocommerce_cart_emptied', array($this, 'reset_checkout_tracking'));
     68        add_action('woocommerce_after_cart_item_quantity_update', array($this, 'reset_checkout_tracking'));
     69       
     70        // Reset tracking for order completion/failure
    6371        add_action('woocommerce_order_status_completed', array($this, 'reset_initiate_checkout_tracking'));
    6472        add_action('woocommerce_order_status_failed', array($this, 'reset_initiate_checkout_tracking'));
    65 
    66 
     73       
     74        // Track order thank you page
     75        add_action('woocommerce_thankyou', array($this, 'track_order_thankyou'), 10);
     76   
    6777        // Initialize cart abandonment tracking
    6878        add_action('woocommerce_init', function() {
    6979            $this->init_cart_abandonment_tracking();
    7080        });
    71 
     81   
    7282        // Add session cleanup on successful order
    7383        add_action('woocommerce_checkout_order_processed', function() {
     
    7686            WC()->session->set('last_activity', null);
    7787        });
    78 
     88   
    7989        // Wishlist Integration (if using WooCommerce Wishlist)
    8090        if (class_exists('YITH_WCWL')) {
     
    8494        }
    8595    }
     96
     97    /**
     98     * Identify user on WooCommerce login
     99     */
     100    public function identify_wc_user($credentials) {
     101        if (!empty($credentials['user_login'])) {
     102            $user = get_user_by('login', $credentials['user_login']);
     103            if ($user) {
     104                $this->send_user_identify_request($user);
     105            }
     106        }
     107        return $credentials;
     108    }
     109
     110    /**
     111     * Send identify call to Usermaven API
     112     *
     113     * @param WP_User $user User object
     114     */
     115    private function send_user_identify_request($user) {
     116        if (!$user) {
     117            return;
     118        }
     119
     120        // Get WooCommerce customer
     121        $customer = new WC_Customer($user->ID);
     122       
     123        // Get custom user data
     124        $roles = $user->roles;
     125        $primary_role = !empty($roles) ? $roles[0] : '';
     126
     127        // Get the anonymous_id from cookie if available
     128        $eventn_cookie_name = '__eventn_id_' . $this->api_key;
     129        $usermaven_cookie_name = 'usermaven_id_' . $this->api_key;
     130        $anonymous_id = '';
     131
     132        if (isset($_COOKIE[$eventn_cookie_name])) {
     133            $anonymous_id = $_COOKIE[$eventn_cookie_name];
     134        } elseif (isset($_COOKIE[$usermaven_cookie_name])) {
     135            $anonymous_id = $_COOKIE[$usermaven_cookie_name];
     136        }
     137
     138        $user_id = $user->ID;
     139        $user_email = $user->user_email;
     140
     141        // if user id is null use email as user id
     142        if (empty($user_id)) {
     143            $user_id = $user_email;
     144        }
     145
     146        // Prepare user data
     147        $user_data = array(
     148            'anonymous_id' => $anonymous_id,
     149            'id' => (string) $user_id,
     150            'email' => (string) $user_email,
     151            'created_at' => date('Y-m-d\TH:i:s', strtotime($user->user_registered)),
     152            'first_name' => $user->first_name,
     153            'last_name' => $user->last_name,
     154            'custom' => array(
     155                'role' => $primary_role,
     156                'username' => $user->user_login,
     157                'display_name' => $user->display_name,
     158                'billing_country' => $customer->get_billing_country(),
     159                'shipping_country' => $customer->get_shipping_country(),
     160                'is_paying_customer' => (bool) $customer->get_is_paying_customer()
     161            )
     162        );
     163
     164        // Prepare company data if available
     165        $company_data = array();
     166        $company_name = $customer->get_billing_company();
     167        if (!empty($company_name)) {
     168            $company_data = array(
     169                'id' => 'wc_' . md5($company_name . $customer->get_billing_email()),
     170                'name' => $company_name,
     171                'created_at' => date('Y-m-d\TH:i:s', strtotime($user->user_registered)),
     172                'custom' => array(
     173                    'billing_country' => $customer->get_billing_country(),
     174                    'billing_city' => $customer->get_billing_city(),
     175                    'billing_postcode' => $customer->get_billing_postcode()
     176                )
     177            );
     178        }
     179
     180        // Send identify request using the API
     181        $this->api->identify($user_data, $company_data);
     182    }
     183
    86184
    87185    /**
     
    407505
    408506    /**
    409      * Track checkout initiation
    410      */
    411     public function track_initiate_checkout() {
     507     * Single entry point for tracking checkout initialization
     508     * This ensures we don't have multiple competing triggers
     509     */
     510    public function maybe_track_checkout_init() {
     511        // Early exit conditions
    412512        if (WC()->cart->is_empty()) {
    413513            return;
    414514        }
    415    
     515
     516        // Get a unique identifier for current cart state
     517        $cart_hash = WC()->cart->get_cart_hash();
     518       
     519        // Get stored tracking data
     520        $tracked_cart_hash = WC()->session->get('usermaven_tracked_cart_hash');
     521        $last_tracked_time = WC()->session->get('usermaven_last_checkout_track_time');
     522        $current_time = time();
     523
     524        // Check if this specific cart state has been tracked recently
     525        if ($tracked_cart_hash === $cart_hash &&
     526            $last_tracked_time &&
     527            ($current_time - $last_tracked_time) < 300) { // 5 minutes threshold
     528            return;
     529        }
     530
     531        if (is_cart()) {
     532            return;
     533        }
     534
     535        // Check if we're actually on a checkout page/process
     536        $is_checkout_context = (
     537            // Only track on actual checkout page, not cart page
     538            (function_exists('is_checkout') && is_checkout()) ||
     539            // For custom checkout pages
     540            (has_shortcode(get_post()->post_content ?? '', 'woocommerce_checkout')) ||
     541            // For AJAX checkout requests
     542            (isset($_REQUEST['wc-ajax']) && $_REQUEST['wc-ajax'] === 'checkout')
     543        );
     544
     545        if (!$is_checkout_context) {
     546            return;
     547        }
     548
     549        $this->track_initiate_checkout($cart_hash);
     550        WC()->session->set('usermaven_initiate_checkout_tracked', true);
     551    }
     552
     553    /**
     554     * Track checkout initiation with duplicate prevention
     555     */
     556    private function track_initiate_checkout($cart_hash) {
    416557        // Prevent duplicate tracking
    417558        if (WC()->session->get('usermaven_initiate_checkout_tracked')) {
    418559            return;
    419560        }
    420    
     561
    421562        $cart = WC()->cart;
    422563        $items = array();
    423    
     564
    424565        // Get WC Countries object for location handling
    425566        $wc_countries = new WC_Countries();
     
    430571                continue;
    431572            }
    432    
     573
    433574            // Get the parent product if this is a variation
    434575            $parent_product = $product;
     
    436577                $parent_product = wc_get_product($product->get_parent_id());
    437578            }
    438    
     579
    439580            // Get product categories from parent product
    440581            $categories = array();
     
    443584                $categories = wp_list_pluck($terms, 'name');
    444585            }
    445    
     586
    446587            // Process variation attributes - keeping attribute_ prefix
    447588            $variation_attributes = array();
     
    451592                }
    452593            }
    453    
     594
    454595            // Get and validate prices
    455596            $unit_price = $product->get_price();
    456597            $unit_price = $unit_price === '' ? 0.0 : (float) $unit_price;
    457    
     598
    458599            $items[] = array(
    459600                'product_id' => (int) $parent_product->get_id(),
     
    465606                'line_tax' => (float) $cart_item['line_tax'],
    466607                'categories' => array_map('strval', $categories),
    467                 'variation_id' => !empty($cart_item['variation_id']) ? (int) $cart_item['variation_id'] : null,
     608                'variation_id' => isset($cart_item['variation_id']) ? (int) $cart_item['variation_id'] : null,
    468609                'variation_attributes' => $variation_attributes,
    469610                'is_on_sale' => (bool) $product->is_on_sale(),
     
    471612            );
    472613        }
    473    
     614           
    474615        $billing_country_code = WC()->customer->get_billing_country();
    475616        $shipping_country_code = WC()->customer->get_shipping_country();
    476    
     617
    477618        $event_attributes = array(
    478619            // Cart Financial Details
     620            'cart_hash' => $cart_hash,
    479621            'total' => (float) $cart->get_total('numeric'),
    480622            'subtotal' => (float) $cart->get_subtotal(),
     623            'cart_tax' => (float) $cart->get_cart_tax(),
    481624            'tax' => (float) $cart->get_total_tax(),
    482625            'shipping_total' => (float) $cart->get_shipping_total(),
    483626            'discount_total' => (float) $cart->get_discount_total(),
    484627            'currency' => (string) get_woocommerce_currency(),
    485            
     628
    486629            // Cart Contents
    487630            'items_count' => (int) $cart->get_cart_contents_count(),
     
    489632            'items' => $items,
    490633            'weight_total' => (float) $cart->get_cart_contents_weight(),
    491            
     634
    492635            // Applied Discounts
    493636            'coupons' => array_map('strval', $cart->get_applied_coupons()),
    494637            'coupon_discount' => (float) $cart->get_discount_total(),
    495638            'tax_discount' => (float) $cart->get_discount_tax(),
    496            
     639
    497640            // Shipping Information
    498641            'needs_shipping' => (bool) $cart->needs_shipping(),
     
    508651            'shipping_country_code' => (string) $shipping_country_code,
    509652            'shipping_country_name' => (string) ($shipping_country_code ? $wc_countries->countries[$shipping_country_code] : ''),
     653            'payment_methods' => array_keys(WC()->payment_gateways->get_available_payment_gateways()),
    510654           
    511655            // Additional Context
    512656            'device_type' => (string) (wp_is_mobile() ? 'mobile' : 'desktop'),
    513657            'referrer' => (string) (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''),
    514             'timestamp' => current_time('mysql'),
     658            'timestamp' => (string) current_time('mysql'),
    515659            'checkout_page' => (string) (is_checkout() ? 'standard' : 'custom'),
    516660            'user_agent' => (string) (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''),
    517             'cart_hash' => (string) WC()->cart->get_cart_hash()
    518         );
    519        
     661        );
     662
     663        // Send the event
    520664        $this->send_event('initiated_checkout', $event_attributes);
    521        
    522         // Set the session variable to prevent duplicate tracking
    523         WC()->session->set('usermaven_initiate_checkout_tracked', true);
     665
     666        // Update tracking state
     667        WC()->session->set('usermaven_tracked_cart_hash', $cart_hash);
     668        WC()->session->set('usermaven_last_checkout_track_time', time());
     669    }
     670
     671    /**
     672     * Reset tracking state when cart is updated
     673     */
     674    public function reset_checkout_tracking() {
     675        WC()->session->set('usermaven_tracked_cart_hash', null);
     676        WC()->session->set('usermaven_last_checkout_track_time', null);
    524677    }
    525678
     
    8691022
    8701023    /**
    871      * Track order submission with full details
    872      *
    873      * @param int $order_id The WooCommerce order ID
    874      * @param array $posted_data Posted checkout form data
    875      * @param WC_Order $order The WooCommerce order object
    876      */
    877     public function track_order_submission($order_id, $posted_data, $order) {
    878         if (!$order_id || !$order) {
    879             return;
    880         }
    881 
     1024     * Early tracking for order submission to catch all checkout types
     1025     */
     1026    public function track_order_submission($order_id) {
     1027        error_log('track_order_submission early triggered for order: ' . $order_id);
     1028
     1029        WC()->session->set('usermaven_initiate_checkout_tracked', null);
     1030
     1031        if (!$order_id) {
     1032            return;
     1033        }
     1034
     1035        $order = wc_get_order($order_id);
     1036        if (!$order) {
     1037            return;
     1038        }
     1039
     1040        // Check if this order has already been tracked
     1041        $tracked = get_post_meta($order_id, '_usermaven_order_tracked', true);
     1042        if ($tracked) {
     1043            return;
     1044        }
     1045
     1046        // Reset checkout tracking
     1047        $this->reset_checkout_tracking();
     1048
     1049        // Rest of your tracking code
    8821050        $location_details = $this->get_location_details($order);
    8831051        $items = $this->get_formatted_order_items($order);
    8841052
    885         // Get common attributes
     1053        // event attributes
    8861054        $event_attributes = array_merge(
    8871055            $this->get_common_order_attributes($order, $location_details),
     
    9061074
    9071075        $this->send_event('order_submitted', $event_attributes);
     1076
     1077        // Mark this order as tracked
     1078        update_post_meta($order_id, '_usermaven_order_tracked', true);
    9081079    }
    9091080   
     
    15741745            WC()->session->set('landing_page', $_SERVER['REQUEST_URI']);
    15751746        }
    1576    
     1747
    15771748        // Do NOT update last_activity on every page load — only when user interacts with the cart or starts checkout.
    15781749        // This prevents continuous resets that block abandonment detection.
  • usermaven/trunk/includes/class-usermaven.php

    r3221608 r3240206  
    8181            $this->version = USERMAVEN_VERSION;
    8282        } else {
    83             $this->version = '1.1.1';
     83            $this->version = '1.1.3';
    8484        }
    8585        $this->plugin_name = 'usermaven';
  • usermaven/trunk/usermaven.php

    r3221608 r3240206  
    1919 * Description:       The Easiest Website and Product Analytics Platform
    2020
    21  * Version:           1.1.1
     21 * Version:           1.1.3
    2222 * Author:            Usermaven
    2323 * Author URI:        https://usermaven.com/
     
    3838 * Rename this for your plugin and update it as you release new versions.
    3939 */
    40 define( 'USERMAVEN_VERSION', '1.1.1' );
     40define( 'USERMAVEN_VERSION', '1.1.3' );
    4141
    4242/**
Note: See TracChangeset for help on using the changeset viewer.