PluginProbe ʕ •ᴥ•ʔ
Microsoft Clarity / 0.10.10
Microsoft Clarity v0.10.10
0.10.26 0.10.25 0.10.24 0.8.0 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 trunk 0.10.0 0.10.1 0.10.10 0.10.11 0.10.12 0.10.13 0.10.14 0.10.15 0.10.16 0.10.17 0.10.18 0.10.19 0.10.2 0.10.20 0.10.21 0.10.22 0.10.23 0.10.3 0.10.4 0.10.5 0.10.6 0.10.7 0.10.8 0.10.9 0.2 0.4 0.5 0.6 0.6.1 0.7 0.7.1 0.7.2 0.7.3 0.7.4 0.7.5
microsoft-clarity / clarity-server-analytics.php
microsoft-clarity Last commit date
js 2 years ago LICENSE.txt 5 years ago clarity-hooks.php 1 year ago clarity-page.php 6 months ago clarity-server-analytics.php 7 months ago clarity.php 6 months ago index.php 5 years ago readme.txt 6 months ago
clarity-server-analytics.php
167 lines
1 <?php
2
3 //
4 // Configurations & Constants
5 //
6
7 const CLARITY_COLLECT_ENDPOINT = 'https://ai.clarity.ms/collect';
8 const CLARITY_COLLECT_PLUGIN_VERSION = 'WordPress-0.10.9';
9
10 const CLARITY_COLLECT_BATCH_KEY = 'clarity_collect_batch';
11 const CLARITY_COLLECT_BATCH_SIZE = 50;
12
13 /**
14 * Collects and sends Clarity events in batches.
15 */
16 function clarity_collect_event() {
17 try {
18 if (is_admin()) {
19 return;
20 }
21
22 $clarity_project_id = get_option('clarity_project_id');
23 $clarity_wp_site = get_option('clarity_wordpress_site_id');
24
25 // Ensure required identifiers are present
26 if (empty($clarity_project_id) || empty($clarity_wp_site)) {
27 return;
28 }
29
30 // Prevent multiple event to be sent in the same session
31 if (!empty($_SESSION['clarity_event_processed'])) {
32 return;
33 }
34
35 // Mark the session as processed
36 $_SESSION['clarity_event_processed'] = true;
37
38 // Construct and buffer the collect event payload for batch sending
39 $event = clarity_construct_collect_event($clarity_project_id);
40 clarity_buffer_collect_event($event);
41 }
42 catch (Exception $e) {
43 // Silently fail on any error
44 }
45 }
46
47 add_action('init', 'clarity_collect_event');
48
49 /**
50 * Buffers a collect event payload for batch sending.
51 *
52 * @param array $event The event payload to buffer.
53 */
54 function clarity_buffer_collect_event($event) {
55 global $wpdb;
56
57 if (!$wpdb->ready) {
58 return;
59 }
60
61 $batch = array();
62 $shouldSendBatch = false;
63
64 try {
65 // Lock to prevent race conditions
66 $wpdb->query('START TRANSACTION');
67
68 // Fetch existing event batch
69 $batch = get_option(CLARITY_COLLECT_BATCH_KEY, array());
70
71 // Append the new payload to the batch
72 $batch[] = $event;
73
74 // If the batch size reached the maximum or the elapsed time exceeded the limit,
75 // clear it from the database and send it after releasing the lock
76 if (count($batch) >= CLARITY_COLLECT_BATCH_SIZE) {
77 update_option(CLARITY_COLLECT_BATCH_KEY, array(), false);
78 $shouldSendBatch = true;
79 }
80 // Otherwise, write the updated batch
81 else {
82 update_option(CLARITY_COLLECT_BATCH_KEY, $batch, false);
83 }
84 }
85 finally {
86 // Release the lock
87 $wpdb->query('COMMIT');
88 }
89
90 // Send the batch if needed
91 if ($shouldSendBatch) {
92 clarity_send_collect_event_batch($batch);
93 }
94 }
95
96 //
97 // Helper Functions
98 //
99
100 /**
101 * Constructs the event payload for the collect endpoint.
102 *
103 * @param string $clarity_project_id The Clarity project ID.
104 * @return array The constructed event payload.
105 */
106 function clarity_construct_collect_event($clarity_project_id) {
107 $envelope = array(
108 'projectId' => $clarity_project_id,
109 'sessionId' => wp_get_session_token(),
110 'version' => CLARITY_COLLECT_PLUGIN_VERSION,
111 );
112
113 $analytics = array(
114 'time' => time(),
115 'ip' => clarity_get_ip_address(),
116 'ua' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field($_SERVER['HTTP_USER_AGENT']) : 'Unknown',
117 'url' => home_url($_SERVER['REQUEST_URI']),
118 'method' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'Unknown',
119 );
120
121 $payload = array(
122 'envelope' => $envelope,
123 'analytics' => $analytics,
124 );
125
126 return $payload;
127 }
128
129 /**
130 * Sends a batch of events to the Clarity collect endpoint.
131 *
132 * @param array $events The batch of events to send.
133 */
134 function clarity_send_collect_event_batch($events) {
135 $request = array(
136 'body' => json_encode($events),
137 'headers' => array('Content-Type' => 'application/json'),
138 'blocking' => false,
139 'timeout' => '1',
140 'redirection' => '5',
141 'httpversion' => '1.0'
142 );
143
144 wp_remote_post(CLARITY_COLLECT_ENDPOINT, $request);
145 }
146
147 /**
148 * Retrieves the client's IP address, excluding private and reserved ranges.
149 */
150 function clarity_get_ip_address() {
151 foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR') as $key) {
152 if (empty($_SERVER[$key])) {
153 continue;
154 }
155
156 foreach (explode(',', $_SERVER[$key]) as $ip) {
157 $ip = trim($ip);
158
159 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
160 return $ip;
161 }
162 }
163 }
164
165 return 'Unknown';
166 }
167