PluginProbe
Visual Website Optimizer / 4.7
Visual Website Optimizer v4.7
trunk 1.0 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.10 All 37 releases
visual-web-optimizer / visual-website-optimizer.php

visual-website-optimizer.php in Visual Website Optimizer 4.7, at visual-website-optimizer.php

858 lines 33.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 *
4 * Plugin Name: VWO
5 * Plugin URI: https://vwo.com/
6 * Description: VWO is the all-in-one platform that helps you conduct visitor research, build an optimization roadmap, and run continuous experimentation. Simply enable the plugin and start running tests on your WordPress website without doing any other code changes. Visit <a href="https://vwo.com/">VWO</a> for more details.
7 * Author: VWO
8 * Version: 4.7
9 * visual-website-optimizer.php
10 * Author URI: https://vwo.com/
11 *
12 * @package VWO
13 * @author VWO
14 * @version 4.7
15 **/
16
17 /**
18 * Generate Common Code
19 *
20 * @param integer $vwo_clicks integer. Defaults to 10.
21 */
22 function get_vwo_clhf_script_common_code( $vwo_clicks = 10 ) {
23 ob_start();
24 // @codingStandardsIgnoreStart
25 ?>
26 <!-- Start VWO Common Smartcode -->
27 <script <?php echo vwo_clhf_ignore_js_attr(); ?> type='text/javascript'>
28 var _vwo_clicks = <?php echo esc_html( $vwo_clicks ); ?>;
29 </script>
30 <!-- End VWO Common Smartcode -->
31 <?php
32 // @codingStandardsIgnoreEnd
33 $script_code = ob_get_clean();
34 return $script_code;
35 }
36
37 /**
38 * Get ignore js field setting
39 *
40 * @return bool boolean
41 */
42 function get_vwo_clhf_ignore_js() {
43 $ignore_js = get_option( 'ignore_js' );
44 $ignore_js = ( '1' === $ignore_js ) ? true : false;
45 return $ignore_js;
46 }
47
48 /**
49 * Get ignore js script attribute value
50 *
51 * @return string Returns script attribute value
52 */
53 function vwo_clhf_ignore_js_attr() {
54 $ignore_js = get_vwo_clhf_ignore_js();
55 $js_attr = '';
56 if ( function_exists( 'get_vwo_clhf_ignore_js' ) && $ignore_js ) {
57 $js_attr = 'data-cfasync="false" nowprocket';
58 }
59 return $js_attr;
60 }
61
62 /**
63 * Generate Synchronous Code
64 *
65 * @param int $vwo_id integer. Defaults to 0.
66 * @return string string for sync script.
67 */
68 function get_vwo_clhf_script_sync_code( $vwo_id = 0 ) {
69 ob_start();
70 // @codingStandardsIgnoreStart
71 ?>
72 <!-- Start VWO Smartcode -->
73 <script <?php echo vwo_clhf_ignore_js_attr(); ?> src="https://dev.visualwebsiteoptimizer.com/lib/<?php echo esc_html( $vwo_id ); ?>.js"></script>
74 <!-- End VWO Smartcode -->
75 <?php
76 // @codingStandardsIgnoreEnd
77 $sync_script = ob_get_clean();
78 return $sync_script;
79 }
80
81 /**
82 * Generate Asynchronous Code
83 *
84 * @param int $vwo_id integer.
85 * @param int $settings_tolerance integer.
86 * @param int $library_tolerance integer.
87 * @param bool $use_existing_jquery boolean.
88 * @return string String for async script.
89 */
90 function get_vwo_clhf_script_async_code( $vwo_id, $settings_tolerance, $library_tolerance, $use_existing_jquery ) {
91 ob_start();
92 // @codingStandardsIgnoreStart
93 ?>
94 <!-- Start VWO Async SmartCode -->
95 <link rel="preconnect" href="https://dev.visualwebsiteoptimizer.com" />
96 <script <?php echo vwo_clhf_ignore_js_attr(); ?> type='text/javascript' id='vwoCode'>
97 /* Fix: wp-rocket (application/ld+json) */
98 window._vwo_code || (function () {
99 var account_id=<?php echo esc_html( $vwo_id ); ?>,
100 version=2.1,
101 settings_tolerance=<?php echo esc_html( $settings_tolerance ); ?>,
102 library_tolerance=<?php echo esc_html( $library_tolerance ); ?>,
103 use_existing_jquery=<?php echo ( $use_existing_jquery ) ? 'true' : 'false'; ?>,
104 hide_element='body',
105 hide_element_style = 'opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important;transition:none !important;',
106 /* DO NOT EDIT BELOW THIS LINE */
107 f=false,w=window,d=document,v=d.querySelector('#vwoCode'),cK='_vwo_'+account_id+'_settings',cc={};try{var c=JSON.parse(localStorage.getItem('_vwo_'+account_id+'_config'));cc=c&&typeof c==='object'?c:{}}catch(e){}var stT=cc.stT==='session'?w.sessionStorage:w.localStorage;code={use_existing_jquery:function(){return typeof use_existing_jquery!=='undefined'?use_existing_jquery:undefined},library_tolerance:function(){return typeof library_tolerance!=='undefined'?library_tolerance:undefined},settings_tolerance:function(){return cc.sT||settings_tolerance},hide_element_style:function(){return'{'+(cc.hES||hide_element_style)+'}'},hide_element:function(){if(performance.getEntriesByName('first-contentful-paint')[0]){return''}return typeof cc.hE==='string'?cc.hE:hide_element},getVersion:function(){return version},finish:function(e){if(!f){f=true;var t=d.getElementById('_vis_opt_path_hides');if(t)t.parentNode.removeChild(t);if(e)(new Image).src='https://dev.visualwebsiteoptimizer.com/ee.gif?a='+account_id+e}},finished:function(){return f},addScript:function(e){var t=d.createElement('script');t.type='text/javascript';if(e.src){t.src=e.src}else{t.text=e.text}d.getElementsByTagName('head')[0].appendChild(t)},load:function(e,t){var i=this.getSettings(),n=d.createElement('script'),r=this;t=t||{};if(i){n.textContent=i;d.getElementsByTagName('head')[0].appendChild(n);if(!w.VWO||VWO.caE){stT.removeItem(cK);r.load(e)}}else{var o=new XMLHttpRequest;o.open('GET',e,true);o.withCredentials=!t.dSC;o.responseType=t.responseType||'text';o.onload=function(){if(t.onloadCb){return t.onloadCb(o,e)}if(o.status===200||o.status===304){_vwo_code.addScript({text:o.responseText})}else{_vwo_code.finish('&e=loading_failure:'+e)}};o.onerror=function(){if(t.onerrorCb){return t.onerrorCb(e)}_vwo_code.finish('&e=loading_failure:'+e)};o.send()}},getSettings:function(){try{var e=stT.getItem(cK);if(!e){return}e=JSON.parse(e);if(Date.now()>e.e){stT.removeItem(cK);return}return e.s}catch(e){return}},init:function(){if(d.URL.indexOf('__vwo_disable__')>-1)return;var e=this.settings_tolerance();w._vwo_settings_timer=setTimeout(function(){_vwo_code.finish();stT.removeItem(cK)},e);var t;if(this.hide_element()!=='body'){t=d.createElement('style');var i=this.hide_element(),n=i?i+this.hide_element_style():'',r=d.getElementsByTagName('head')[0];t.setAttribute('id','_vis_opt_path_hides');v&&t.setAttribute('nonce',v.nonce);t.setAttribute('type','text/css');if(t.styleSheet)t.styleSheet.cssText=n;else t.appendChild(d.createTextNode(n));r.appendChild(t)}else{t=d.getElementsByTagName('head')[0];var n=d.createElement('div');n.style.cssText='z-index: 2147483647 !important;position: fixed !important;left: 0 !important;top: 0 !important;width: 100% !important;height: 100% !important;background: white !important;';n.setAttribute('id','_vis_opt_path_hides');n.classList.add('_vis_hide_layer');t.parentNode.insertBefore(n,t.nextSibling)}var o='https://dev.visualwebsiteoptimizer.com/j.php?a='+account_id+'&u='+encodeURIComponent(d.URL)+'&vn='+version;if(w.location.search.indexOf('_vwo_xhr')!==-1){this.addScript({src:o})}else{this.load(o+'&x=true')}}};w._vwo_code=code;code.init();})();
108 </script>
109 <!-- End VWO Async SmartCode -->
110 <?php
111 // @codingStandardsIgnoreEnd
112 $async_script = ob_get_clean();
113 return $async_script;
114 }
115
116 // ------------------------------------------------------------------------//
117 // ---Hook-----------------------------------------------------------------//
118 // ------------------------------------------------------------------------//
119 add_action( 'wp_head', 'vwo_clhf_headercode', 1 );
120 add_action( 'admin_menu', 'vwo_clhf_plugin_menu' );
121 add_action( 'admin_init', 'vwo_clhf_register_mysettings' );
122 add_action( 'admin_notices', 'vwo_clhf_warn_nosettings' );
123
124
125 // ------------------------------------------------------------------------//
126 // ---Functions------------------------------------------------------------//
127 // ------------------------------------------------------------------------//
128 // options page link
129
130 /**
131 * Generate a function comment for the given function body.
132 *
133 * @throws Exception Description of exception.
134 * @return void
135 */
136 function vwo_clhf_plugin_menu() {
137 add_options_page( 'Visual Website Optimizer', 'VWO', 'create_users', 'clhf_vwo_options', 'vwo_clhf_plugin_options' );
138 }
139
140 /**
141 * Register the settings for the VWO options.
142 *
143 * @return void
144 */
145 function vwo_clhf_register_mysettings() {
146 register_setting('clhf_vwo_options', 'vwo_id', array(
147 'sanitize_callback' => 'vwo_clhf_sanitize_settings',
148 ));
149 register_setting( 'clhf_vwo_options', 'code_type' );
150 register_setting( 'clhf_vwo_options', 'vwo_clicks' );
151 register_setting( 'clhf_vwo_options', 'ignore_js', 'boolval' );
152 register_setting( 'clhf_vwo_options', 'settings_tolerance', 'intval' );
153 register_setting( 'clhf_vwo_options', 'library_tolerance', 'intval' );
154 register_setting( 'clhf_vwo_options', 'use_existing_jquery', 'boolval' );
155 register_setting( 'clhf_vwo_options', 'enable_woocommerce_event_tracking', 'boolval');
156 register_setting( 'clhf_vwo_options', 'track_product_view', 'boolval' );
157 register_setting( 'clhf_vwo_options', 'track_add_to_cart', 'boolval' );
158 register_setting( 'clhf_vwo_options', 'track_remove_from_cart', 'boolval' );
159 register_setting( 'clhf_vwo_options', 'track_checkout', 'boolval' );
160 register_setting( 'clhf_vwo_options', 'track_purchase', 'boolval' );
161 register_setting( 'clhf_vwo_options', 'vwo_server_side_tracking', 'boolval' );
162 }
163
164 // ------------------------------------------------------------------------//
165 // ---Output Functions-----------------------------------------------------//
166 // ------------------------------------------------------------------------//
167
168
169 /**
170 * Generates the action vwo_clhf_headercode function.
171 *
172 * @throws Exception Description of exception.
173 * @return void
174 */
175 function vwo_clhf_headercode() {
176 // Runs in the header.
177 $vwo_id = get_option( 'vwo_id' );
178 $code_type = get_option( 'code_type' );
179
180 if ( $vwo_id ) {
181 if ( empty( get_option( 'vwo_clicks' ) ) ) {
182 update_option( 'vwo_clicks', '10' );
183 }
184 $vwo_clicks = get_option( 'vwo_clicks' );
185
186 // Common script code.
187 // @codingStandardsIgnoreLine
188 echo get_vwo_clhf_script_common_code( $vwo_clicks );
189
190 if ( 'SYNC' === $code_type ) {
191 // Sync script code.
192 // @codingStandardsIgnoreLine
193 echo get_vwo_clhf_script_sync_code( $vwo_id );
194 } else {
195
196 $settings_tolerance = get_option( 'settings_tolerance' );
197 if ( ! is_numeric( $settings_tolerance ) ) {
198 $settings_tolerance = 2000;
199 }
200
201 $library_tolerance = get_option( 'library_tolerance' );
202 if ( ! is_numeric( $library_tolerance ) ) {
203 $library_tolerance = 2500;
204 }
205
206 $use_existing_jquery = get_option( 'use_existing_jquery' );
207 $use_existing_jquery = ( '1' === $use_existing_jquery ) ? true : false;
208
209 // Async script code.
210 // @codingStandardsIgnoreLine
211 echo get_vwo_clhf_script_async_code( $vwo_id, $settings_tolerance, $library_tolerance, $use_existing_jquery );
212 }
213 }
214 }
215
216 // ------------------------------------------------------------------------//
217 // ---Page Output Functions------------------------------------------------//
218 // ------------------------------------------------------------------------//
219 // options page
220
221
222 /**
223 * Generates the options page for the VWO plugin.
224 *
225 * @throws Exception Description of exception.
226 * @return void
227 */
228 function vwo_clhf_plugin_options() {
229
230 ?>
231 <div class="wrap">
232 <h1 style="margin-bottom: 15px;"><img src="https://static.wingify.com/gcp/images/vwo-logo-color.svg" alt="VWO Logo" style="vertical-align: middle; margin-right: 10px; margin-top: -5px; height: 20px;">Configuration</h1>
233
234 <form method="post" action="options.php" novalidate>
235 <?php
236 settings_fields('clhf_vwo_options');
237 ?>
238 <div class="vwo-admin-content">
239 <?php vwo_clhf_render_tabs(); ?>
240 <div class="tab-content">
241 <div id="tab-general" class="tab-pane active">
242 <?php vwo_clhf_render_general_settings(); ?>
243 </div>
244 <div id="tab-advanced" class="tab-pane">
245 <?php vwo_clhf_render_advanced_settings(); ?>
246 </div>
247 <div id="tab-woocommerce" class="tab-pane">
248 <?php vwo_clhf_render_woocommerce_settings(); ?>
249 </div>
250 </div>
251 </div>
252 <?php submit_button(); ?>
253 </form>
254 </div>
255 <?php
256 vwo_clhf_render_styles();
257 vwo_clhf_render_scripts();
258 }
259
260 function vwo_clhf_render_tabs() {
261 ?>
262 <h2 class="nav-tab-wrapper">
263 <a href="#tab-general" class="nav-tab nav-tab-active">General Settings</a>
264 <a href="#tab-advanced" class="nav-tab">Advanced Settings</a>
265 <a href="#tab-woocommerce" class="nav-tab">WooCommerce</a>
266 </h2>
267 <?php
268 }
269
270 function vwo_clhf_render_general_settings() {
271 ?>
272 <main class="main-grid">
273 <div class="form-container">
274 <?php
275 vwo_clhf_render_field([
276 'id' => 'vwo_id',
277 'label' => 'Your VWO Account ID',
278 'type' => 'text',
279 'tooltip' => 'Enter your VWO Account ID here',
280 ]);
281 vwo_clhf_render_field([
282 'id' => 'code_type',
283 'label' => 'Code Type',
284 'type' => 'radio',
285 'options' => [
286 [
287 'label' => 'Asynchronous',
288 'value' => 'ASYNC',
289 'sublabel' => 'Loads faster without blocking other elements',
290 ],
291 [
292 'label' => 'Synchronous',
293 'value' => 'SYNC',
294 'sublabel' => 'Executes immediately but may slow down page load',
295 ],
296 ],
297 ]);
298 ?>
299 </div>
300 <div class="main-grid__description">
301 <h2>Get Started Easily</h2>
302 <p>
303 Enter your <b>VWO Account ID</b> to begin.
304 <br>
305 New to VWO?
306 <a target="_blank" href="https://vwo.com/free-trial/?utm_source=integration_wordpress&utm_medium=referral&utm_campaign=plugin_page&utm_content=config_screen_banner">Create an account</a> and start optimizing <br/>your website effortlessly.
307 <br><br><br>
308 Need help? Visit our <a target="_blank" href="https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress">knowledge base</a>.
309 </p>
310 </div>
311 </main>
312 <?php
313 }
314
315 function vwo_clhf_render_advanced_settings() {
316 ?>
317 <div class="form-container">
318 <?php
319 vwo_clhf_render_field([
320 'id' => 'vwo_clicks',
321 'label' => 'No. of Heatmap Clicks',
322 'type' => 'number',
323 'tooltip' => 'Set the number of heatmap clicks to record',
324 'min' => 3,
325 'default' => 10,
326 ]);
327 vwo_clhf_render_field([
328 'id' => 'settings_tolerance',
329 'label' => 'Settings Timeout',
330 'type' => 'number',
331 'tooltip' => 'Set the timeout for settings in milliseconds',
332 'default' => 2000,
333 'class' => 'async-option',
334 'suffix' => 'ms',
335 ]);
336 vwo_clhf_render_field([
337 'id' => 'library_tolerance',
338 'label' => 'Library Timeout',
339 'type' => 'number',
340 'tooltip' => 'Set the timeout for library in milliseconds',
341 'default' => 2500,
342 'class' => 'async-option',
343 'suffix' => 'ms',
344 ]);
345 vwo_clhf_render_field([
346 'id' => 'use_existing_jquery',
347 'label' => 'Use Existing jQuery',
348 'type' => 'checkbox',
349 'tooltip' => 'Use the existing jQuery library on your site',
350 'class' => 'async-option',
351 ]);
352 vwo_clhf_render_field([
353 'id' => 'ignore_js',
354 'label' => 'Skip Deferred Execution',
355 'type' => 'checkbox',
356 'tooltip' => 'Skip deferred execution of the VWO script',
357 ]);
358 ?>
359 </div>
360 <?php
361 }
362
363 function vwo_clhf_render_woocommerce_settings() {
364 $value = get_option('enable_woocommerce_event_tracking', false);
365 $vwo_server_side_tracking = get_option('vwo_server_side_tracking', false);
366 ?>
367 <div>
368 <div class="woocommerce-main-header">
369 <div class="checkbox-container">
370 <input type="checkbox" id="enable_woocommerce_event_tracking" name="enable_woocommerce_event_tracking" class="vwo-checkbox" <?php echo checked($value, '1', false) ?>>
371 <label class="vwo-checkbox-label" for="enable_woocommerce_event_tracking">Toggle</label>
372 <label class="form-label form-label--checkbox" for="enable_woocommerce_event_tracking">Enable WooCommerce Event Tracking</label>
373 </div>
374 <p class="form-description form-description--checkbox">Event tracking will not work unless WooCommerce is enabled on your WordPress site.</p>
375 </div>
376 <div class="woocommerce-main-header">
377 <div class="checkbox-container vwo_server_side_tracking">
378 <input type="checkbox" id="vwo_server_side_tracking" name="vwo_server_side_tracking" class="vwo-checkbox" <?php echo checked($vwo_server_side_tracking, '1', false) ?>>
379 <label class="vwo-checkbox-label" for="vwo_server_side_tracking">Toggle</label>
380 <label class="form-label form-label--checkbox" for="Enable Server-Side Tracking">Enable Server-Side Tracking</label>
381 </div>
382 <p class="form-description form-description--checkbox">Enable server-side tracking instead of JavaScript-based tracking.</p>
383 </div>
384
385
386 <div class="woocommerce-row woocommerce-row--disabled">
387 <?php
388 vwo_clhf_render_woocommerce_event_tracking([
389 'id' => 'track_product_view',
390 'label' => 'Product Viewed',
391 'description' => 'This event logs an instance where a customer views a product details page.',
392 'readmore_link' => 'https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress'
393 ]);
394 vwo_clhf_render_woocommerce_event_tracking([
395 'id' => 'track_add_to_cart',
396 'label' => 'Add To Cart',
397 'description' => 'This event logs an instance where a customer adds a product to their cart.',
398 'readmore_link' => 'https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress'
399 ]);
400 vwo_clhf_render_woocommerce_event_tracking([
401 'id' => 'track_remove_from_cart',
402 'label' => 'Product Removed From Cart',
403 'description' => 'This event logs an instance where a customer removes a product from their cart.',
404 'readmore_link' => 'https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress'
405 ]);
406 // vwo_clhf_render_woocommerce_event_tracking([
407 // 'id' => 'track_checkout',
408 // 'label' => 'Checkout Page',
409 // 'description' => 'This event logs an instance where a customer visits the checkout page.',
410 // 'readmore_link' => 'https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress'
411 // ]);
412 vwo_clhf_render_woocommerce_event_tracking([
413 'id' => 'track_purchase',
414 'label' => 'Purchase Order',
415 'description' => 'This event logs an instance where a customer completes a purchase.',
416 'readmore_link' => 'https://help.vwo.com/hc/en-us/articles/360020745993-Integrating-VWO-With-WordPress'
417 ]);
418 ?>
419 </div>
420 </div>
421 <?php
422 }
423
424 function vwo_clhf_render_woocommerce_event_tracking($field) {
425 $value = get_option($field['id'], isset($field['default']) ? $field['default'] : '');
426 ?>
427 <div class="woocommerce-row-item">
428 <div class="woocommerce-row-item-header">
429 <h3 class="woocommerce-row-item-title"><?php echo esc_html($field['label']); ?></h3>
430 <input type="checkbox" name="<?php echo esc_attr($field['id']); ?>" id="<?php echo esc_attr($field['id']); ?>" <?php echo checked($value, '1', false) ?> class="vwo-checkbox">
431 <label for="<?php echo esc_attr($field['id']); ?>" class="vwo-checkbox-label">Toggle</label>
432 </div>
433 <p class="woocommerce-row-item-description">
434 <?php echo esc_html($field['description']); ?>
435 <?php /* if (isset($field['readmore_link'])): ?>
436 <a href="<?php echo esc_url($field['readmore_link']); ?>" target="_blank">Read more</a>
437 <?php endif; */ ?>
438 </p>
439 </div>
440 <?php
441 }
442
443
444 function vwo_clhf_render_field($field) {
445 $isCheckbox = $field['type'] === 'checkbox';
446 $value = get_option($field['id'], isset($field['default']) ? $field['default'] : '');
447
448 echo '<div class="' . esc_attr(isset($field['class'])?$field['class']:"") . '">';
449
450 $label = '<label class="form-label" for="' . esc_attr($field['id']) . '">' . esc_html($field['label']) . '</label>';
451
452 switch ($field['type']) {
453 case 'text':
454 case 'number':
455 echo $label;
456 echo '<input type="' . esc_attr($field['type']) . '" id="' . esc_attr($field['id']) . '" name="' . esc_attr($field['id']) . '" value="' . esc_attr($value) . '"';
457 if (isset($field['min'])) echo ' min="' . esc_attr($field['min']) . '"';
458 echo ' class="form-input" />';
459 if (isset($field['suffix'])) echo ' ' . esc_html($field['suffix']);
460 break;
461 case 'radio':
462 echo $label;
463 foreach ($field['options'] as $options) {
464 echo '<div class="radio-container-wrapper">
465 <div class="radio-container">';
466 echo '<label class="form-radio-label"><input type="radio" name="' . esc_attr($field['id']) . '" value="' . esc_attr($options['value']) . '"' . checked($value, $options['value'], false) . ' /> ' . esc_html($options['label']) . '</label> ';
467 echo '</div>';
468 echo '<p class="radio-sublabel">' . esc_html($options['sublabel']) . '</p>';
469 echo '</div>';
470 }
471 break;
472 case 'checkbox':
473 echo '<div class="checkbox-container">';
474 echo '<input type="checkbox" id="' . esc_attr($field['id']) . '" name="' . esc_attr($field['id']) . '" class="vwo-checkbox" value="1"' . checked($value, '1', false) . ' />';
475 echo '<label class="vwo-checkbox-label" for="' . esc_attr($field['id']) . '">Toggle</label>';
476 echo '<label class="form-label form-label--checkbox" for="' . esc_attr($field['id']) . '">' . esc_html($field['label']) . '</label>';
477 echo '</div>';
478 break;
479 }
480
481 if (isset($field['tooltip'])) {
482 echo '<p class="form-description ' . ($isCheckbox ? 'form-description--checkbox' : '') . '">' . esc_html($field['tooltip']) . '</p>';
483 }
484
485 echo '</div>';
486 }
487
488 function vwo_clhf_render_styles() {
489 ?>
490 <style>
491 input[type="radio"] {
492 margin: 0 !important;
493 }
494 input[type=radio]:checked::before {
495 background-color: #3858E9;
496 }
497 .vwo-admin-content {
498 background: #fff;
499 padding: 20px;
500 border: 1px solid #ccd0d4;
501 box-shadow: 0 1px 1px rgba(0,0,0,.04);
502 margin-top: 20px;
503 }
504 .vwo-admin-content .nav-tab,
505 .vwo-admin-content .nav-tab-active{
506 outline:none;
507 box-shadow: none;
508 }
509 .main-grid {
510 display: flex;
511 justify-content: space-between;
512 }
513 .main-grid__description {
514 background-color: #f9f9f9;
515 padding: 24px;
516 border-radius: 8px;
517 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
518 font-family: 'Segoe UI', sans-serif;
519 height: fit-content;max-width: 650px;
520 border: 1px solid #E0E0E0;
521 margin: 20px;
522 }
523 .main-grid__description h2 {
524 font-weight: 600;
525 margin-bottom: 10px;
526 margin-top: 0;
527 font-size: 20px;
528 color: #333;
529 }
530 .main-grid__description p {
531 font-size: 14px;
532 color: #757575;
533 line-height: 1.6;
534 margin-top: 21px;
535 margin-bottom: 0px;
536 }
537 .main-grid__description a {
538 color: #3858E9;
539 }
540 .form-container {
541 margin-top: 24px;
542 margin-bottom: 30px;
543 display: flex;
544 flex-direction: column;
545 gap: 28px;
546 flex: 1;
547 }
548 .form-label {
549 font-size: 12px;
550 color: #1E1E1E;
551 display: block;
552 margin-bottom: 10px;
553 font-weight: 500;
554 }
555 .form-label--checkbox {
556 cursor: pointer;
557 margin-bottom: 0;
558 }
559 .form-radio-label {
560 display: flex;
561 align-items: center;
562 gap: 10px;
563 margin-bottom: 10px;
564 cursor: pointer;
565 }
566 .form-radio-label:last-child {
567 margin-bottom: 0;
568 }
569 .form-description {
570 color: #757575;
571 margin-top: 10px;
572 margin-bottom: 0;
573 font-size: 12px;
574 }
575 .form-description--checkbox {
576 margin-top: 5px;
577 margin-left: 42px;
578 }
579 .form-input {
580 width: 100%;
581 max-width: 400px;
582 border: 1px solid #949494 !important;
583 border-radius: 2px !important;
584 }
585 .checkbox-container, .radio-container {
586 display: flex;
587 gap: 10px;
588 }
589 .radio-container-wrapper {
590 margin-bottom: 20px;
591 }
592 .radio-container-wrapper:last-child {
593 margin-bottom: 0;
594 }
595 .radio-sublabel {
596 font-size: 12px;
597 color: #757575;
598 margin-top: 5px;
599 margin-bottom: 0;
600 margin-left: 26px;
601 }
602 .checkbox-container .form-description {
603 width: 100%;
604 }
605 .async-option {
606 display: none;
607 }
608 .tab-pane {
609 display: none;
610 }
611 .tab-pane.active {
612 display: block;
613 }
614 .description {
615 max-width: 800px;
616 margin-bottom: 20px;
617 }
618
619 .woocommerce-row {
620 display: grid;
621 grid-template-columns: repeat(3, 1fr);
622 gap: 16px;
623 }
624 .woocommerce-row-item {
625 border: 1px solid rgba(0, 0, 0, 0.10);
626 border-radius: 8px;
627 }
628 .woocommerce-row-item-header {
629 display: flex;
630 justify-content: space-between;
631 align-items: center;
632 gap: 5px;
633 padding: 10px;
634 border-bottom: 1px solid rgba(0, 0, 0, 0.10);
635 }
636 .woocommerce-row-item-title {
637 margin: 0;
638 font-size: 13px;
639 font-weight: 500;
640 color: #1E1E1E;
641 }
642 .woocommerce-row-item-description {
643 margin: 0;
644 font-size: 12px;
645 color: #757575;
646 padding: 10px;
647 }
648 .woocommerce-row-item-description a {
649 color: #3858E9;
650 }
651 .woocommerce-main-header {
652 margin: 30px 0;
653 }
654 .woocommerce-row--disabled {
655 opacity: 0.4;
656 cursor: not-allowed;
657 pointer-events: none;
658 }
659 input[type=checkbox].vwo-checkbox{
660 height: 0;
661 width: 0;
662 visibility: hidden;
663 position: absolute;
664 clip: rect(1px,1px,1px,1px);
665 overflow: hidden;
666 }
667
668 label.vwo-checkbox-label {
669 box-sizing: border-box;
670 cursor: pointer;
671 text-indent: -9999px;
672 width: 32px;
673 height: 18px;
674 border: 1px solid #000;
675 background: #fff;
676 display: block;
677 border-radius: 100px;
678 position: relative;
679 }
680
681 label.vwo-checkbox-label:after {
682 content: '';
683 position: absolute;
684 top: 50%;
685 transform: translateY(-50%);
686 left: 2px;
687 width: 12px;
688 height: 12px;
689 background: #000;
690 border-radius: 90px;
691 transition: 0.3s;
692 }
693
694 input.vwo-checkbox:checked + label.vwo-checkbox-label {
695 background: #3858E9;
696 border-color: #3858E9;
697 }
698
699 input.vwo-checkbox:checked + label.vwo-checkbox-label:after {
700 left: calc(100% - 2px);
701 transform: translateX(-100%) translateY(-50%);
702 background-color: #fff;
703 }
704
705 </style>
706 <?php
707 }
708
709 function vwo_clhf_render_scripts() {
710 ?>
711 <script>
712 jQuery(document).ready(function($) {
713 function toggleAsyncOptions() {
714 var isAsync = $('input[name="code_type"]:checked').val() === 'ASYNC';
715 $('.async-option').toggle(isAsync);
716 }
717 function toggleWooCommerceOptions() {
718 var isWooCommerce = $('input[name="enable_woocommerce_event_tracking"]:checked');
719
720 if(isWooCommerce.length > 0) {
721 $('.woocommerce-row').removeClass('woocommerce-row--disabled');
722 $('.vwo_server_side_tracking').removeClass('woocommerce-row--disabled');
723
724 } else {
725 $('.woocommerce-row').addClass('woocommerce-row--disabled');
726 $('.vwo_server_side_tracking').addClass('woocommerce-row--disabled');
727 }
728 }
729
730 $('input[name="enable_woocommerce_event_tracking"]').change(toggleWooCommerceOptions);
731 $("label[for='enable_woocommerce_event_tracking']").click(toggleWooCommerceOptions);
732 toggleWooCommerceOptions(); // Run on page load
733
734 $('input[name="code_type"]').change(toggleAsyncOptions);
735 toggleAsyncOptions(); // Run on page load
736
737 // Handle tab switching
738 $('.nav-tab-wrapper .nav-tab').on('click', function(e) {
739 e.preventDefault();
740 var targetTab = $(this).attr('href');
741
742 // Update active tab
743 $('.nav-tab-wrapper .nav-tab').removeClass('nav-tab-active');
744 $(this).addClass('nav-tab-active');
745
746 // Show target tab content
747 $('.tab-pane').removeClass('active').hide();
748 $(targetTab).addClass('active').show();
749 });
750
751 // Ensure the first tab is visible on page load
752 $('#tab-general').show();
753 });
754 </script>
755 <?php
756 }
757
758 function vwo_clhf_enqueue_admin_scripts($hook) {
759 if ('settings_page_clhf_vwo_options' !== $hook) {
760 return;
761 }
762 wp_enqueue_style('wp-admin');
763 }
764 add_action('admin_enqueue_scripts', 'vwo_clhf_enqueue_admin_scripts');
765
766 /**
767 * Displays a warning message if VWO settings are not configured.
768 * This function checks if the user is an admin and if the VWO ID option is set. If the user is not an admin or
769 * the VWO ID option is not set, it displays a warning message.
770 *
771 * @throws Exception Description of exception.
772 * @return void
773 */
774 function vwo_clhf_warn_nosettings() {
775 if ( ! is_admin() ) {
776 return;
777 }
778
779 $clhf_option = get_option( 'vwo_id' );
780 if ( ! $clhf_option || $clhf_option < 1 ) {
781 echo "<div id='vwo-warning' class='updated fade'><p><strong>VWO is almost ready.</strong> You must <a href=\"options-general.php?page=clhf_vwo_options\">enter your Account ID</a> for it to work.</p></div>";
782 }
783 }
784
785
786 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'vwo_clhf_add_plugin_page_settings_link' );
787
788 /**
789 * Function to add Settings Links on Plugin page
790 *
791 * @param array $links Array of links.
792 * @return array
793 */
794 function vwo_clhf_add_plugin_page_settings_link( $links ) {
795 $links[] = '<a href="' .
796 admin_url( 'options-general.php?page=clhf_vwo_options' ) .
797 '">' . __( 'Settings' ) . '</a>';
798 return $links;
799 }
800
801 /**
802 * Disables VWO in Divi Builder.
803 *
804 * @throws Exception Description of exception.
805 * @return void
806 */
807 function disable_vwo_in_divi_builder() {
808 if ( has_action( 'wp_head', 'vwo_clhf_headercode' ) && function_exists( 'et_core_is_fb_enabled' ) && et_core_is_fb_enabled() ) {
809 remove_action( 'wp_head', 'vwo_clhf_headercode', 1 );
810 }
811 }
812
813 add_action( 'wp_head', 'disable_vwo_in_divi_builder', 0 );
814
815 // Add this new function to validate settings
816 function vwo_clhf_validate_settings() {
817 $has_errors = false;
818
819 // Validate VWO Account ID
820 $vwo_id = get_option('vwo_id');
821 if (empty($vwo_id) || !is_numeric($vwo_id)) {
822 add_settings_error('vwo_clhf_options', 'vwo_id', 'Please enter a valid VWO Account ID.', 'error');
823 $has_errors = true;
824 }
825
826 // Add more validation for other fields as needed
827
828 return $has_errors;
829 }
830
831 // Add this new function to sanitize and validate settings
832 function vwo_clhf_sanitize_settings($input) {
833 // Sanitize and validate VWO Account ID
834 $vwo_id = sanitize_text_field($input);
835 if (empty($vwo_id) || !is_numeric($vwo_id)) {
836 add_settings_error('vwo_clhf_options', 'vwo_id', 'Please enter a valid VWO Account ID.', 'error');
837 }
838
839 // Add more sanitization and validation for other fields as needed
840 // Check if vwo_id is changed
841 $current_vwo_id = get_option('vwo_id');
842 if ($current_vwo_id !== $vwo_id) {
843 update_option('vwo_coll_url','');
844 }
845 return $vwo_id;
846 }
847
848 function enqueue_jquery_script() {
849 wp_enqueue_script('jquery');
850 }
851 add_action('wp_enqueue_scripts', 'enqueue_jquery_script');
852
853 if (file_exists(plugin_dir_path(__FILE__) . 'woocommerce-events.php')) {
854 include_once plugin_dir_path(__FILE__) . 'woocommerce-events.php';
855 }
856
857
858 ?>