PluginProbe
EasyTest – Simplify A/B Testing / trunk
EasyTest – Simplify A/B Testing vtrunk
1.0.4 1.0.3 trunk 1.0.1 1.0.2
convertpro / includes / Template / form-view.php

form-view.php in EasyTest – Simplify A/B Testing trunk, at includes/Template/form-view.php

333 lines 20.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit; // Called directly, nothing to do here.
5 }
6
7 // A save that was turned away comes back as a fresh page load, so what someone
8 // typed only survives if it was put aside first. Fill the form from that when
9 // there is one, otherwise from the saved test as before. The draft is tied to
10 // the test it was typed against, so a rejected new test cannot reappear on a
11 // different test's form and be saved over it.
12 if (is_object($test)) {
13 $convertpro_draft = convertpro_take_form_draft(isset($test->id) ? (int) $test->id : 0);
14
15 if ($convertpro_draft) {
16 $test->name = $convertpro_draft['name'];
17 $test->test_type = $convertpro_draft['test_type'];
18 $test->test_uri = $convertpro_draft['test_uri'];
19 $test->conversion_type = $convertpro_draft['conversion_type'];
20 $test->conversion_page_id = $convertpro_draft['conversion_page_id'];
21 $test->conversion_url = $convertpro_draft['conversion_url'];
22
23 if (!empty($convertpro_draft['variations'])) {
24 $test->variations = array();
25
26 foreach ($convertpro_draft['variations'] as $convertpro_row) {
27 $test->variations[] = (object) $convertpro_row;
28 }
29 }
30 }
31 }
32
33 if ($scope == "edit") {
34 $formUrl = admin_url('admin.php?page=convertpro-settings&scope=test&action=update&id=' . $test->id);
35 } else {
36 $formUrl = admin_url('admin.php?page=convertpro-settings&scope=test&action=store');
37 }
38 ?>
39 <div class="meassage">
40 <?php
41 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
42 $convertpro_message = isset($_GET['message']) ? sanitize_key(wp_unslash($_GET['message'])) : '';
43
44 $convertpro_notices = array(
45 'save_success' => array('success', __('Saved.', 'convertpro')),
46 'store_success' => array('success', __('Your test is ready. It starts running as soon as visitors arrive.', 'convertpro')),
47 'error_name_missing' => array('error', __('Give the test a name so you can recognise it later.', 'convertpro')),
48 'error_type_missing' => array('error', __('Pick whether you are testing whole pages or an element.', 'convertpro')),
49 'conversion_page_missing' => array('error', __('Choose the page that counts as a conversion, so we know when a visitor succeeded.', 'convertpro')),
50 'error_selector_missing' => array('error', __('Tell us what to watch for a click, such as a CSS class or part of the link address.', 'convertpro')),
51 'error_uri_missing' => array('error', __('Add a test URL. This is the link you share, and it decides which version each visitor sees.', 'convertpro')),
52 'error_test_page_invalid_chars' => array('error', __('The test URL cannot contain a slash. Use letters, numbers, dashes and underscores.', 'convertpro')),
53 'error_uri_taken_by_content' => array('error', __('You already have a page or post at that address. Pick a different test URL, or the real page would start redirecting people.', 'convertpro')),
54 'error_uri_taken_by_test' => array('error', __('Another test already uses that URL. Give this one its own address.', 'convertpro')),
55 'error_need_two_variations' => array('error', __('A test needs at least two versions to compare.', 'convertpro')),
56 'error_test_limit' => array('error', sprintf(
57 /* translators: %d: number of tests the free plugin runs at once. */
58 _n(
59 'EasyTest runs %d test at a time. Delete one you are done with to make room.',
60 'EasyTest runs %d tests at a time. Delete one you are done with to make room.',
61 convertpro_free_limit('tests'),
62 'convertpro'
63 ),
64 convertpro_free_limit('tests')
65 )),
66 'error_variation_limit' => array('error', sprintf(
67 /* translators: %d: number of versions allowed per test. */
68 _n('A test compares %d version.', 'A test compares %d versions — A against B.', convertpro_free_limit('variations'), 'convertpro'),
69 convertpro_free_limit('variations')
70 )),
71 'error_percentage_range' => array('error', __('Each share has to be between 1 and 100.', 'convertpro')),
72 'error_percentage_total' => array('error', __('The shares have to add up to 100. Right now they do not.', 'convertpro')),
73 'error_variation_page_missing' => array('error', __('Every version needs a page to send visitors to.', 'convertpro')),
74 'error_variation_page_duplicate' => array('error', __('Two versions point at the same page, so there would be nothing to compare. Pick a different page for one of them.', 'convertpro')),
75 'error_conversion_is_variation' => array('error', __('The conversion page is also one of the versions being tested, so everyone would convert the moment they arrive. Choose a different page.', 'convertpro')),
76 'error_variation_class_missing' => array('error', __('Every version needs a CSS class. Copy it into your page builder on the element you want to test.', 'convertpro')),
77 'error_variation_class_duplicate' => array('error', __('Two versions use the same CSS class. Each one needs its own.', 'convertpro')),
78 'error_variation_class_invalid' => array('error', __('A CSS class can only use letters, numbers, dashes and underscores — something like hero-version-a. Symbols such as * or a comma would match the wrong part of your page.', 'convertpro')),
79 'security_error' => array('error', __('That request could not be verified. Please try again.', 'convertpro')),
80 'error_update_data_missing' => array('error', __('Something was missing from that request. Please try again.', 'convertpro')),
81 'error_test_not_saved' => array('error', __('The test could not be saved. Nothing was lost — everything you filled in is still here, so try again.', 'convertpro')),
82 );
83
84 if (isset($convertpro_notices[$convertpro_message])) :
85 list($convertpro_notice_type, $convertpro_notice_text) = $convertpro_notices[$convertpro_message];
86 ?>
87 <div class="notice notice-<?php echo esc_attr($convertpro_notice_type); ?> is-dismissible">
88 <p><?php echo esc_html($convertpro_notice_text); ?></p>
89 </div>
90 <?php endif; ?>
91
92 <?php
93 // A cache that answers before WordPress does will hand every visitor the same
94 // version, and the test will look like it is running while measuring nothing.
95 // We cannot reach those caches from here, so say what needs adding by hand.
96 $convertpro_edge = convertpro_detect_edge_cache();
97
98 if ($convertpro_edge) : ?>
99 <div class="notice notice-warning">
100 <p>
101 <strong><?php
102 /* translators: %s: name of the caching service, e.g. Cloudflare. */
103 printf(esc_html__('%s is in front of this site.', 'convertpro'), esc_html($convertpro_edge['name']));
104 ?></strong>
105 <?php echo esc_html($convertpro_edge['how']); ?>
106 </p>
107 </div>
108 <?php endif; ?>
109
110 </div>
111
112 <script>
113 function copyToClipboard(inputElement) {
114 // Select the input field's text
115 inputElement.select();
116 inputElement.setSelectionRange(0, 99999); // For mobile devices
117
118 // Copy the text inside the input field
119 document.execCommand("copy");
120
121 // Optional: Show a message to the user that the text has been copied
122
123 }
124 </script>
125
126
127 <div class="convertpro-create-wrapper">
128 <div class="test-top-area">
129 <div class="back-test">
130 <a href="<?php echo esc_url(admin_url('admin.php?page=convertpro-settings')); ?>"><svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
131 <path d="M7.5 14.75L2.25 9.5M2.25 9.5L7.5 4.25M2.25 9.5L15.75 9.5" stroke="#080E13" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
132 </svg><?php echo esc_html__('Back to All Tests', 'convertpro') ?></a>
133 </div>
134 <div class="create-update-test">
135 <h4><?php echo esc_html($text); ?></h4>
136 </div>
137 </div>
138
139 <form method="post" action="<?php echo esc_url($formUrl); ?>" id="convertpro-test-form">
140 <input name="nonce" type="hidden" value="<?php echo esc_attr(wp_create_nonce('convertpro-nonce')); ?>" />
141 <div class="test-top-wrap">
142 <div class="test-name-wrap">
143 <label for="test-name"><?php esc_html_e('Test name', 'convertpro'); ?></label>
144 <p><?php echo esc_html__('Only you see this. Name it so you can tell it apart later.', 'convertpro') ?></p>
145 <input id="test-name" class="text-name" name="test-name" type="text" value="<?php echo (isset($test->name) ? esc_attr($test->name) : ""); ?>" placeholder="<?php esc_attr_e('Add a name', 'convertpro'); ?>" required />
146 </div>
147
148 <!-- /.test type select start-->
149 <div class="test-type-wrapper">
150 <div class="test-type-title">
151 <h2><?php esc_html_e('Test type', 'convertpro'); ?>:</h2>
152 </div>
153 <div class="test-type-select">
154 <select name="convertpro-test-type" style="width: 100%;">
155 <?php if (!isset($test->test_type)) { ?>
156 <option value="null" selected="selected"><?php esc_html_e('Please select test type ...', 'convertpro'); ?></option>
157 <?php } ?>
158 <option value="elements" <?php if (isset($test->test_type) && $test->test_type == "elements") {
159 echo ('selected="selected"');
160 } ?>><?php esc_html_e('Elements', 'convertpro'); ?></option>
161 <option value="pages" <?php if (isset($test->test_type) && $test->test_type == "pages") {
162 echo ('selected="selected"');
163 } ?>><?php esc_html_e('Page', 'convertpro'); ?></option>
164 </select>
165 </div>
166 </div>
167 <!-- /.test type select end -->
168
169 <!-- /.select page showing this content start -->
170 <div class="convertpro-uri-wrapper">
171 <div class="convertpro-headline" style="margin-top: 14px;">
172 <label><?php esc_html_e('Test URL', 'convertpro'); ?></label>
173 <p><?php echo esc_html__('Send people here and EasyTest passes them on to one of the versions below. Make up an address of your own — it cannot be a page you already have.', 'convertpro') ?></p>
174 </div>
175 <div class="url-identfier">
176 <span><?php echo esc_url(home_url('/')); ?></span>
177 <input name="test-uri" type="text" placeholder="<?php esc_attr_e('summer-offer', 'convertpro'); ?>" pattern="^([A-Za-z0-9\-_\/]*)$" title="<?php esc_attr_e('Letters, numbers, dashes and underscores only', 'convertpro'); ?>" value="<?php echo isset($test->test_uri) ? esc_attr($test->test_uri) : ''; ?>" />
178
179 </div>
180 <?php if (isset($test->test_uri) && '' !== $test->test_uri) : ?>
181 <div class="convertpro-pageview">
182 <a class="pageview-btn" id="test-page-url" target="_blank" href="<?php echo esc_url(home_url() . '/' . $test->test_uri . '/'); ?>"><?php esc_html_e('View Page', 'convertpro'); ?></a>
183 </div>
184
185 <?php
186 $convertpro_previews = array();
187
188 foreach ($test->variations as $convertpro_variation) {
189 if (!empty($convertpro_variation->page_id) && get_post($convertpro_variation->page_id)) {
190 $convertpro_previews[] = array(
191 'name' => $convertpro_variation->name,
192 'url' => get_permalink($convertpro_variation->page_id),
193 );
194 }
195 }
196 ?>
197
198 <?php if ($convertpro_previews) : ?>
199 <p class="convertpro-preview-note">
200 <?php esc_html_e('Opening the test URL puts you on one version and keeps you there, the same as it would any visitor. To look at the others, open them directly:', 'convertpro'); ?>
201 <?php foreach ($convertpro_previews as $convertpro_index => $convertpro_preview) : ?>
202 <a href="<?php echo esc_url($convertpro_preview['url']); ?>" target="_blank"><?php echo esc_html($convertpro_preview['name']); ?></a><?php echo $convertpro_index < count($convertpro_previews) - 1 ? ', ' : ''; ?>
203 <?php endforeach; ?>
204 </p>
205 <?php endif; ?>
206 <?php endif; ?>
207 </div>
208 </div>
209
210 <div class="convertpro-test-variations">
211 <div class="headline">
212 <div class="name"><?php esc_html_e('Version name', 'convertpro'); ?>:</div>
213 <div class="post"><?php esc_html_e('Page', 'convertpro'); ?>:</div>
214 <div class="percentage"><?php esc_html_e('Share', 'convertpro'); ?>:</div>
215 <div class="convertpro-class-gen"><?php esc_html_e('CSS class', 'convertpro'); ?>:</div>
216 <?php // Matches the row's actions column so every label sits over its own field. ?>
217 <div class="actions" aria-hidden="true"></div>
218
219 </div>
220 <div id="variations-container">
221 <?php
222 $i = 0;
223 foreach ($test->variations as $variation) {
224
225 ?>
226 <div class="convertpro-data-variation" data-variation-id="<?php echo esc_attr($variation->id); ?>">
227 <input type="hidden" name="test-variation[<?php echo esc_attr($i); ?>][id]" value="<?php echo esc_attr($variation->id); ?>">
228 <div class="name">
229 <input class="variation-name" name="test-variation[<?php echo esc_attr($i); ?>][name]" type="text" value="<?php echo esc_attr($variation->name); ?>" />
230 </div>
231 <div class="post">
232 <select name="test-variation[<?php echo esc_attr($i); ?>][page-id]">
233 <option value="null" disabled selected><?php echo esc_attr('Select Page'); ?></option>
234 <?php foreach ($pages as $page) { ?>
235 <option value="<?php echo esc_attr($page->ID); ?>" <?php if (isset($variation->page_id) && $variation->page_id == $page->ID) {
236 echo 'selected="selected"';
237 } ?>><?php echo esc_html(convertpro_page_option_label($page, $pages)); ?></option>
238
239 <?php } ?>
240 </select>
241 </div>
242
243 <div class="percentage">
244 <input name="test-variation[<?php echo esc_attr($i); ?>][percentage]" type="number" min="1" max="100" step="1" value="<?php echo esc_attr($variation->percentage); ?>" placeholder="<?php esc_attr_e('Share', 'convertpro'); ?>" required />
245 </div>
246 <div class="convertpro-class-gen">
247 <input name="test-variation[<?php echo esc_attr($i); ?>][customclass]" type="text" value="<?php echo esc_attr($variation->class_name); ?>" placeholder="<?php esc_attr_e('CSS class', 'convertpro'); ?>" />
248 <div class="copy-button" onclick="copyToClipboard(this.previousElementSibling)">Copy</div>
249 </div>
250
251 <div class="actions">
252 <div class="button-delete">&times;</div>
253 </div>
254 </div>
255
256
257 <?php $i++;
258 } ?>
259
260 </div>
261 <?php do_action('convertpro-variation-btn') ?>
262
263 <?php $convertpro_variation_cap = convertpro_free_limit('variations'); ?>
264 <?php if ($convertpro_variation_cap) : ?>
265 <p class="convertpro-variation-cap" style="display:none">
266 <?php
267 printf(
268 /* translators: %d: number of versions a test compares. */
269 esc_html(_n('A test compares %d version.', 'A test compares %d versions — A against B. Run a second test to try a third idea.', $convertpro_variation_cap, 'convertpro')),
270 (int) $convertpro_variation_cap
271 );
272 ?>
273 </p>
274 <?php endif; ?>
275
276 <?php
277 // Only the note for the current type starts visible; the script swaps
278 // them when the type changes.
279 $convertpro_current_type = isset($test->test_type) ? $test->test_type : '';
280 ?>
281 <p class="convertpro-variation-help convertpro-help-elements"<?php echo 'elements' === $convertpro_current_type ? '' : ' style="display:none"'; ?>>
282 <?php esc_html_e('Copy each class and paste it into the CSS class field of the matching element in your page builder. Visitors see one version and the rest stay hidden.', 'convertpro'); ?>
283 </p>
284 <p class="convertpro-variation-help convertpro-help-pages"<?php echo 'pages' === $convertpro_current_type ? '' : ' style="display:none"'; ?>>
285 <?php esc_html_e('The shares decide how traffic is divided and need to add up to 100. Once someone lands on a version, they keep seeing it.', 'convertpro'); ?>
286 </p>
287 </div>
288
289
290
291 <?php $convertpro_goal = (isset($test->conversion_type) && 'click' === $test->conversion_type) ? 'click' : 'page'; ?>
292
293 <div class="convertpro-goal-card">
294 <div class="test-conversion-page">
295 <h4><?php esc_html_e('What counts as a conversion', 'convertpro'); ?></h4>
296 <p><?php esc_html_e('How we know a visitor did the thing you are testing for.', 'convertpro'); ?></p>
297 </div>
298 <select name="test-conversion-type" id="test-conversion-type" style="width: 100%;">
299 <option value="page" <?php selected($convertpro_goal, 'page'); ?>><?php esc_html_e('Reaching a page on this site', 'convertpro'); ?></option>
300 <option value="click" <?php selected($convertpro_goal, 'click'); ?>><?php esc_html_e('Clicking a link or button', 'convertpro'); ?></option>
301 </select>
302
303 <div class="convertpro-conversion-page-wrapper convertpro-goal-field">
304 <label for="test-conversion-page"><?php esc_html_e('Which page', 'convertpro'); ?></label>
305 <p class="convertpro-goal-hint"><?php esc_html_e('Reaching this page counts as a conversion.', 'convertpro'); ?></p>
306 <select name="test-conversion-page" id="test-conversion-page" style="width: 100%;">
307 <option value="null" disabled selected><?php esc_html_e('Select a page', 'convertpro'); ?></option>
308 <?php
309 foreach ($pages as $page) { ?>
310 <option value="<?php echo esc_attr($page->ID); ?>" <?php if (isset($test->conversion_page_id) && $test->conversion_page_id == $page->ID) {
311 echo ('selected="selected"');
312 } ?>><?php echo esc_html(convertpro_page_option_label($page, $pages)); ?></option>
313 <?php } ?>
314 </select>
315 </div>
316
317 <div class="test-conversion-url-wrapper convertpro-goal-field">
318 <label for="test-conversion-selector"><?php esc_html_e('Which link or button', 'convertpro'); ?></label>
319 <p class="convertpro-goal-hint"><?php esc_html_e('Its CSS class or id, or part of the address it points to. Use this when the next step is somewhere we cannot see, like a checkout on another site. Separate several with commas.', 'convertpro'); ?></p>
320 <input type="text" name="test-conversion-selector" id="test-conversion-selector"
321 value="<?php echo isset($test->conversion_url) ? esc_attr($test->conversion_url) : ''; ?>"
322 placeholder="<?php esc_attr_e('.buy-now, #checkout-button, or checkout.example.com', 'convertpro'); ?>" />
323 </div>
324 </div>
325 <div class="submit-btn">
326 <input type="hidden" name="variation-count" value="<?php echo esc_attr($i); ?>" />
327 <input type="hidden" name="test-id" value="<?php echo (isset($test->id) ? esc_attr($test->id) : ''); ?>" />
328 <input class="test-button-save" type="submit" value="<?php esc_html_e('Save Test', 'convertpro'); ?>" />
329
330 </div>
331 </form>
332
333 </div>