PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / woocommerce-analytics / src / API / class-wc-analytics-tracking-proxy.php

class-wc-analytics-tracking-proxy.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.7, at jetpack_vendor/automattic/woocommerce-analytics/src/API/class-wc-analytics-tracking-proxy.php

168 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST API: WC_Analytics_Tracking_Proxy class
4 *
5 * @package automattic/woocommerce-analytics
6 */
7
8 namespace Automattic\Woocommerce_Analytics;
9
10 defined( 'ABSPATH' ) || exit;
11
12 /**
13 * Class to handle tracking events via the REST API
14 *
15 * @since 0.7.0
16 */
17 class WC_Analytics_Tracking_Proxy extends \WC_REST_Controller {
18
19 /**
20 * Endpoint namespace.
21 *
22 * @var string
23 */
24 protected $namespace = 'woocommerce-analytics/v1';
25
26 /**
27 * Route base.
28 *
29 * @var string
30 */
31 protected $rest_base = 'track';
32
33 /**
34 * Register the routes for tracking.
35 */
36 public function register_routes() {
37 register_rest_route(
38 $this->namespace,
39 '/' . $this->rest_base,
40 array(
41 array(
42 'methods' => \WP_REST_Server::CREATABLE,
43 'callback' => array( $this, 'track_events' ),
44 // Unauthenticated front-end event endpoint. track_events() validates consent
45 // and records events without client-supplied server-owned properties.
46 'permission_callback' => '__return_true',
47 'schema' => array( $this, 'get_public_item_schema' ),
48 ),
49 )
50 );
51 }
52
53 /**
54 * Track events.
55 *
56 * @param \WP_REST_Request $request Full data about the request.
57 * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
58 */
59 public function track_events( $request ) {
60 // Cached pages can still post here after proxy tracking is disabled; return a
61 // visible error instead of losing the event to a 404.
62 if ( ! Features::is_proxy_tracking_enabled() ) {
63 return new \WP_Error(
64 'proxy_tracking_disabled',
65 'Proxy tracking is not enabled on this site.',
66 array( 'status' => 403 )
67 );
68 }
69
70 // Check consent before processing any events
71 if ( ! Consent_Manager::has_analytics_consent() ) {
72 return new \WP_REST_Response(
73 array(
74 'success' => true,
75 'message' => 'Events skipped due to lack of analytics consent',
76 'results' => array(),
77 ),
78 200
79 );
80 }
81
82 $events = $request->get_json_params();
83
84 if ( ! is_array( $events ) || ( isset( $events['event_name'] ) ) ) {
85 // If $events is a single event (associative array), wrap it in an array.
86 $events = array( $events );
87 }
88
89 // Limit unauthenticated callers to a bounded number of pixel requests.
90 if ( count( $events ) > WC_Analytics_Tracking::MAX_CLIENT_EVENTS_PER_REQUEST ) {
91 $events = array_slice( $events, 0, WC_Analytics_Tracking::MAX_CLIENT_EVENTS_PER_REQUEST, true );
92 }
93
94 $results = array();
95 $has_errors = false;
96
97 foreach ( $events as $index => $event ) {
98 // Validate event structure.
99 if ( empty( $event ) || ! is_array( $event ) ) {
100 $results[ $index ] = array(
101 'success' => false,
102 'error' => 'Invalid event format',
103 );
104 $has_errors = true;
105 continue;
106 }
107
108 // Validate event name and properties.
109 $event_name = $event['event_name'] ?? null;
110 $properties = $event['properties'] ?? array();
111 if ( ! $event_name || ! is_string( $event_name ) || ! is_array( $properties ) ) {
112 $results[ $index ] = array(
113 'success' => false,
114 'error' => 'Missing event_name or invalid properties',
115 );
116 $has_errors = true;
117 continue;
118 }
119
120 $result = WC_Analytics_Tracking::record_client_event( $event_name, $properties );
121
122 if ( is_wp_error( $result ) ) {
123 $results[ $index ] = array(
124 'success' => false,
125 'error' => $result->get_error_message(),
126 );
127 $has_errors = true;
128 continue;
129 }
130
131 $results[ $index ] = array( 'success' => true );
132 }
133
134 $response_data = array(
135 'success' => ! $has_errors,
136 'results' => $results,
137 );
138
139 return new \WP_REST_Response( $response_data, $has_errors ? 207 : 200 );
140 }
141
142 /**
143 * Get the schema for tracking events.
144 *
145 * @return array
146 */
147 public function get_item_schema() {
148 $schema = array(
149 '$schema' => 'http://json-schema.org/draft-04/schema#',
150 'title' => 'tracking_events',
151 'type' => 'array',
152 'items' => array(
153 'type' => 'object',
154 'properties' => array(
155 'event_name' => array(
156 'type' => 'string',
157 ),
158 'properties' => array(
159 'type' => 'object',
160 ),
161 ),
162 ),
163 );
164
165 return $this->add_additional_fields_schema( $schema );
166 }
167 }
168