PluginProbe ʕ •ᴥ•ʔ
Microsoft Clarity / 0.10.19
Microsoft Clarity v0.10.19
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.php
microsoft-clarity Last commit date
js 4 months ago LICENSE.txt 5 years ago clarity-collect-batch.php 3 months ago clarity-collect-storage.php 3 months ago clarity-hooks.php 4 months ago clarity-page.php 4 months ago clarity-server-analytics.php 4 months ago clarity.php 3 months ago index.php 5 years ago readme.txt 3 months ago
clarity.php
306 lines
1 <?php
2
3 /**
4 * Plugin Name: Microsoft Clarity
5 * Plugin URI: https://clarity.microsoft.com/
6 * Description: With data and session replay from Clarity, you'll see how people are using your site — where they get stuck and what they love.
7 * Version: 0.10.19
8 * Author: Microsoft
9 * Author URI: https://www.microsoft.com/en-us/
10 * License: MIT
11 * License URI: https://docs.opensource.microsoft.com/content/releasing/license.html
12 */
13
14 require_once plugin_dir_path(__FILE__) . '/clarity-page.php';
15 require_once plugin_dir_path(__FILE__) . '/clarity-hooks.php';
16 require_once plugin_dir_path(__FILE__) . '/clarity-server-analytics.php';
17
18 /**
19 * Runs when Clarity Plugin is activated.
20 */
21 register_activation_hook(__FILE__, 'clarity_on_activation');
22 add_action('admin_init', 'clarity_activation_redirect');
23
24 /**
25 * Plugin activation callback. Registers option to redirect on next admin load.
26 */
27 function clarity_on_activation($network_wide)
28 {
29 // update activate option
30 clrt_update_clarity_options('activate', $network_wide);
31
32 // Don't do redirects when multiple plugins are bulk activated
33 if (
34 (isset($_REQUEST['action']) && 'activate-selected' === $_REQUEST['action']) &&
35 (isset($_POST['checked']) && count($_POST['checked']) > 1)
36 ) {
37 return;
38 }
39 add_option('clarity_activation_redirect', wp_get_current_user()->ID);
40 }
41
42 /**
43 * Redirects the user after plugin activation
44 */
45 function clarity_activation_redirect()
46 {
47 // Make sure it is the user that activated the plugin
48 if (is_user_logged_in() && intval(get_option('clarity_activation_redirect', false)) === wp_get_current_user()->ID) {
49 // Make sure we don't redirect again
50 delete_option('clarity_activation_redirect');
51 wp_safe_redirect(admin_url('admin.php?page=microsoft-clarity'));
52 exit;
53 }
54 }
55
56 /**
57 * Runs when Clarity Plugin is deactivated.
58 */
59 register_deactivation_hook(__FILE__, 'clarity_on_deactivation');
60 function clarity_on_deactivation($network_wide)
61 {
62 clrt_update_clarity_options('deactivate', $network_wide);
63 }
64
65 /**
66 * Runs when Clarity Plugin is uninstalled.
67 */
68 register_uninstall_hook(__FILE__, 'clarity_on_uninstall');
69 function clarity_on_uninstall()
70 {
71 // Uninstall hook doesn't pass $network_wide flag.
72 // Set it to true to delete options for all the sites in a multisite setup (in a single site setup, the flag is irrelevant).
73
74 clrt_update_clarity_options('uninstall', true);
75 }
76
77 /**
78 * Updates clarity options based on the plugin's action and WordPress installation type.
79 *
80 * @since 0.10.1
81 *
82 * @param string $action activate, deactivate or uninstall.
83 * @param bool $network_wide In case of a multisite installation, should the action be performed on all the sites or not.
84 */
85 function clrt_update_clarity_options($action, $network_wide)
86 {
87 if (is_multisite() && $network_wide) {
88 $sites = get_sites();
89 foreach ($sites as $site) {
90 switch_to_blog($site->blog_id);
91
92 clrt_update_clarity_options_handler($action, $network_wide);
93
94 restore_current_blog();
95 }
96 } else {
97 clrt_update_clarity_options_handler($action, $network_wide);
98 }
99 }
100
101 /**
102 * @since 0.10.1
103 */
104 function clrt_update_clarity_options_handler($action, $network_wide)
105 {
106 switch ($action) {
107 case 'activate':
108 $id = get_option('clarity_wordpress_site_id');
109
110 if (! $id) {
111 update_option('clarity_wordpress_site_id', wp_generate_uuid4());
112 }
113
114 clarity_create_collect_events_table();
115 clarity_schedule_collect_recurring();
116 break;
117 case 'deactivate':
118 // Plugin activation/deactivation is handled differently in the database for site-level and network-wide activation.
119 // Ensure a complete deactivation if the plugin was activated per site before network-wide activation.
120
121 $plugin_name = plugin_basename(__FILE__);
122 if ($network_wide && in_array($plugin_name, (array) get_option('active_plugins', array()), true)) {
123 deactivate_plugins($plugin_name, true, false);
124 }
125
126 update_option('clarity_wordpress_site_id', '');
127 update_option('clarity_project_id', '');
128 clarity_flush_and_clear_collect_recurring();
129 break;
130 case 'uninstall':
131 delete_option('clarity_wordpress_site_id');
132 delete_option('clarity_project_id');
133 delete_option('clarity_is_agent_enabled');
134 // Cleanup for the option used up to version 0.10.16. Should remove this after users migrate to 0.10.17+ where this option is no longer used.
135 delete_option('clarity_collect_batch');
136 clarity_flush_and_clear_collect_recurring();
137 clarity_drop_collect_events_table();
138 break;
139 }
140 }
141
142 /**
143 * Escapes the plugin id characters.
144 */
145 function escape_value_for_script($value)
146 {
147 return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
148 }
149
150 /**
151 * Adds the script to run clarity.
152 */
153 add_action('wp_head', 'clarity_add_script_to_header');
154 function clarity_add_script_to_header()
155 {
156 $clarity_project_id = get_option('clarity_project_id');
157 if (! empty($clarity_project_id)) {
158 ?>
159 <script type="text/javascript">
160 (function(c, l, a, r, i, t, y) {
161 c[a] = c[a] || function() {
162 (c[a].q = c[a].q || []).push(arguments)
163 };
164 t = l.createElement(r);
165 t.async = 1;
166 t.src = "https://www.clarity.ms/tag/" + i + "?ref=wordpress";
167 y = l.getElementsByTagName(r)[0];
168 y.parentNode.insertBefore(t, y);
169 })(window, document, "clarity", "script", "<?php echo escape_value_for_script($clarity_project_id); ?>");
170 </script>
171 <?php
172 }
173 }
174
175 /**
176 * Adds the script to run clarity.
177 */
178 add_action('wp_head', 'brand_agent_add_script_to_header');
179 function brand_agent_add_script_to_header()
180 {
181 $is_agent_enabled = get_option('clarity_is_agent_enabled');
182 $should_inject_brand_agents_script = should_inject_brand_agents_script();
183 if ($is_agent_enabled == 1 && $should_inject_brand_agents_script) {
184 $frontend_injection_url = 'https://adsagentclientafd-b7hqhjdrf3fpeqh2.b01.azurefd.net/frontendInjection.js'
185 ?>
186 <script>
187 (function() {
188 var script = document.createElement('script');
189 script.src = '<?php echo esc_js($frontend_injection_url); ?>';
190 script.type = 'module';
191 document.head.appendChild(script);
192 })();
193 </script>
194 <?php
195 }
196 }
197
198 /**
199 * Adds the page link to the Microsoft Clarity block on installed plugin page.
200 */
201 add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'clarity_page_link');
202 function clarity_page_link($links)
203 {
204 $url = get_admin_url() . 'admin.php?page=microsoft-clarity';
205 $clarity_link = "<a href='$url'>" . __('Clarity Dashboard') . '</a>';
206 array_unshift($links, $clarity_link);
207 return $links;
208 }
209
210 /**
211 * Retrieving the currently installed plugin version
212 */
213 function get_installed_plugin_version()
214 {
215 if (! function_exists('get_plugin_data')) {
216 require_once(ABSPATH . 'wp-admin/includes/plugin.php');
217 }
218
219 $plugin_data = get_plugin_data(plugin_dir_path(__FILE__) . 'clarity.php');
220
221 return $plugin_data['Version'];
222 }
223
224 /**
225 * Retrieving the latest version from the WordPress.org repository.
226 */
227 function get_latest_plugin_version_from_api()
228 {
229 $api_url = 'http://api.wordpress.org/plugins/info/1.0/microsoft-clarity.json';
230 $response = wp_remote_get($api_url);
231
232 if (is_wp_error($response)) {
233 return false;
234 }
235
236 $body = wp_remote_retrieve_body($response);
237 $plugin_info = json_decode($body);
238
239 if ($plugin_info && isset($plugin_info->version)) {
240 return $plugin_info->version;
241 }
242
243 return false;
244 }
245
246 /**
247 * Checking if the current plugin version is latest
248 */
249 add_action('admin_init', 'check_if_installed_plugin_version_is_latest');
250 function check_if_installed_plugin_version_is_latest()
251 {
252 $installed_version = get_installed_plugin_version();
253 $latest_version = get_latest_plugin_version_from_api();
254
255 if ($installed_version && $latest_version) {
256 if (version_compare($installed_version, $latest_version, '<')) {
257 update_option('clarity_is_latest_plugin_version', '0');
258 } else {
259 update_option('clarity_is_latest_plugin_version', '1');
260 }
261 }
262 }
263
264 /**
265 * Check if script should be injected on current page
266 */
267 function should_inject_brand_agents_script()
268 {
269 // Inject on WooCommerce pages
270 if (function_exists('is_woocommerce') && is_woocommerce()) {
271 return true;
272 }
273
274 // Inject on shop page
275 if (function_exists('is_shop') && is_shop()) {
276 return true;
277 }
278
279 // Inject on product pages
280 if (function_exists('is_product') && is_product()) {
281 return true;
282 }
283
284 // Inject on cart page
285 if (function_exists('is_cart') && is_cart()) {
286 return true;
287 }
288
289 // Inject on checkout page
290 if (function_exists('is_checkout') && is_checkout()) {
291 return true;
292 }
293
294 // Inject on account pages
295 if (function_exists('is_account_page') && is_account_page()) {
296 return true;
297 }
298
299 // Inject on homepage if it's the shop
300 if (is_front_page() && get_option('show_on_front') === 'page' && function_exists('wc_get_page_id') && get_option('page_on_front') == wc_get_page_id('shop')) {
301 return true;
302 }
303
304 return false;
305 }
306