Skip to content

Add Appsero tracking and update dependencies#514

Open
kzamanbd wants to merge 4 commits intodevelopfrom
chore/appsero-integration
Open

Add Appsero tracking and update dependencies#514
kzamanbd wants to merge 4 commits intodevelopfrom
chore/appsero-integration

Conversation

@kzamanbd
Copy link
Contributor

@kzamanbd kzamanbd commented Oct 29, 2025

Introduced Appsero client and updater dependencies for tracking and insights. Added a new Tracker class to handle plugin analytics and custom deactivation reasons. Updated Bootstrap to initialize Tracker and defined STOREGROWTH_VERSION constant in main plugin file.

Summary by CodeRabbit

  • New Features

    • Added analytics tracking to monitor plugin performance and usage patterns.
    • Enhanced deactivation form with custom feedback options for improved insights.
  • Requirements

    • Minimum PHP version requirement updated to 7.4 or higher.
    • Plugin version constant explicitly defined to ensure consistent versioning.
  • Chores

    • Added developer tooling for telemetry and updater integrations.

Introduced Appsero client and updater dependencies for tracking and insights. Added a new Tracker class to handle plugin analytics and custom deactivation reasons. Updated Bootstrap to initialize Tracker and defined STOREGROWTH_VERSION constant in main plugin file.
@kzamanbd kzamanbd self-assigned this Oct 29, 2025
@kzamanbd kzamanbd added Need Dev Review Label for developer review needs. Need Testing Label for qa testing labels Oct 29, 2025
@kzamanbd kzamanbd requested a review from mrabbani October 29, 2025 06:37
@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

📝 Walkthrough

Walkthrough

Adds Appsero-based telemetry: new Tracker class initializes an Appsero client, collects insights and dynamic plugin data, and provides custom deactivation reasons. Bootstrap is updated to instantiate the tracker. composer.json gains PHP >=7.4 and Appsero dev dependencies; plugin version constant STOREGROWTH_VERSION is defined.

Changes

Cohort / File(s) Summary
Dependency & Entry
composer.json, storegrowth-sales-booster.php
Add root require PHP >= 7.4 and require-dev entries for appsero/client ^2.0, appsero/updater ^2.3; define STOREGROWTH_VERSION if missing.
Tracker Implementation
includes/Tracker.php
New StorePulse\StoreGrowth\Tracker class: initializes Appsero client, fetches insights, registers dynamic extra data (product count, pro status, WooCommerce/version info), initializes plugin telemetry, and supplies custom deactivation reasons.
Bootstrap Integration
includes/Bootstrap.php
Add nullable public tracker property and instantiate Tracker in constructor.

Sequence Diagram

sequenceDiagram
    participant Bootstrap as Bootstrap
    participant Tracker as Tracker
    participant Appsero as Appsero Client

    Bootstrap->>Tracker: new Tracker()
    Tracker->>Tracker: __construct()
    Tracker->>Appsero: appsero_init_tracker_dokan() / instantiate Client
    Appsero-->>Tracker: return Client & Insights
    Tracker->>Appsero: register dynamic extras (products, pro status, versions)
    Tracker->>Appsero: initialize plugin telemetry
    Tracker->>Tracker: add filter for custom deactivation reasons
    Tracker-->>Bootstrap: tracker initialized
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • mrabbani

Poem

🐰 I hopped in soft with telemetry bright,
Tracking versions and products by night,
Appsero listens, reasons take flight,
A tiny tracker, steady and light,
Version 2.0.2 beams in moonlight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Add Appsero tracking and update dependencies' accurately describes the main changes: introducing Appsero integration for tracking and updating project dependencies.
Linked Issues check ✅ Passed The PR implements Appsero tracking functionality as required by issue #195, including the Tracker class, initialization in Bootstrap, dependencies in composer.json, and deactivation reason customization.
Out of Scope Changes check ✅ Passed All changes are directly related to the Appsero integration objective: tracker class implementation, dependency management, version constant definition, and Bootstrap initialization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/appsero-integration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
storegrowth-sales-booster.php (1)

33-38: Fix docblock label and guard against version drift.

  • The comment says “Define plugin FILE” but defines version. Update it.
  • Keep header Version and constant in sync to avoid drift.
-/**
- * Define plugin __FILE__
- */
+/**
+ * Define plugin version.
+ */
 if ( ! defined( 'STOREGROWTH_VERSION' ) ) {
     define( 'STOREGROWTH_VERSION', '2.0.2' );
 }

Optionally enforce sync in CI (fail if header Version ≠ STOREGROWTH_VERSION).

includes/Tracker.php (6)

14-20: Type and narrow visibility for $insights.

