PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.4.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.4.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
← All changes | includes/Classes/Plugin_Usage_Tracker.php +159 -63 1.0.3 → 2.4.1 View file →
@@ -54,8 +54,18 @@
54 54 * Instace of Plugin_Usage_Tracker
55 55 * @var Plugin_Usage_Tracker
56 56 */
57 57 private static $_instance = null;
58 +
59 + private $disabled_wp_cron;
60 + private $enable_self_cron;
61 + private $require_optin;
62 + private $include_goodbye_form;
63 + private $marketing;
64 + private $options;
65 + private $item_id;
66 + private $notice_options;
67 +
58 68 /**
59 69 * Get Instance of Plugin_Usage_Tracker
60 70 * @return Plugin_Usage_Tracker
61 71 */
@@ -77,9 +87,27 @@
77 87 $this->plugin_name = basename($this->plugin_file, '.php');
78 88 $this->disabled_wp_cron = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true;
79 89 $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
80 90
81 - $this->event_hook = 'put_do_weekly_action';
91 + /**
92 + * The cron hook MUST be scoped to this plugin.
93 + *
94 + * Upstream WP Insights hardcodes the bare `put_do_weekly_action`, and
95 + * every plugin shipping a copy of this library hooks its own
96 + * do_tracking() onto that one name — on this dev site that was Better
97 + * Payment, Essential Addons, EasyJobs and NotificationX, all sharing a
98 + * SINGLE scheduled event. `deactivate_this_plugin()` then calls
99 + * wp_clear_scheduled_hook() on it, so deactivating Better Payment
100 + * silently unscheduled all FOUR plugins' telemetry, and reactivating BP
101 + * did not bring the others back (only their own activation hooks
102 + * re-schedule it). Observed, not theoretical.
103 + *
104 + * With a plugin-scoped name we schedule and clear only our own event.
105 + * We never schedule, clear, or listen on the shared one again.
106 + *
107 + * @since 2.3.2
108 + */
109 + $this->event_hook = 'better_payment_put_do_weekly_action';
82 110
83 111 $this->require_optin = isset($args['opt_in']) ? $args['opt_in'] : true;
84 112 $this->include_goodbye_form = isset($args['goodbye_form']) ? $args['goodbye_form'] : true;
85 113 $this->marketing = isset($args['email_marketing']) ? $args['email_marketing'] : true;
@@ -107,8 +135,36 @@
107 135 wp_schedule_event(time(), $this->recurrence, $this->event_hook);
108 136 }
109 137 }
110 138 /**
139 + * Ensure an opted-in site actually has our event scheduled.
140 + *
141 + * Two ways a consenting site ends up with no schedule, and neither is
142 + * self-correcting without this:
143 + *
144 + * 1. **The rename.** An install that opted in before 2.3.2 has consent
145 + * recorded and only the OLD shared event scheduled. Nothing re-runs
146 + * `activate_this_plugin()` or the opt-in click on upgrade, so tracking
147 + * would simply stop for every existing opted-in user — a silent
148 + * regression that looks exactly like "the tracker broke".
149 + * 2. **Collateral damage.** Another plugin sharing the old hook clears it
150 + * on ITS deactivation. That is the bug being fixed here, seen from the
151 + * other side; scoping our hook stops us doing it to others, and this
152 + * recovers us when someone does it to us.
153 + *
154 + * Cheap enough for every admin request: both reads are autoloaded options.
155 + *
156 + * @since 2.3.2
157 + * @return void
158 + */
159 + public function maybe_schedule_tracking()
160 + {
161 + if ($this->disabled_wp_cron || !$this->is_tracking_allowed()) {
162 + return;
163 + }
164 + $this->schedule_tracking();
165 + }
166 + /**
111 167 * Add the schedule event if the plugin is tracked.
112 168 *
113 169 * @return void
114 170 */
@@ -149,8 +205,21 @@
149 205 delete_option('wpins_deactivation_reason_' . $this->plugin_name);
150 206 delete_option('wpins_deactivation_details_' . $this->plugin_name);
151 207 /**
152 208 * Clear the event schedule.
209 + *
210 + * `$this->event_hook` is plugin-scoped (see the constructor), so this
211 + * now clears only our own event.
212 + *
213 + * The legacy shared `put_do_weekly_action` is deliberately NOT cleaned
214 + * up here, even on a site where Better Payment is the one that
215 + * scheduled it. There is no way to tell a BP-scheduled event from one
216 + * scheduled by Essential Addons / EasyJobs / NotificationX — the cron
217 + * entry records no owner — and clearing another plugin's telemetry
218 + * schedule is the exact bug this rename fixes. An orphaned event with
219 + * no listeners costs a hook dispatch and nothing else.
220 + *
221 + * @since 2.3.2
153 222 */
154 223 if (!$this->disabled_wp_cron) {
155 224 wp_clear_scheduled_hook($this->event_hook);
156 225 }
@@ -163,8 +232,9 @@
163 232 {
164 233 // $this->clicked();
165 234 add_action('wpdeveloper_notice_clicked_for_' . $this->plugin_name, array($this, 'clicked'));
166 235 add_action($this->event_hook, array($this, 'do_tracking'));
236 + $this->maybe_schedule_tracking();
167 237 // For Test
168 238 // add_action( 'admin_init', array( $this, 'force_tracking' ) );
169 239 // add_action( 'admin_notices', array( $this, 'notice' ) );
170 240 add_action('wpdeveloper_optin_notice_for_' . $this->plugin_name, array($this, 'notice'));
@@ -377,9 +447,18 @@
377 447 $body['marketing_method'] = $this->marketing;
378 448 $body['server'] = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '';
379 449
380 450 /**
381 - * Collect all active and inactive plugins
451 + * Collect active plugins.
452 + *
453 + * The full inventory of *inactive* plugins is deliberately not sent.
454 + * It carries little compatibility signal (dormant code does not run)
455 + * while being exactly the inventory an attacker would use to match a
456 + * site against known vulnerabilities. Only the count is reported, so
457 + * the "how much dormant code is installed" signal survives without
458 + * shipping the list itself.
459 + *
460 + * @since 2.3.2
382 461 */
383 462 if (!function_exists('get_plugins')) {
384 463 include ABSPATH . '/wp-admin/includes/plugin.php';
385 464 }
@@ -390,9 +469,9 @@
390 469 unset($plugins[$key]);
391 470 }
392 471 }
393 472 $body['active_plugins'] = $active_plugins;
394 - $body['inactive_plugins'] = $plugins;
473 + $body['inactive_plugins_count'] = count($plugins);
395 474
396 475 /**
397 476 * Text Direction.
398 477 */
@@ -415,28 +494,8 @@
415 494 $body['status'] = 'Active';
416 495 }
417 496
418 497 /**
419 - * Get our plugin options
420 - * @since 1.0.0
421 - */
422 - // $options = $this->options;
423 - // $plugin_options = array();
424 - // if( ! empty( $options ) && is_array( $options ) ) {
425 - // foreach( $options as $option ) {
426 - // $fields = get_option( $option );
427 - // // Check for permission to send this option
428 - // if( isset( $fields['wpins_registered_setting'] ) ) {
429 - // foreach( $fields as $key=>$value ) {
430 - // $plugin_options[$key] = $value;
431 - // }
432 - // }
433 - // }
434 - // }
435 - // $body['plugin_options'] = $this->options; // Returns array
436 - // $body['plugin_options_fields'] = $plugin_options; // Returns object
437 -
438 - /**
439 498 * Get active theme name and version
440 499 * @since 3.0.0
441 500 */
442 501 $theme = wp_get_theme();
@@ -445,8 +504,22 @@
445 504 }
446 505 if ($theme->Version) {
447 506 $body['theme_version'] = sanitize_text_field($theme->Version);
448 507 }
508 +
509 + /**
510 + * Better Payment's own feature usage — widgets, blocks, campaigns,
511 + * subscriptions and feature configuration. Aggregate counts only; see
512 + * Usage_Data for what is deliberately excluded (money, customers,
513 + * credentials).
514 + *
515 + * @since 2.3.2
516 + */
517 + $usage = Usage_Data::collect();
518 + if (!empty($usage)) {
519 + $body['optional_data'] = $usage;
520 + }
521 +
449 522 return $body;
450 523 }
451 524
452 525 /**
@@ -484,15 +557,23 @@
484 557 /**
485 558 * Send Initial Data to API
486 559 */
487 560 if ($site_id == false && $this->item_id !== false) {
488 - if (isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1')) {
489 - $country_request = wp_remote_get('http://ip-api.com/json/' . $_SERVER['REMOTE_ADDR'] . '?fields=country');
490 - if (!is_wp_error($country_request) && $country_request['response']['code'] == 200) {
491 - $ip_data = json_decode($country_request["body"]);
492 - $body['country'] = isset($ip_data->country) ? $ip_data->country : 'NOT SET';
493 - }
494 - }
561 + /**
562 + * Country is intentionally NOT resolved here.
563 + *
564 + * This used to POST the administrator's IP address to
565 + * http://ip-api.com over plain, unencrypted HTTP — a second
566 + * third-party recipient of personal data, sent in the clear.
567 + * ip-api.com offers no HTTPS on its free tier, so the lookup was
568 + * removed outright rather than re-pointed: the receiving endpoint
569 + * already sees the request IP and can resolve country server-side
570 + * without any extra party or any plaintext hop.
571 + *
572 + * Do not reintroduce a client-side geo lookup here.
573 + *
574 + * @since 2.3.2
575 + */
495 576
496 577 $body['plugin_slug'] = $this->plugin_name;
497 578 $body['url'] = $site_url;
498 579 $body['item_id'] = $this->item_id;
@@ -570,14 +651,14 @@
570 651 * WP_REMOTE_POST method responsible for send data to the API_URL
571 652 *
572 653 * @param array $data
573 654 * @param array $args
574 - * @return void
655 + * @return array|\WP_Error|null
575 656 */
576 657 protected function remote_post($data = array(), $args = array())
577 658 {
578 659 if (empty($data)) {
579 - return;
660 + return null;
580 661 }
581 662
582 663 $args = wp_parse_args($args, array(
583 664 'method' => 'POST',
@@ -648,8 +729,11 @@
648 729 'plugin' => $this->plugin_name,
649 730 'plugin_action' => 'no'
650 731 ));
651 732
733 + $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
734 + $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
735 +
652 736 // Decide on notice text
653 737 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-' . $this->plugin_name . '-collect">' . $this->notice_options['consent_button_text'] . '</a>';
654 738 $extra_notice_text = $this->notice_options['extra_notice'];
655 739
@@ -665,9 +749,9 @@
665 749 $output .= '</p>';
666 750 $output .= "<script type='text/javascript'>jQuery('.wpinsights-" . $this->plugin_name . "-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
667 751 $output .= '</div>';
668 752
669 - echo $output;
753 + printf( '%1$s', $output );
670 754 }
671 755 /**
672 756 * Set all notice options to customized notice.
673 757 *
@@ -677,11 +761,11 @@
677 761 */
678 762 public function set_notice_options($options = [])
679 763 {
680 764 $default_options = [
681 - 'consent_button_text' => esc_html__('What we collect.', 'disable-comments'),
682 - 'yes' => esc_html__('Sure, I\'d like to help', 'disable-comments'),
683 - 'no' => esc_html__('No Thanks.', 'disable-comments'),
765 + 'consent_button_text' => 'What we collect.',
766 + 'yes' => 'Sure, I\'d like to help',
767 + 'no' => 'No Thanks.',
684 768 ];
685 769 $options = wp_parse_args($options, $default_options);
686 770 $this->notice_options = $options;
687 771 }
@@ -690,27 +774,31 @@
690 774 * @return void
691 775 */
692 776 public function clicked()
693 777 {
694 - if (isset($_GET['plugin']) && trim($_GET['plugin']) === $this->plugin_name && isset($_GET['plugin_action'])) {
695 - if (isset($_GET['tab']) && $_GET['tab'] === 'plugin-information') {
778 + if ( isset( $_GET['_wpnonce'] ) && isset( $_GET['plugin'] ) && trim( $_GET['plugin'] ) === $this->plugin_name && isset( $_GET['plugin_action'] ) ) {
779 + if ( ! wp_verify_nonce( $_GET['_wpnonce'], '_wpnonce_optin_' . $this->plugin_name ) ) {
696 780 return;
697 781 }
698 - $plugin = sanitize_text_field($_GET['plugin']);
699 - $action = sanitize_text_field($_GET['plugin_action']);
700 - if ($action == 'yes') {
782 +
783 + if( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
784 + return;
785 + }
786 + $plugin = sanitize_text_field( $_GET['plugin'] );
787 + $action = sanitize_text_field( $_GET['plugin_action'] );
788 + if( $action == 'yes' ) {
701 789 $this->schedule_tracking();
702 - $this->set_is_tracking_allowed(true, $plugin);
703 - if ($this->do_tracking(true)) {
704 - $this->update_block_notice($plugin);
790 + $this->set_is_tracking_allowed( true, $plugin );
791 + if( $this->do_tracking( true ) ) {
792 + $this->update_block_notice( $plugin );
705 793 }
706 794 /**
707 795 * Redirect User To the Current URL, but without set query arguments.
708 796 */
709 - wp_safe_redirect($this->redirect_to());
797 + wp_safe_redirect( $this->redirect_to() );
710 798 } else {
711 - $this->set_is_tracking_allowed(false, $plugin);
712 - $this->update_block_notice($plugin);
799 + $this->set_is_tracking_allowed( false, $plugin );
800 + $this->update_block_notice( $plugin );
713 801 }
714 802 }
715 803 }
716 804 /**
@@ -737,14 +825,20 @@
737 825 */
738 826 public function deactivate_reasons_form_submit()
739 827 {
740 828 check_ajax_referer('wpins_deactivation_nonce', 'security');
829 + // Better Payment hardening (not upstream): a nonce is not a permission, so only a user
830 + // who can deactivate plugins may write these options — and what they write is stored as
831 + // plain text, never as whatever structure the request carried.
832 + if ( ! current_user_can( 'activate_plugins' ) ) {
833 + wp_send_json_error( null, 403 );
834 + }
741 835 if (isset($_POST['values'])) {
742 - $values = $_POST['values'];
836 + $values = is_scalar( $_POST['values'] ) ? sanitize_text_field( wp_unslash( $_POST['values'] ) ) : '';
743 837 update_option('wpins_deactivation_reason_' . $this->plugin_name, $values);
744 838 }
745 839 if (isset($_POST['details'])) {
746 - $details = sanitize_text_field($_POST['details']);
840 + $details = is_scalar( $_POST['details'] ) ? sanitize_text_field( wp_unslash( $_POST['details'] ) ) : '';
747 841 update_option('wpins_deactivation_details_' . $this->plugin_name, $details);
748 842 }
749 843 echo 'success';
750 844 wp_die();
@@ -777,22 +871,22 @@
777 871 */
778 872 public function deactivation_reasons()
779 873 {
780 874 $form = array();
781 - $form['heading'] = esc_html__('Sorry to see you go', 'disable-comments');
782 - $form['body'] = esc_html__('Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'disable-comments');
875 + $form['heading'] = esc_html__('Sorry to see you go', 'better-payment');
876 + $form['body'] = esc_html__('Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'better-payment');
783 877
784 878 $form['options'] = array(
785 - esc_html__('I no longer need the plugin', 'disable-comments'),
879 + esc_html__('I no longer need the plugin', 'better-payment'),
786 880 [
787 - 'label' => esc_html__('I found a better plugin', 'disable-comments'),
788 - 'extra_field' => esc_html__('Please share which plugin', 'disable-comments')
881 + 'label' => esc_html__('I found a better plugin', 'better-payment'),
882 + 'extra_field' => esc_html__('Please share which plugin', 'better-payment')
789 883 ],
790 - esc_html__("I couldn't get the plugin to work", 'disable-comments'),
791 - esc_html__('It\'s a temporary deactivation', 'disable-comments'),
884 + esc_html__("I couldn't get the plugin to work", 'better-payment'),
885 + esc_html__('It\'s a temporary deactivation', 'better-payment'),
792 886 [
793 - 'label' => esc_html__('Other', 'disable-comments'),
794 - 'extra_field' => esc_html__('Please share the reason', 'disable-comments'),
887 + 'label' => esc_html__('Other', 'better-payment'),
888 + 'extra_field' => esc_html__('Please share the reason', 'better-payment'),
795 889 'type' => 'textarea'
796 890 ]
797 891 );
798 892 return apply_filters('wpins_form_text_' . $this->plugin_name, $form);
@@ -833,9 +927,9 @@
833 927 }
834 928 $html .= '</ul></div><!-- .wpinsights-' . esc_attr( $class_plugin_name ) . '-goodbye-options -->';
835 929 }
836 930 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
837 - $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . esc_html__('Submitting form', 'disable-comments') . '</p>';
931 + $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . esc_html__('Submitting form', 'better-payment') . '</p>';
838 932
839 933 $wrapper_class = '.wpinsights-goodbye-form-wrapper-' . esc_attr( $class_plugin_name );
840 934
841 935 $styles = '';
@@ -846,9 +940,9 @@
846 940 $styles .= $wrapper_class . '{';
847 941 $styles .= 'position: relative; display: none;';
848 942 $styles .= '}';
849 943 $styles .= '.wpinsights-form-active-' . esc_attr( $class_plugin_name ) . ' ' . $wrapper_class . '{';
850 - $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
944 + $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center; z-index: 99999';
851 945 $styles .= '}';
852 946 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
853 947 $styles .= '.wpinsights-form-active-' . esc_attr( $class_plugin_name ) . ' .wpinsights-goodbye-form {';
854 948 $styles .= 'position: relative !important; width: 550px; max-width: 80%; background: #fff; box-shadow: 2px 8px 23px 3px rgba(0,0,0,.2); border-radius: 3px; white-space: normal; overflow: hidden; display: block; z-index: 999999;';
@@ -863,8 +957,10 @@
863 957 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
864 958 $styles .= '}';
865 959 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
866 960 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
961 + $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options input[type=radio] { border-color: #6B59EE; box-shadow: none; outline: 0; }';
962 + $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options input[type=radio]:checked::before { content: ""; border-radius: 50%; width: .6rem; height: .6rem; margin: 2.45px; background-color: #6B59EE; line-height: 1.14285714; outline: 0; }';
867 963 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
868 964 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, ' . $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {';
869 965 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
870 966 $styles .= '}';
@@ -872,11 +968,11 @@
872 968 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
873 969 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
874 970 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
875 971 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
876 - $styles .= 'background-color: #d30c5c; -webkit-border-radius: 3px; border-radius: 3px; color: #fff; line-height: 1; padding: 15px 20px; font-size: 13px;';
972 + $styles .= 'background-color: #6B59EE; -webkit-border-radius: 8px; border-radius: 8px; color: #fff; line-height: 1; padding: 12px 18px; font-size: 13px;';
877 973 $styles .= '}';
878 - $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
974 + $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpsp-put-deactivate-btn {';
879 975 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
880 976 $styles .= '}';
881 977 $styles .= $wrapper_class . ' .test {';
882 978 $styles .= '}';
@@ -891,9 +987,9 @@
891 987 // We'll send the user to this deactivation link when they've completed or dismissed the form
892 988 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_attr( $class_plugin_name ); ?>");
893 989 $('body').toggleClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
894 990 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
895 - $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").html('<?php echo $html; ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>" class="wpinsights-submit-btn" href="#"><?php esc_html_e('Submit and Deactivate', 'disable-comments'); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="' + url + '"><?php esc_html_e('Just Deactivate', 'disable-comments'); ?></a></div></div>');
991 + $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").html('<?php echo $html; ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>" class="wpinsights-submit-btn" href="#"><?php esc_html_e('Submit and Deactivate', 'better-payment'); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="' + url + '"><?php esc_html_e('Just Deactivate', 'better-payment'); ?></a></div></div>');
896 992 $('#wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>').on('click', function(e) {
897 993 // As soon as we click, the body of the form should disappear
898 994 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
899 995 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();