PluginProbe
EasyTest – Simplify A/B Testing / 1.0.2
EasyTest – Simplify A/B Testing v1.0.2
1.0.4 1.0.3 trunk 1.0.1 1.0.2
convertpro / includes / function.php

function.php in EasyTest – Simplify A/B Testing 1.0.2, at includes/function.php

394 lines 14.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use ConvertPro\Classes\Repo;
4
5 // AJAX handler to handle requests
6 add_action('wp_ajax_convertpro_ajax_action', 'convertpro_ajax_request');
7 add_action('wp_ajax_nopriv_convertpro_ajax_action', 'convertpro_ajax_request');
8
9 function convertpro_ajax_request()
10 {
11 check_ajax_referer('convertpro_nonce', 'security');
12
13 global $wpdb;
14
15 $testId = isset($_COOKIE['convert_pro_test_id']) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_test_id'])) : '';
16 $variationid = isset($_COOKIE['convert_pro_variation_id_'.$testId]) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_variation_id_'.$testId])) : '';
17 $clientId = isset($_COOKIE['convert_pro_uid']) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_uid'])) : '';
18 $pageslug = isset($_COOKIE['convert_pro_test_' . $testId]) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_test_' . $testId])) : '';
19 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
20
21 $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "convertpro" . " WHERE id =%d", $testId)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
22
23 $pageId = '';
24 foreach ($results as $result) {
25 $pageId = isset($result->conversion_page_id) ? $result->conversion_page_id : '';
26 }
27
28 $permalink = get_permalink($pageId);
29
30 $purl = isset($_POST['previous_url']) ? sanitize_text_field(wp_unslash($_POST['previous_url'])) : '';
31
32 $parsedUrl = wp_parse_url($purl);
33 $path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
34 $path = trim($path, '/');
35
36 // Get the last segment (page slug)
37 $segments = explode('/', $path);
38 $pageSlug = end($segments);
39
40
41 $fpath = isset($_SERVER['HTTP_REFERER']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_REFERER'])) : '';
42
43
44 $message = '';
45 if ($pageSlug == $pageslug) {
46
47 if ($fpath === $permalink) {
48
49 $query = $wpdb->get_results($wpdb->prepare(// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
50 "SELECT * FROM {$wpdb->prefix}convertpro_interactions
51 WHERE splittest_id = %d
52 AND client_id = %s",
53 $testId,
54 $clientId
55 ), OBJECT);
56 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
57 if (sizeof($query) > 0) {
58 $query = $wpdb->query(// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
59 $wpdb->prepare(
60 "UPDATE {$wpdb->prefix}convertpro_interactions
61 SET type = 'conversion', variation_id = %d
62 WHERE splittest_id = %d
63 AND client_id = %s",
64 $variationid,
65 $testId,
66 $clientId
67 )
68 );
69 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
70 }
71 }
72 }
73
74
75
76 // Modify the URL value in the response array
77 $response = array(
78 'url' => $permalink,
79 'id' => $testId,
80 'variationdid' => $variationid,
81 'fpath' => $fpath,
82 'message' => $message
83 );
84
85 // Encode the array as JSON and output it
86
87
88 wp_die();
89 }
90
91 function convertpro_interactions_report_html()
92 {
93
94
95 $id = isset($_GET['id']) ? intval(sanitize_text_field(wp_unslash($_GET['id']))) : 0;
96 $range = isset($_GET['range']) ? sanitize_text_field(wp_unslash(($_GET['range']))) : 7;
97
98 $repo = new Repo();
99 $results = $repo->getVariations($id);
100
101 ?>
102 <div class="convertpro-fullreport">
103 <table>
104 <tr>
105 <th><?php esc_html_e('Variation', 'convertpro'); ?></th>
106 <th><?php esc_html_e('Percentage', 'convertpro'); ?></th>
107 <th><?php esc_html_e('Views', 'convertpro'); ?></th>
108 <th><?php esc_html_e('Conversions', 'convertpro'); ?></th>
109 <th><?php esc_html_e('Conversion Rate', 'convertpro'); ?></th>
110 </tr>
111 <?php if ($results) {
112 foreach ($results as $result) {
113 // Output the table row for each variation
114 $conversion_count = convertpro_get_conversion($id, $result->id, $range);
115 $total_views = convertpro_get_views($id, $result->id, $range);
116
117 if ($total_views > 0) {
118 $conversion_rate = ($conversion_count / $total_views) * 100;
119 } else {
120 $conversion_rate = 0;
121 }
122
123 ?>
124 <tr>
125 <td><?php echo esc_html($result->name); ?></td>
126 <td><?php echo esc_html($result->percentage); ?></td>
127 <td><?php echo intval($total_views); ?></td>
128 <td><?php echo intval($conversion_count); ?></td>
129 <td><?php echo intval($conversion_rate); ?>%</td>
130
131 </tr>
132 <?php }
133 } else { ?>
134 <tr>
135 <td colspan="5"><?php esc_html_e('No data available', 'convertpro'); ?></td>
136 </tr>
137 <?php } ?>
138 </table>
139 </div>
140 <?php
141
142
143 }
144
145 function convertpro_interactions_report_ajax()
146 {
147 // Reporting is admin-only: enforce capability and nonce (CVE-2025-63031).
148 if (!current_user_can('manage_options')) {
149 wp_send_json_error(esc_html__('You are not allowed to access this resource.', 'convertpro'), 403);
150 }
151 check_ajax_referer('convertpro-report-nonce', 'nonce');
152
153 if (!isset($_GET['id']))
154 return false;
155 ob_start();
156 convertpro_interactions_report_html();
157 wp_send_json(ob_get_clean());
158 }
159 add_action('wp_ajax_convertpro_interactions_report_ajax', 'convertpro_interactions_report_ajax');
160 function convertpro_interactions_chart_query($id, $range = 7)
161 {
162 if (!$id) {
163 return false;
164 }
165
166
167
168 global $wpdb;
169 $table_name = $wpdb->prefix . 'convertpro_interactions';
170 $test_id = $id;
171 // Handle AJAX request to fetch data based on selected date range
172
173
174 // Calculate the start date based on the selected range
175
176 $query = "";
177 $placeholders = [];
178 $query .= "SELECT
179 v.name AS variation_name,
180 DATE_FORMAT(i.updated_at, '%%Y-%%m-%%d') AS interaction_date,
181 DATE_FORMAT(i.updated_at, '%%W') AS day_name,
182 COUNT(CASE WHEN i.type = 'view' THEN 1 END) AS daily_views,
183 COUNT(CASE WHEN i.type = 'conversion' THEN 1 END) AS daily_conversions,
184 COUNT(i.type) AS daily_total_interactions
185 FROM
186 {$wpdb->prefix}convertpro_variations AS v
187 INNER JOIN {$wpdb->prefix}convertpro_interactions AS i ON v.id = i.variation_id
188 INNER JOIN {$wpdb->prefix}convertpro AS s ON i.splittest_id = s.id
189 WHERE
190 i.splittest_id = %d";
191
192 $placeholders[] = $test_id;
193
194 if ($range != 'all') {
195 $query .= " AND i.updated_at <= NOW()
196 AND i.updated_at >= DATE_SUB(NOW(), INTERVAL %s DAY)";
197 $placeholders[] = intval($range);
198 // $placeholders[] = $endDate;
199 }
200
201 $query .= " GROUP BY
202 variation_name, interaction_date
203 ORDER BY
204 interaction_date ASC";
205
206 $query = $wpdb->prepare(// phpcs:ignore
207 $query, // phpcs:ignore
208 $placeholders
209 );
210
211 return $wpdb->get_results($query, ARRAY_A); // phpcs:ignore
212 }
213
214 function convertpro_get_chart_data()
215 {
216 // Reporting is admin-only: enforce capability and nonce (CVE-2025-63031).
217 if (!current_user_can('manage_options')) {
218 wp_send_json_error(esc_html__('You are not allowed to access this resource.', 'convertpro'), 403);
219 }
220 check_ajax_referer('convertpro-report-nonce', 'nonce');
221
222 if (isset($_GET['range'])) {
223 $test_id = isset($_GET['id']) ? sanitize_text_field(wp_unslash($_GET['id'])) : false;
224 // Handle AJAX request to fetch data based on selected date range
225 $range = isset($_GET['range']) ? sanitize_text_field(wp_unslash($_GET['range'])) : '';
226
227 $results = convertpro_interactions_chart_query($test_id, $range);
228 // var_dump($results);
229 if ($results) :
230 // Prepare the data for Chart.js
231 $labels = array_unique(array_merge(array_column($results, 'interaction_date'))); // or 'day_name'
232 sort($labels);
233
234 $datasets = array();
235 $bg_color_set = [
236 1 => '#3BCB38',
237 2 => '#3767FB',
238 3 => '#3767FB',
239 4 => '#EE2626'
240 ];
241 $i = 0;
242 foreach ($results as $row) {
243 $i++;
244 $variation_name = $row['variation_name'];
245 $date = $row['interaction_date']; // or $row['day_name']
246 $views = $row['daily_total_interactions'];
247 $conversions = $row['daily_conversions'];
248
249 // Create a dataset for views
250 $dataset_name = $variation_name;
251 if (!isset($datasets[$dataset_name])) {
252 $datasets[$dataset_name] = array(
253 'label' => $dataset_name,
254 'data' => array_fill_keys($labels, 0),
255 'backgroundColor' => [
256 $bg_color_set[$i]
257 ],
258 );
259 }
260 $datasets[$dataset_name]['data'][$date] = $views;
261 }
262
263 $datasets = array_values($datasets);
264 wp_send_json([
265 'labels' => $labels,
266 'datasets' => $datasets
267 ]);
268 else :
269 wp_send_json([
270 'labels' => 0,
271 'datasets' => 0
272 ]);
273
274 endif;
275 // Return the response as a JSON
276
277
278
279 }
280 }
281
282 // Hook the AJAX handler function to a WordPress AJAX action
283 add_action('wp_ajax_convertpro_get_chart_data', 'convertpro_get_chart_data');
284
285
286 function convertpro_get_views($test_id, $variation_id, $range = 7)
287 {
288 global $wpdb;
289 $table_name = $wpdb->prefix . 'convertpro_interactions';
290
291 $views_query = "";
292 $views_placeholders = [];
293 $views_query .= "SELECT COUNT(*) FROM {$table_name} WHERE splittest_id = %d AND variation_id = %d";
294 $views_placeholders[] = $test_id;
295 $views_placeholders[] = $variation_id;
296
297 if ($range != 'all') {
298
299 $views_query .= " AND updated_at <= NOW()
300 AND updated_at >= DATE_SUB(NOW(), INTERVAL %s DAY)";
301 $views_placeholders[] = intval($range);
302 }
303
304 $views_query = $wpdb->prepare(
305 $views_query,// phpcs:ignore
306 $views_placeholders
307 );
308
309 return $wpdb->get_var($views_query);// phpcs:ignore
310 }
311 function convertpro_get_conversion($test_id, $variation_id, $range = 7)
312 {
313
314 global $wpdb;
315 $table_name = $wpdb->prefix . 'convertpro_interactions';
316
317 $conversion_query = "";
318 $conversion_placeholders = [];
319 $conversion_query .= "SELECT COUNT(*) FROM {$table_name} WHERE type = 'conversion' AND splittest_id = %d AND variation_id = %d";
320 $conversion_placeholders[] = $test_id;
321 $conversion_placeholders[] = $variation_id;
322
323 if ($range != 'all') {
324
325 $conversion_query .= " AND updated_at <= NOW()
326 AND updated_at >= DATE_SUB(NOW(), INTERVAL %s DAY)";
327 $conversion_placeholders[] = intval($range);
328 }
329
330 $conversion_query = $wpdb->prepare(
331 $conversion_query,// phpcs:ignore
332 $conversion_placeholders
333 );
334
335
336 // Get the count of conversions
337 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
338 return $wpdb->get_var($conversion_query);// phpcs:ignore
339 }
340
341 // elements conversion here
342
343
344 function get_conversion_page_permalink_ajax()
345 {
346 global $wpdb;
347 $testeleId = isset($_COOKIE['convert_pro_ele_uid']) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_ele_uid'])) : '';
348 $variationid = isset($_COOKIE['convert_pro_variation_id_'.$testeleId]) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_variation_id_'.$testeleId])) : '';
349 $clientId = isset($_COOKIE['convert_pro_uid']) ? sanitize_text_field(wp_unslash($_COOKIE['convert_pro_uid'])) : '';
350 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
351 $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM " . $wpdb->prefix . "convertpro WHERE id = %d", $testeleId));
352 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
353 $pageeleId = '';
354 foreach ($results as $result) {
355 $pageeleId = isset($result->conversion_page_id) ? $result->conversion_page_id : '';
356 }
357
358 if ($pageeleId) {
359 $permalink = get_permalink($pageeleId);
360 $cpath = isset($_SERVER['HTTP_REFERER']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_REFERER'])) : '';
361 if ($permalink == $cpath) {
362 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
363 $query = $wpdb->get_results($wpdb->prepare(
364 "SELECT * FROM {$wpdb->prefix}convertpro_interactions
365 WHERE splittest_id = %d
366 AND client_id = %s",
367 $testeleId,
368 $clientId
369 ), OBJECT);
370 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
371 if (sizeof($query) > 0) {
372 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
373 $result = $query = $wpdb->query(
374 $wpdb->prepare(
375 "UPDATE {$wpdb->prefix}convertpro_interactions
376 SET type = 'conversion', variation_id = %d
377 WHERE splittest_id = %d
378 AND client_id = %s",
379 $variationid,
380 $testeleId,
381 $clientId
382 )
383 );
384 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
385 }
386 }
387 }
388
389 wp_die(); // Always include this at the end of your AJAX callback function
390 }
391
392 add_action('wp_ajax_get_conversion_page_permalink', 'get_conversion_page_permalink_ajax');
393 add_action('wp_ajax_nopriv_get_conversion_page_permalink', 'get_conversion_page_permalink_ajax');
394