Use a typed, private property to prevent accidental external mutation.

-    /**
-     * Insights class
-     *
-     * @var Insights
-     */
-    public $insights = null;
+    /**
+     * Insights instance.
+     *
+     * @var Insights|null
+     */
+    private ?Insights $insights = null;

27-29: Rename init method and add return types.

Name is plugin-agnostic; add return type hints.

-    public function __construct() {
-        $this->appsero_init_tracker_dokan();
-    }
+    public function __construct() {
+        $this->appsero_init_tracker();
+    }
@@
-    public function appsero_init_tracker_dokan() {
+    public function appsero_init_tracker(): void {

Also applies to: 37-38


37-56: Defensive check: ensure constants are defined; optional early exit.

If STOREGROWTH_FILE isn’t defined for any reason, bail to avoid fatals.

-        $client = new Client( '512b82bc-5d26-46d3-9d14-e51642c15ff3', 'StoreGrowth', STOREGROWTH_FILE );
+        if ( ! defined( 'STOREGROWTH_FILE' ) ) {
+            return;
+        }
+        $client = new Client( '512b82bc-5d26-46d3-9d14-e51642c15ff3', 'StoreGrowth', STOREGROWTH_FILE );

Also confirm that the Appsero project key is intended to be public in VCS.


67-76: Fix docblock types and add method return type.

The filter receives/returns an array of arrays, not string[].

-     * @param string[] $reasons
-     * @param null|Client $client
+     * @param array       $reasons
+     * @param null|Client $client
@@
-    public function get_custom_deactivation_reasons( $reasons, $client = null ) {
+    public function get_custom_deactivation_reasons( array $reasons, $client = null ): array {

78-121: Merge default reasons, localize strings, and keep HTML sanitized.

  • Merge with existing $reasons instead of replacing.
  • Make user-visible strings translatable.
  • Rely on Appsero/WP sanitization for SVG; confirm it’s kses‑sanitized.
-        return [
+        return array_merge(
+            $reasons,
+            [
             [
                 'id'          => 'storegrowth-sales-booster-pro-is-expensive',
-                'text'        => 'StoreGrowth PRO is expensive ',
-                'placeholder' => 'We’ve discounts going all year round. Please copy & visit this link to instantly get 30% off your purchase: https://storegrowth.io/pricing/?utm_source=plugin&utm_medium=wp-admin&utm_campaign=storegrowth-sales-booster',
+                'text'        => __( 'StoreGrowth PRO is expensive', 'storegrowth-sales-booster' ),
+                'placeholder' => __( 'We’ve discounts going all year round. Please copy & visit this link to instantly get 30% off your purchase: https://storegrowth.io/pricing/?utm_source=plugin&utm_medium=wp-admin&utm_campaign=storegrowth-sales-booster', 'storegrowth-sales-booster' ),
                 'icon'        => '<svg height="23" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23"><path d="M11.5 0C17.9 0 23 5.1 23 11.5S17.9 23 11.5 23 0 17.9 0 11.5 5.1 0 11.5 0zm0 2C6.3 2 2 6.3 2 11.5S6.3 21 11.5 21s9.5-4.3 9.5-9.5S16.7 2 11.5 2zm.5 3v1.1c.5 0 .9.1 1.4.3.4.1.8.3 1.1.6.3.2.6.5.8.9.2.4.3.8.4 1.3h-2.3c0-.4-.1-.7-.4-1-.3-.3-.6-.4-.9-.4v2.5c.1 0 .3.1.4.1.1 0 .3.1.4.1.8.2 1.4.4 1.8.7s.7.6 1 .9c.2.3.3.6.4.9 0 .3.1.6.1.8 0 .2-.1.5-.2.8-.1.3-.3.6-.6.9-.3.3-.7.6-1.2.8s-1.2.4-2 .4V18h-1v-1.2c-1.2-.1-2.1-.4-2.8-1S7.1 14.4 7 13.2h2.3c0 .5.2 1 .5 1.3.3.3.7.5 1.2.6v-3c-.1 0-.1 0-.2-.1-.1 0-.2 0-.3-.1l-1.2-.3c-.4-.1-.7-.3-1-.5-.3-.2-.6-.5-.7-.8s-.3-.7-.3-1.1c0-.5.1-.9.3-1.3.2-.4.5-.7.8-.9.3-.3.7-.4 1.2-.6l1.4-.3V5h1zm0 7.4v2.7c.2 0 .4-.1.6-.1l.6-.3c.2-.1.3-.3.4-.4.1-.2.2-.4.2-.6 0-.4-.1-.7-.4-.8-.4-.2-.8-.4-1.4-.5zm-1-4.6c-.2 0-.4 0-.5.1-.2 0-.3.1-.5.2l-.3.3c-.1.2-.1.4-.1.6 0 .3.1.6.3.7.2.2.6.3 1.1.4V7.8z" fill-rule="evenodd" clip-rule="evenodd" fill="#3b86ff"/></svg>',
             ],
             [
                 'id'          => 'testing-debugging',
-                'text'        => 'I’m Testing or Debugging',
-                'placeholder' => 'If you’re temporarily deactivating, please let us know if we can help you in any way.',
+                'text'        => __( 'I’m Testing or Debugging', 'storegrowth-sales-booster' ),
+                'placeholder' => __( 'If you’re temporarily deactivating, please let us know if we can help you in any way.', 'storegrowth-sales-booster' ),
                 'icon'        => '<svg height="23" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23"><path d="M21 17.4c-.1-1.7-1.4-3-3-3.1v-1.2h-.3v1.2c-1.6.1-2.9 1.4-3 3.1h-1.2v.4h1.2c.1 1.7 1.4 3 3 3.1v1.2h.3v-1.2c1.6-.1 2.9-1.4 3-3.1h1.5v-.4H21zm-3.4 3.1c-1.4-.1-2.6-1.3-2.7-2.7h2.7v2.7zm0-3.1h-2.7c.1-1.5 1.2-2.6 2.7-2.7v2.7zm.4 3.1v-2.7h2.7c-.2 1.4-1.3 2.6-2.7 2.7zm0-3.1v-2.7c1.4.1 2.6 1.3 2.7 2.7H18zM16.2 4.9c0-.3.1-.5.4-.6.1 0 2.8-.5 3-2.9 0-.3.2-.5.5-.5s.5.3.4.5c-.2 3.1-3.7 3.8-3.8 3.8h-.1c-.1.1-.3-.1-.4-.3zM1.8 1.5c0-.2.2-.5.4-.5.3 0 .5.2.5.5.2 2.4 2.9 2.8 3 2.9.3 0 .4.3.4.6 0 .2-.2.4-.5.4h-.1c-.1-.1-3.5-.7-3.7-3.9zM18.4 9c.1 0 3.4.2 4 2.8 0 .1 0 .3-.1.4-.1.1-.2.2-.3.2h-.1c-.2 0-.4-.2-.5-.4-.5-1.9-3.1-2.1-3.2-2.1-.1 0-.2-.1-.3-.2-.1-.1-.1-.2-.1-.4.1-.1.3-.3.6-.3zM4.1 10s-2.7.2-3.2 2.1c-.1.2-.2.4-.5.4H.3c-.1 0-.2-.1-.3-.2v-.5C.7 9.2 3.9 9 4.1 9c.3 0 .5.2.5.5 0 .2-.2.5-.5.5zM9 2.6v-.3C8.9 1 10 0 11.2 0c1.2 0 2.3 1 2.3 2.3v.3c1.4.6 2.5 1.8 3.3 3.3V6l-.2.1c-1.5.8-3.1 1.2-4.9 1.2-2.5 0-4.7-.9-5.8-1.4l-.2-.1.1-.2c.7-1.4 1.9-2.4 3.2-3zM6.5 16.7c.1.3-.1.5-.3.6 0 0-2.6.7-2.9 3 0 .2-.2.4-.5.4h-.1c-.3 0-.4-.3-.4-.6.4-3 3.5-3.8 3.6-3.8H6c.2 0 .4.2.5.4zm11.3-4.3h-.2c.1-.7.2-1.4.2-2.1 0-1.3-.2-2.5-.7-3.7l-.1-.2-.2.1c-1.2.6-3.2 1-4.6 1.1h-.1v.1c-.4 1.5-.6 3.4-.8 5.2-.2-2.8-.5-5.1-.5-5.2v-.2C8.2 7.3 6 6.4 5.7 6.3l-.2-.1-.1.2c-.5 1.2-.8 2.5-.8 3.9 0 4.5 3 8.2 6.6 8.2.5 0 1-.1 1.4-.2a5.21 5.21 0 0010.4-.6c0-2.9-2.3-5.3-5.2-5.3z" fill-rule="evenodd" clip-rule="evenodd" fill="#3b86ff"/></svg>',
             ],
             // ...apply the same __(...) wrapping for all remaining 'text' and 'placeholder' fields...
-        ];
+        ] );

Please confirm Appsero escapes these fields with wp_kses before output. If not, we should sanitize here.


31-56: Consent and privacy notice check (GDPR/CCPA).

Confirm the integration shows explicit opt‑in and updates your privacy policy. If not, enable Appsero’s consent notice and add a settings toggle to opt‑out.

includes/Bootstrap.php (1)

29-36: Instantiate Tracker only in admin.

Telemetry/deactivation UI are admin concerns; avoid front-end cost.

-    public ?Tracker $tracker = null;
+    public ?Tracker $tracker = null;
@@
-    private function __construct() {
-        $this->tracker = new Tracker();
+    private function __construct() {
+        if ( is_admin() ) {
+            $this->tracker = new Tracker();
+        }
         add_action( 'woocommerce_loaded', [ $this, 'on_wc_loaded' ] );
         add_action( 'admin_notices', [ $this, 'show_notice_if_wc_is_not_active' ] );
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 168acaa and 19f3db1.

⛔ Files ignored due to path filters (1)
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • composer.json (1 hunks)
  • includes/Bootstrap.php (1 hunks)
  • includes/Tracker.php (1 hunks)
  • storegrowth-sales-booster.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
includes/Tracker.php (2)
includes/Bootstrap.php (2)
  • __construct (34-38)
  • has_pro (188-190)
storegrowth-sales-booster.php (1)
  • sp_store_growth (118-120)
includes/Bootstrap.php (1)
includes/Tracker.php (2)
  • Tracker (12-123)
  • __construct (27-29)
🔇 Additional comments (2)
includes/Tracker.php (1)

73-76: Slug comparison verified—no issue found.

The code at lines 73–76 is correct. STOREGROWTH_FILE is defined as the plugin's main file (storegrowth-sales-booster.php), and Appsero derives $client->slug from the plugin basename of that file, which is 'storegrowth-sales-booster'. The comparison will match and the deactivation reasons filter will execute as intended.

composer.json (1)

3-7: No action required—code already handles Appsero single-argument filter correctly.

The code registers the filter with 2-arg capacity, but the method signature makes $client optional with default null, and checks if it's null before using it. The implementation includes a comment explicitly addressing this: "return if old version of appsero client is loaded, where corresponding hooks provides only one argument". This defensive pattern already ensures compatibility with Appsero v2.x's single-argument filter—no verification or fix needed.

The side note about "minimum-stability": "dev" is accurate; switching to "stable" is a reasonable optional improvement to avoid pre-releases, but this is not critical.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
includes/Tracker.php (1)

80-119: Wrap user-facing deactivation strings with translation functions.

All text and placeholder strings in the deactivation reasons (lines 81–118) are hardcoded without translation function wrappers, making this flow non-localizable. Use __() for simple text or esc_html__() where appropriate for WordPress localization support.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@includes/Tracker.php` around lines 80 - 119, The deactivation-reasons array
in includes/Tracker.php contains hardcoded user-facing strings (e.g. entries
with ids like 'storegrowth-sales-booster-pro-is-expensive', 'testing-debugging',
'dont-need-anymore') — wrap all 'text' and 'placeholder' values with proper i18n
functions: use esc_html__() (or __() if raw HTML is intentionally allowed) for
visible text and esc_attr__() for attribute/placeholders, passing the plugin
text-domain (or the existing TEXT_DOMAIN constant) as the second arg; update
every array element that contains a literal string accordingly so these strings
are localizable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@composer.json`:
- Around line 26-31: The Appsero packages are required at runtime
(includes/Tracker.php instantiates Appsero\Client) but are currently in
"require-dev"; move "appsero/client" and "appsero/updater" from require-dev into
the top-level "require" in composer.json so they are installed in production,
and also fix the post-install/post-update script condition that currently reads
'[ $COMPOSER_DEV_MODE -eq 0 ] || "vendor/bin/mozart" compose' so Mozart runs
during production installs (either remove the conditional or invert it) to
ensure vendor/bin/mozart compose executes when --no-dev is used.

---

Nitpick comments:
In `@includes/Tracker.php`:
- Around line 80-119: The deactivation-reasons array in includes/Tracker.php
contains hardcoded user-facing strings (e.g. entries with ids like
'storegrowth-sales-booster-pro-is-expensive', 'testing-debugging',
'dont-need-anymore') — wrap all 'text' and 'placeholder' values with proper i18n
functions: use esc_html__() (or __() if raw HTML is intentionally allowed) for
visible text and esc_attr__() for attribute/placeholders, passing the plugin
text-domain (or the existing TEXT_DOMAIN constant) as the second arg; update
every array element that contains a literal string accordingly so these strings
are localizable.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19f3db1 and 2995ac9.

📒 Files selected for processing (3)
  • composer.json
  • includes/Tracker.php
  • storegrowth-sales-booster.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • storegrowth-sales-booster.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Need Dev Review Label for developer review needs. Need Testing Label for qa testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant