PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 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 All 508 releases
← All changes | jetpack_vendor/automattic/woocommerce-analytics/src/API/class-wc-analytics-tracking-proxy.php +167 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,167 @@
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 +}