Plugin Directory

Changeset 3750893


Ignore:
Timestamp:
10/16/2026 05:56:02 PM (4 weeks ago)
Author:
vectorilo
Message:

Release 1.4

Location:
viswapp-chat-widget
Files:
18 added
4 edited

Legend:

Unmodified
Added
Removed
  • viswapp-chat-widget/trunk/includes/class-viswapp-widget-settings.php

    r3739838 r3750893  
    6565        ]);
    6666
     67        // Web forms ([viswapp_form] and the VisWapp form block)
     68        register_setting(self::GROUP, VisWapp_Forms::OPTION, [
     69            'type'              => 'array',
     70            'sanitize_callback' => [$this, 'sanitize_forms'],
     71            'default'           => VisWapp_Forms::defaults(),
     72        ]);
     73
    6774        // WooCommerce abandoned carts (the tab is only shown, and so only posted, with WooCommerce)
    6875        if (VisWapp_Woo_Carts::woo_active()) {
    … …  
    111118    }
    112119
     120    public function sanitize_forms($input): array
     121    {
     122        $input = is_array($input) ? wp_unslash($input) : [];
     123
     124        // A pasted embed code (a form's Share tab) fills both addresses
     125        $code = trim((string) ($input['embed'] ?? ''));
     126        if ($code !== '') {
     127            $parsed = VisWapp_Forms::parse_embed($code);
     128            if (empty($parsed['api'])) {
     129                add_settings_error(self::PAGE, 'forms_embed', __('That embed code has no data-api. Copy the “Embed on a page” code from VisWapp → Web Forms → Share.', 'viswapp-chat-widget'));
     130            }
     131            $input = array_merge($input, $parsed);
     132        }
     133
     134        $clean = VisWapp_Forms::sanitize($input);
     135        // Only when forms are being set up: the tab is posted with every save
     136        if (($code !== '' || $clean['api'] !== '' || $clean['src'] !== '') && !VisWapp_Forms::ready($clean)) {
     137            add_settings_error(self::PAGE, 'forms_api', __('Forms need the VisWapp API address: paste a form’s embed code, or set up the chat widget first.', 'viswapp-chat-widget'), 'warning');
     138        }
     139
     140        return $clean;
     141    }
     142
    113143    public function sanitize_login($input): array
    114144    {
    … …  
    201231        $wo       = $woo ? VisWapp_Woo_Carts::get() : [];
    202232        $wooReady = $woo && VisWapp_Woo_Carts::ready($wo);
     233        $fo       = VisWapp_Forms::get();
     234        $formsReady = VisWapp_Forms::ready($fo);
    203235        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only picks the open tab
    204236        $tab = isset($_GET['vw_tab']) ? sanitize_key(wp_unslash($_GET['vw_tab'])) : 'chat';
    205         if (!in_array($tab, $woo ? ['chat', 'login', 'woo'] : ['chat', 'login'], true)) {
     237        if (!in_array($tab, $woo ? ['chat', 'login', 'forms', 'woo'] : ['chat', 'login', 'forms'], true)) {
    206238            $tab = 'chat';
    207239        }
    … …  
    217249                    <?php esc_html_e('Login with WhatsApp', 'viswapp-chat-widget'); ?>
    218250                    <span class="vw-dot <?php echo esc_attr($loginReady ? 'is-on' : ''); ?>" aria-hidden="true"></span></a>
     251                <a href="<?php echo esc_url(add_query_arg('vw_tab', 'forms')); ?>" class="nav-tab <?php echo esc_attr($tab === 'forms' ? 'nav-tab-active' : ''); ?>" data-tab="forms">
     252                    <?php esc_html_e('Web forms', 'viswapp-chat-widget'); ?>
     253                    <span class="vw-dot <?php echo esc_attr($formsReady ? 'is-on' : ''); ?>" aria-hidden="true"></span></a>
    219254                <?php if ($woo) : ?>
    220255                <a href="<?php echo esc_url(add_query_arg('vw_tab', 'woo')); ?>" class="nav-tab <?php echo esc_attr($tab === 'woo' ? 'nav-tab-active' : ''); ?>" data-tab="woo">
    … …  
    448483
    449484                <?php
     485                $this->render_forms($fo, $formsReady, $tab === 'forms');
    450486                if ($woo) {
    451487                    $this->render_woo($wo, $wooReady, $tab === 'woo');
    … …  
    456492            </form>
    457493        </div>
     494        <?php
     495    }
     496
     497    /** Web forms tab: where forms load from, and how to add one */
     498    private function render_forms(array $fo, bool $ready, bool $open): void
     499    {
     500        $name = VisWapp_Forms::OPTION;
     501        ?>
     502            <div class="vw-pane" data-pane="forms" <?php echo esc_attr($open ? '' : 'hidden'); ?>>
     503                <div class="vw-status <?php echo esc_attr($ready ? 'is-on' : 'is-off'); ?>">
     504                    <?php if ($ready) : ?>
     505                        <strong><?php esc_html_e('Forms are ready to add to your pages.', 'viswapp-chat-widget'); ?></strong>
     506                        <span><?php echo esc_html((string) wp_parse_url(VisWapp_Forms::api($fo), PHP_URL_HOST)); ?></span>
     507                    <?php else : ?>
     508                        <strong><?php esc_html_e('Not set up yet.', 'viswapp-chat-widget'); ?></strong>
     509                        <span><?php esc_html_e('Paste a form’s embed code below and save.', 'viswapp-chat-widget'); ?></span>
     510                    <?php endif; ?>
     511                </div>
     512
     513                <div class="vw-card">
     514                    <h2><?php esc_html_e('1. Connect to VisWapp', 'viswapp-chat-widget'); ?></h2>
     515                    <p class="description">
     516                        <?php esc_html_e('Build lead forms in VisWapp → Web Forms. Every response becomes a contact, and can create a lead, send a WhatsApp message, add a Google Sheet row or call your webhook. If the chat widget is set up, forms already work: its API address is used.', 'viswapp-chat-widget'); ?>
     517                    </p>
     518                    <table class="form-table" role="presentation">
     519                        <tr>
     520                            <th scope="row"><label for="vw-forms-embed"><?php esc_html_e('Embed code', 'viswapp-chat-widget'); ?></label></th>
     521                            <td><textarea id="vw-forms-embed" class="large-text code" rows="3" name="<?php echo esc_attr($name); ?>[embed]" placeholder="<?php esc_attr_e('Paste the embed code from VisWapp → Web Forms → Share', 'viswapp-chat-widget'); ?>"></textarea>
     522                                <p class="description"><?php esc_html_e('Optional. Any form’s “Embed on a page” code from VisWapp → Web Forms → Share fills the two addresses below.', 'viswapp-chat-widget'); ?></p></td>
     523                        </tr>
     524                        <tr>
     525                            <th scope="row"><label for="vw-forms-api"><?php esc_html_e('API address', 'viswapp-chat-widget'); ?></label></th>
     526                            <td><input id="vw-forms-api" type="url" class="regular-text code" name="<?php echo esc_attr($name); ?>[api]" value="<?php echo esc_attr($fo['api']); ?>" placeholder="<?php echo esc_attr(VisWapp_Forms::api(array_merge($fo, ['api' => ''])) ?: 'https://…/api'); ?>">
     527                                <p class="description"><?php esc_html_e('The data-api of the embed code. Empty: the chat widget’s Data API address.', 'viswapp-chat-widget'); ?></p></td>
     528                        </tr>
     529                        <tr>
     530                            <th scope="row"><label for="vw-forms-src"><?php esc_html_e('Script address', 'viswapp-chat-widget'); ?></label></th>
     531                            <td><input id="vw-forms-src" type="url" class="regular-text code" name="<?php echo esc_attr($name); ?>[src]" value="<?php echo esc_attr($fo['src']); ?>" placeholder="<?php echo esc_attr(VisWapp_Forms::src(array_merge($fo, ['src' => '']))); ?>">
     532                                <p class="description"><?php esc_html_e('Where f.js loads from. Empty: next to the chat widget script. It is only added to pages that show a form.', 'viswapp-chat-widget'); ?></p></td>
     533                        </tr>
     534                    </table>
     535                </div>
     536
     537                <div class="vw-card">
     538                    <h2><?php esc_html_e('2. Add a form to a page', 'viswapp-chat-widget'); ?></h2>
     539                    <p class="description"><?php esc_html_e('In the block editor, add the “VisWapp form” block and paste the form key. Or use the shortcode anywhere shortcodes work:', 'viswapp-chat-widget'); ?></p>
     540                    <p><code>[viswapp_form id="vw_frm_…"]</code> — <?php esc_html_e('the form in the page', 'viswapp-chat-widget'); ?></p>
     541                    <p><code>[viswapp_form id="vw_frm_…" mode="popup" label="Get a quote" position="right"]</code> — <?php esc_html_e('a floating button that opens it', 'viswapp-chat-widget'); ?></p>
     542                    <p class="description">
     543                        <?php
     544                        printf(
     545                            /* translators: %s: this site's domain */
     546                            esc_html__('If a form limits where it can be embedded (Share → Where can it be embedded?), add %s there.', 'viswapp-chat-widget'),
     547                            '<code>' . esc_html((string) wp_parse_url(home_url(), PHP_URL_HOST)) . '</code>'
     548                        );
     549                        ?>
     550                    </p>
     551                </div>
     552
     553                <p class="vw-foot">
     554                    <?php esc_html_e('Privacy: form answers are sent straight to VisWapp and are not stored in WordPress. Page caching: forms work on cached pages.', 'viswapp-chat-widget'); ?>
     555                </p>
     556            </div>
    458557        <?php
    459558    }
  • viswapp-chat-widget/trunk/readme.txt

    r3739838 r3750893  
    11=== VisWapp Chat Widget ===
    22Contributors: vectorilo
    3 Tags: chat, live chat, whatsapp, whatsapp login, abandoned cart
     3Tags: chat, whatsapp, lead form, whatsapp login, abandoned cart
    44Requires at least: 5.8
    55Tested up to: 7.1
    66Requires PHP: 7.4
    7 Stable tag: 1.3.1
     7Stable tag: 1.4.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    1010
    11 VisWapp chat widget, one-tap "Continue with WhatsApp" login and WhatsApp reminders for abandoned WooCommerce carts.
     11VisWapp chat widget, lead forms, one-tap "Continue with WhatsApp" login and WhatsApp reminders for abandoned WooCommerce carts.
    1212
    1313== Description ==
    … …  
    2121* When an identified customer logs out, their chat is cleared from that browser.
    2222* Login with WhatsApp: a "Continue with WhatsApp" button on the WordPress login page, WooCommerce My account and checkout, or anywhere with the [viswapp_login] shortcode. WhatsApp opens with a message ready; the customer taps send and is logged in. Existing users are matched by WhatsApp number or WooCommerce billing phone; new numbers can get an account automatically.
     23* Lead forms: add a form from VisWapp → Web Forms to any page with the "VisWapp form" block or the [viswapp_form] shortcode, in the page or as a popup button. Every response becomes a VisWapp contact and can create a lead, send a WhatsApp message, add a Google Sheet row or call your webhook.
    2324* Abandoned cart recovery (WooCommerce): carts are sent to VisWapp once the shopper's phone or email is known, and VisWapp sends a WhatsApp reminder with a link that restores the cart and opens checkout.
    2425
    … …  
    43444. In VisWapp, click Go live when you are ready (test mode works on your allowed domains too).
    4445
     46To add a lead form:
     47
     481. In VisWapp, build and publish a form under Web Forms, and copy its form key (vw_frm_…) from the Share tab.
     492. In WordPress, add the "VisWapp form" block to a page and paste the key, or use the shortcode [viswapp_form id="vw_frm_…"].
     503. Forms use the chat widget's API address. Without the chat widget, paste the form's "Embed on a page" code in Settings → VisWapp → Web forms.
     51
    4552To turn on abandoned cart recovery (WooCommerce):
    4653
    … …  
    6976    }, 10, 2 );
    7077
     78== Lead forms ==
     79
     80The block and the shortcode print a placeholder that the VisWapp forms script (f.js) fills in. The script is added only to pages that show a form, and each form is drawn in its own isolated area, so your theme's styles don't change it.
     81
     82    [viswapp_form id="vw_frm_…"]
     83    [viswapp_form id="vw_frm_…" mode="popup" label="Get a quote" position="left"]
     84
     85* id: the form key from VisWapp → Web Forms → Share (required).
     86* mode: inline (the form in the page, default) or popup (a floating button in the form's colour that opens it).
     87* label and position: the popup button's text (default: the form title) and corner (right or left).
     88
     89The form's look, questions, thank-you message and what happens with each response are all set in VisWapp; changes show on your site straight away. Responses record the page they came from and its UTM tags.
     90
     91Developers can change the printed markup with the viswapp_form_markup filter ($html, $key, $atts); its output is checked against an allow-list.
     92
    7193== External services ==
    7294
    … …  
    7597* Chat widget. On the pages you choose, visitors' browsers load the widget script from the address in your install snippet (by default https://cdn.viswapp.com/w.js) and talk to your VisWapp Data API address. The widget sends the page address and referrer, the page and browser language, basic device details (browser, screen size, time zone), UTM parameters and what the visitor types in the chat. With "Identify logged-in users" on, the logged-in user's ID, name, email and phone number are sent, signed on your server.
    7698* Login with WhatsApp. On the login, My account and checkout pages (and wherever you place [viswapp_login]) browsers load login.js from your VisWapp sign-in address. When a customer signs in, your server sends the one-time code and your client credentials to that address (/oauth/token) and receives the customer's verified WhatsApp number.
     99* Lead forms. On pages that show a [viswapp_form] shortcode or a VisWapp form block, browsers load f.js (by default from next to the chat widget script, e.g. https://cdn.viswapp.com/f.js) and read the form from your VisWapp API address. When a visitor submits, their answers, the page address and referrer and the page's UTM parameters are sent to VisWapp. In the block editor, the form's title is read from the same address for the preview.
    77100* Abandoned cart recovery (WooCommerce). Once a shopper's phone number or email is known, your server sends the cart (products, quantities, prices, totals, cart link) and the shopper's name, phone number, email, country and marketing consent to your VisWapp delivery URL, and again when the cart changes or the order is placed.
    78101
    … …  
    82105== Privacy ==
    83106
     107Lead form answers (for example name, phone number and email) are sent straight from the visitor's browser to VisWapp and are not stored in WordPress. Mention your forms in your privacy policy, and add a consent checkbox to forms that lead to WhatsApp messages.
     108
    84109With abandoned cart recovery on, cart contents (products, quantities, prices, totals) and the shopper's name, phone number and email address are sent to VisWapp so WhatsApp cart reminders can be sent. The plugin adds suggested text to Settings → Privacy → Policy guide; add it to your privacy policy. Use the consent checkbox where the law requires opt-in for marketing messages. Cart links are stored on your site for 14 days.
    85110
    86111== Frequently Asked Questions ==
     112
     113= How do I add a lead form? =
     114
     115Add the "VisWapp form" block and paste the form key (vw_frm_…) from VisWapp → Web Forms → Share, or use [viswapp_form id="vw_frm_…"]. Set mode="popup" for a floating button instead. The form must be published in VisWapp; until then visitors see that it is not accepting responses.
     116
     117= The form says it is not available on this website =
     118
     119The form only allows some websites. In VisWapp → Web Forms → Share → Where can it be embedded?, add your site's domain.
    87120
    88121= Can I put the WhatsApp login button on my own page? =
    … …  
    138171= What happens when I delete the plugin? =
    139172
    140 Its settings, the saved Identity secret, the WhatsApp Login and abandoned-cart secrets, and saved cart links are removed from WordPress. Chats, contacts and carts stay in VisWapp.
     173Its settings (including the Web forms tab), the saved Identity secret, the WhatsApp Login and abandoned-cart secrets, and saved cart links are removed from WordPress. Chats, contacts and carts stay in VisWapp.
    141174
    142175== Screenshots ==
    … …  
    1481815. Abandoned cart recovery settings for WooCommerce and The WhatsApp reminder with a link that restores the cart.
    149182
    150 
    151183== Changelog ==
     184
     185= 1.4.0 =
     186* Lead forms from VisWapp → Web Forms: the "VisWapp form" block (with a preview of the form in the editor) and the [viswapp_form] shortcode, in the page or as a popup button. The forms script loads only on pages with a form.
     187* Settings → VisWapp → Web forms tab: paste a form's embed code, or let forms use the chat widget's API address.
    152188
    153189= 1.3.1 =
  • viswapp-chat-widget/trunk/uninstall.php

    r3739838 r3750893  
    33 * Deleting the plugin removes its settings, the saved Identity secret, the
    44 * WhatsApp Login client secret, the abandoned-cart settings and webhook
    5  * secret, and the saved cart-recovery links. Users keep their viswapp_phone
     5 * secret, the web forms settings, and the saved cart-recovery links. Users keep their viswapp_phone
    66 * meta. Chats, contacts and carts stay in VisWapp.
    77 */
    … …  
    2121    delete_option('viswapp_woo_carts');
    2222    delete_option('viswapp_woo_carts_secret');
     23    delete_option('viswapp_forms_settings');
    2324
    2425    // Cart-recovery links and rate-limit counters (transients stored in the options table)
  • viswapp-chat-widget/trunk/viswapp-chat-widget.php

    r3739838 r3750893  
    33 * Plugin Name:       VisWapp Chat Widget
    44 * Plugin URI:        https://viswapp.com
    5  * Description:       Login with WhatsApp (one tap on wp-login, WooCommerce and the [viswapp_login] shortcode), the VisWapp website chat widget and WooCommerce abandoned cart reminders on WhatsApp. Settings → VisWapp.
    6  * Version:           1.3.1
     5 * Description:       Login with WhatsApp (one tap on wp-login, WooCommerce and the [viswapp_login] shortcode), the VisWapp website chat widget, VisWapp lead forms (the [viswapp_form] shortcode and block) and WooCommerce abandoned cart reminders on WhatsApp. Settings → VisWapp.
     6 * Version:           1.4.0
    77 * Requires at least: 5.8
    88 * Requires PHP:      7.4
    … …  
    1818}
    1919
    20 define('VISWAPP_WIDGET_VERSION', '1.3.1');
     20define('VISWAPP_WIDGET_VERSION', '1.4.0');
    2121define('VISWAPP_WIDGET_FILE', __FILE__);
    2222define('VISWAPP_WIDGET_DIR', plugin_dir_path(__FILE__));
    … …  
    2828require_once VISWAPP_WIDGET_DIR . 'includes/class-viswapp-login.php';
    2929require_once VISWAPP_WIDGET_DIR . 'includes/class-viswapp-woo-carts.php';
     30require_once VISWAPP_WIDGET_DIR . 'includes/class-viswapp-forms.php';
    3031
    3132// The Identity secret is read only when signing, so it isn't loaded on every request
    … …  
    3637    add_option(VisWapp_Login::OPTION, VisWapp_Login::defaults());
    3738    VisWapp_Woo_Carts::install();
     39    add_option(VisWapp_Forms::OPTION, VisWapp_Forms::defaults());
    3840});
    3941
    … …  
    4547    (new VisWapp_Login())->register();
    4648    (new VisWapp_Woo_Carts())->register(); // does nothing without WooCommerce
     49    (new VisWapp_Forms())->register();
    4750});
    4851
Note: See TracChangeset for help on using the changeset viewer.