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