get( 'analytics_enable_click_tracking', true ) ) ) { return; } if ( get_option( 'accessiq_analytics_exclude_logged_in', $s->get( 'analytics_exclude_logged_in', false ) ) && is_user_logged_in() ) { return; } wp_enqueue_script( 'accessiq-tracker', ACCESSIQ_URL . 'public/js/tracker.js', array(), ACCESSIQ_VERSION, true ); $page_url = get_permalink(); if ( ! $page_url ) { $page_url = home_url( isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ); } wp_localize_script( 'accessiq-tracker', 'accessiqTracker', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => accessiq_tracking_token(), 'page_url' => (string) $page_url, 'enabled' => true, ) ); } /** * Handle click tracking AJAX request. */ public function handle_track_click() { if ( ! accessiq_verify_tracking_request() ) { wp_send_json_error( 'Invalid nonce' ); } if ( accessiq_is_bot_request() || accessiq_tracking_rate_limited() ) { wp_send_json_error( 'Throttled' ); } global $wpdb; $page_url = isset( $_POST['page_url'] ) ? esc_url_raw( wp_unslash( $_POST['page_url'] ) ) : ''; $x_percent = isset( $_POST['x_percent'] ) ? floatval( wp_unslash( $_POST['x_percent'] ) ) : 0; $y_percent = isset( $_POST['y_percent'] ) ? floatval( wp_unslash( $_POST['y_percent'] ) ) : 0; $element = isset( $_POST['element'] ) ? sanitize_text_field( wp_unslash( $_POST['element'] ) ) : ''; // Selector charset only (tag.class#id[attr]) — blocks quote/attribute-breakout payloads. $element = substr( preg_replace( '/[^A-Za-z0-9_\-.#:\[\]=>+~ ]/', '', $element ), 0, 150 ); $device_type = isset( $_POST['device_type'] ) ? sanitize_key( wp_unslash( $_POST['device_type'] ) ) : 'desktop'; if ( ! in_array( $device_type, array( 'desktop', 'tablet', 'mobile' ), true ) ) { $device_type = 'desktop'; } $session_id = isset( $_POST['session_id'] ) ? accessiq_clean_session_id( $_POST['session_id'] ) : ''; if ( empty( $page_url ) ) { wp_send_json_error( 'Missing data' ); } if ( $x_percent < 0 || $x_percent > 100 || $y_percent < 0 || $y_percent > 100 ) { wp_send_json_error( 'Invalid coordinates' ); } if ( strpos( $page_url, '/wp-' ) !== false ) { wp_send_json_error( 'Internal URL ignored' ); } $table_name = $wpdb->prefix . 'accessiq_clicks'; $inserted = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $table_name, array( 'page_url' => $page_url, 'x_percent' => $x_percent, 'y_percent' => $y_percent, 'element' => $element, 'device_type' => $device_type, 'session_id' => $session_id, 'created_at' => current_time( 'mysql' ), ), array( '%s', '%f', '%f', '%s', '%s', '%s', '%s' ) ); if ( $inserted ) { wp_send_json_success( 'Click logged' ); } else { wp_send_json_error( 'Failed to log click' ); } } }