eventRepository = $eventRepository; } public function trackProductView($product_id) { if (!$product_id) { return; } $session_key = 'sodino_viewed_' . intval($product_id); if ($this->hasLogged($session_key)) { return; } $this->logEvent('product_view', [ 'product_id' => $product_id, ]); $this->markLogged($session_key); } public function trackAddToCart($product_id, $variation_id = null, $quantity = 1) { if (!$product_id) { return; } $this->logEvent('add_to_cart', [ 'product_id' => $product_id, 'variation_id' => $variation_id, 'value' => floatval($quantity), ]); } public function trackCheckoutStart() { $this->logEvent('checkout_start', []); } public function trackPurchase($order_id) { if (!$order_id) { return; } $order = wc_get_order($order_id); if (!$order) { return; } $total = floatval($order->get_total()); $discount = 0; if (method_exists($order, 'get_total_discount')) { $discount = floatval($order->get_total_discount()); } else { foreach ($order->get_items() as $item) { $discount += floatval($item->get_subtotal()) - floatval($item->get_total()); } } $this->logEvent('purchase', [ 'value' => $total, 'discount_value' => max(0, $discount), ]); } public function recordDiscountApplied($product, $original_price, $discounted_price, $rule_id = null) { if (!$product || $original_price <= 0 || $discounted_price >= $original_price) { return; } $product_id = $product->get_id(); $variation_id = $product->is_type('variation') ? $product_id : 0; $discount_value = round($original_price - $discounted_price, 2); $key = 'discount_applied_' . $product_id . '_' . $rule_id . '_' . $discount_value; if ($this->hasLogged($key)) { return; } $this->logEvent('discount_applied', [ 'product_id' => $product_id, 'variation_id' => $variation_id, 'rule_id' => $rule_id, 'value' => $discounted_price, 'discount_value' => $discount_value, ]); $this->markLogged($key); } public function getRuleUsageCount($rule_id) { return $this->eventRepository->getRuleUsageCount($rule_id); } private function logEvent($type, array $data = []) { $event = [ 'event_type' => $type, 'product_id' => isset($data['product_id']) ? intval($data['product_id']) : null, 'variation_id' => isset($data['variation_id']) ? intval($data['variation_id']) : null, 'user_id' => get_current_user_id() ?: null, 'session_id' => $this->getSessionId(), 'rule_id' => isset($data['rule_id']) ? intval($data['rule_id']) : null, 'value' => isset($data['value']) ? floatval($data['value']) : 0, 'discount_value' => isset($data['discount_value']) ? floatval($data['discount_value']) : 0, 'metadata' => isset($data['metadata']) ? wp_json_encode($data['metadata']) : null, 'created_at' => current_time('mysql'), ]; $this->eventRepository->insert($event); } private function getSessionId() { if (function_exists('WC') && WC()->session) { $session_id = WC()->session->get('sodino_session_id'); if (!$session_id) { $session_id = uniqid('sodino_', true); WC()->session->set('sodino_session_id', $session_id); } return $session_id; } return 'guest_' . md5($_SERVER['REMOTE_ADDR'] . '|' . $_SERVER['HTTP_USER_AGENT']); } private function hasLogged($key) { return isset($this->loggedEvents[$key]); } private function markLogged($key) { $this->loggedEvents[$key] = true; } }