Product Updates Statnive Plugin · Parhum Khoshbakht

248 Tests, 22 Release Gates, Zero Shortcuts: How We Ship Statnive

Most WordPress plugins run a linter and call it a day. Statnive passes through 5 layers of automated verification — from pre-commit hooks to WordPress.org compliance gates — before any release ships. Here is exactly what we check and why. (Numbers as of v0.4.9.)

Before You Install Any Plugin, You Are Trusting Someone Else’s Code

Every WordPress plugin you activate gets full access to your database, your admin panel, and your visitors’ data. Most plugin pages show a star rating and a “Last updated” date. That is not enough information to make a trust decision.

We built Statnive to be the analytics plugin we would trust on our own sites. This post walks through the exact quality pipeline every line of Statnive code passes through before it reaches your WordPress installation. No vague claims — specific checks, real numbers, and honest caveats about what automated testing can and cannot catch.

The headline numbers (as of v0.4.9): 248 PHP unit tests, 31 WordPress.org compliance sections, 22 specialized release gates (5 static + 17 compliance grep), 3 PHP version targets, and a 5KB tracker size budget enforced on every single build.

Layer 1: The Pre-Commit Hook — Nothing Enters the Repository Unchecked

Before code even enters our Git repository, a pre-commit hook runs two checks on every staged file:

For PHP changes:

  1. PHPCS (PHP CodeSniffer) validates staged files against the WordPress Coding Standards — the same ruleset WordPress core uses. This catches insecure output escaping, missing sanitization, and non-standard code patterns.
  2. PHPUnit runs the full unit test suite. All 248 tests must pass. A single failure blocks the commit.

For TypeScript/JavaScript changes:

  1. Vitest runs all React component tests. The dashboard UI cannot regress without being caught here.

The pre-commit hook is intentionally fast — it runs in under 5 seconds on a developer machine. The goal is not to replace CI, but to catch the most common mistakes before they waste a round-trip to GitHub. In practice, this single gate catches roughly 80% of issues before they ever leave the developer’s laptop.

Layer 2: Continuous Integration — 6 Parallel Jobs on Every Push

Every push to our development or main branch, and every pull request, triggers a GitHub Actions CI pipeline with 6 parallel jobs:

JobWhat It ChecksWhy It Matters
Lint (PHP 8.2, 8.3, 8.4)PHPCS + PHPStan level 6Coding standards and static type safety across 3 PHP versions
Unit Tests (PHP 8.2, 8.3, 8.4)PHPUnit suiteLogic correctness across 3 PHP versions
Minimum Floor Smoke (PHP 8.0)Syntax lint + autoloader bootProves the plugin loads on the declared minimum PHP version
Tracker BuildVite build + gzip size checkEnforces the 5KB gzipped budget on the analytics tracker

Why 4 PHP versions?

WordPress sites run on PHP 8.0 through 8.4 in the real world. A function that works on PHP 8.4 might behave differently on PHP 8.0 — default parameter values, type coercion rules, and deprecated features all vary across versions. We test on the three versions where our full test suite runs (8.2, 8.3, 8.4) and separately verify that the production code at least parses and boots on PHP 8.0 — the declared minimum in our plugin header.

The 5KB tracker budget

The JavaScript tracker that collects pageviews on your site has a hard size limit: 5,120 bytes gzipped. Every build measures the output and fails the pipeline if the tracker exceeds that budget. This is not arbitrary — our performance benchmark showed that tracker size directly correlates with LCP impact. The budget forces us to keep the critical path minimal and defer non-essential features to an async secondary script.

# From our CI workflow — the tracker size check
- name: Verify tracker size
  run: |
    MAX_SIZE=5120  # 5KB in bytes
    GZIP_SIZE=$(gzip -c public/tracker/statnive.js | wc -c)
    if [ "$GZIP_SIZE" -gt "$MAX_SIZE" ]; then
      echo "::error::Tracker size (${GZIP_SIZE}B) exceeds limit (${MAX_SIZE}B)"
      exit 1
    fi

PHPStan at level 6

PHPStan is a static analysis tool that finds bugs without running the code. Level 6 (out of 10) catches type mismatches, undefined variables, incorrect return types, and dead code paths. We run it with the phpstan-wordpress extension, which understands WordPress hook signatures, filter return types, and $wpdb method contracts. Combined with $wpdb->prepare() enforcement, this is our primary defense against SQL injection — the static analyzer flags any query that concatenates user input instead of using prepared statements.

Layer 3: WordPress.org Compliance — 22 Release Gates

This is where Statnive’s quality pipeline diverges from most WordPress plugins. Beyond standard linting and testing, we run 22 purpose-built release gates (5 static + 17 compliance grep) that enforce WordPress.org plugin guidelines — the same rules the review team checks manually during submission.

Most plugin developers discover these rules when their submission gets rejected. We automated them so violations are caught on every commit:

Security gates

ABSPATH Guards — Every PHP file must check defined('ABSPATH') before executing. This prevents direct access to plugin files via URL, which could leak server paths or execute code outside WordPress context. Our gate scans every .php file in the source tree and fails if any file is missing the guard.

Forbidden Patterns — An automated scan blocks dangerous PHP functions that WordPress.org explicitly rejects: eval(), exec(), shell_exec(), system(), passthru(), and curl_init(). It also catches PHP short tags, raw json_encode() (must use wp_json_encode()), and hardcoded wp-content paths.

WP API Compliance — Checks that all scripts and stylesheets use WordPress’s enqueue system instead of hardcoded <script> or <link> tags. Also scans for unsanitized superglobal access ($_GET, $_POST, $_REQUEST) — one of the top reasons WordPress.org rejects plugin submissions.

Integrity gates

Readme & Version Consistency — The plugin version must match in three places: readme.txt Stable tag, statnive.php header, and the STATNIVE_VERSION PHP constant. A mismatch means WordPress would show the wrong version number — confusing for users and a red flag for reviewers. This gate also validates tag count (max 5), short description length (max 150 characters), LICENSE file presence, and the External Services disclosure section.

Distribution ZIP Validation — Builds the actual ZIP file that would be uploaded to WordPress.org, then validates its contents. Required files must be present (statnive.php, readme.txt, LICENSE, src/Plugin.php, unminified tracker source). Forbidden files must be absent (node_modules/, .git/, composer.json, tests/, phpunit, config files). ZIP size must stay under 25MB.

Header Parity — Validates all 11 required plugin header fields are present and consistent. Checks that the Tested up to WordPress version is within 2 minor releases of the current stable — a stale value signals an unmaintained plugin and can affect WordPress.org search ranking.

Architecture gates

Architecture Blockers — Scans for patterns that indicate policy violations: phone-home HTTP calls inside activation hooks (users should not see network requests when they activate a plugin), custom auto-updater hooks (WordPress.org handles updates), and bundled MaxMind GeoIP databases (users must provide their own license key).

Freemium Boundary — The free WordPress.org version must not contain license-gating code. This gate scans for patterns like isPro(), checkLicense(), trial_expires, and premium_only — ensuring the .org build is genuinely free, not a crippled trial.

External Services Audit — Extracts every https:// domain referenced in the PHP source code, then verifies each one is documented in the readme.txt External Services section. Any undocumented external connection fails the build. This is how we guarantee transparency about where your data flows.

Get Statnive: Code You Can Trust

Every check described in this post runs automatically on every change. No human has to remember to run the security scan or check version consistency — the pipeline enforces it. Install Statnive from WordPress.org and see the result: fast, private analytics on your own server.

Layer 4: WordPress Plugin Check — Stricter Than Required

The Plugin Check (PCP) is an official tool from the WordPress.org team that runs the same automated checks the review team uses. Most plugins configure PCP to fail only on errors.

Statnive fails on both errors AND warnings.

This is a deliberate choice. PCP warnings often flag legitimate issues — deprecated function usage, accessibility gaps, performance concerns — that do not technically block submission but degrade plugin quality over time. By treating warnings as errors, we catch issues that other plugins ship with.

The PCP gate runs on the built distribution directory (not the source tree), using PHP 8.0 — the declared minimum. This means we are testing exactly what users would install, on the oldest PHP version we support.

Layer 5: The Release Gate — 31 Sections Before Any Version Ships

Before a release, the full gate combines everything above into a single pass-or-fail decision:

Static test gates (must all pass):

GateCheckTool
S-1WordPress Coding StandardsPHPCS
S-2Static type analysisPHPStan level 6
S-3PHP unit + integration testsPHPUnit
S-4React component testsVitest
S-5Official Plugin CheckPCP (errors + warnings)

Compliance grep gates (17 automated pattern checks):

GatesWhat They Enforce
C-1ABSPATH guards on every PHP file
C-2License file validation
C-3, C-4No phone-home on activation, no hidden paywalls
C-5Readme structure, version parity, external services disclosure
C-6No unsanitized superglobal access
C-7No bundled GeoIP databases
C-8, C-9, C-10No custom updater, no bundled core libraries, no external CDN
C-11, C-12Cron cleanup on deactivation, uninstall function present
C-13SVN assets directory structure
C-14ZIP integrity and size
C-15Database table creation follows dbDelta format
C-16All user-facing strings are internationalized
C-17WordPress Privacy API hooks registered

Beyond the automated gates, each release includes a manual review covering performance budgets, browser compatibility, accessibility (WCAG 2.2 AA), admin UX clarity, upgrade/migration safety, and failure handling. The full checklist spans 31 sections across 3 severity levels:

  • CRITICAL — automated gates that block the release pipeline
  • RELEASE BLOCKER — manual checks that must pass before tagging a version
  • QUALITY GATE — standards we hold ourselves to, reviewed but advisory

Security and Privacy: Verified by the Pipeline, Not Just Promised

Many analytics plugins list security and privacy features on their marketing page. We prefer to show how those promises are mechanically enforced:

All SQL queries use prepared statements. PHPStan’s WordPress extension flags any $wpdb method call that concatenates user input instead of using $wpdb->prepare(). This is caught at static analysis time — before the code ever runs.

No cookies, localStorage, or fingerprinting. The compliance gates scan for cookie-setting functions and browser storage APIs. The unit test suite verifies that the tracker payload contains only hashed, non-reversible visitor identifiers.

Daily rotating salts. The same visitor produces a different hash each day, preventing cross-day tracking. This is covered by dedicated unit tests that verify hash uniqueness across salt rotations.

HMAC signatures on tracker payloads. Every pageview hit is signed with a server-generated key. The signature verification is tested in the unit suite — invalid or tampered payloads are rejected.

External service transparency. The CI gate extracts every external domain from the source code and verifies it appears in the readme.txt disclosure. If a developer adds an HTTP call to a new domain, the build fails until the domain is documented.

What Automated Testing Cannot Catch

We believe in transparency about limitations, not just capabilities.

Automated tests verify that code behaves correctly under known conditions. They cannot catch:

  • Subtle UX confusion — a dashboard chart that is technically correct but misleading to non-technical users
  • Performance edge cases — a query that is fast with 1,000 rows but degrades at 100,000. We have k6 load tests for critical paths, but they cannot cover every data shape
  • WordPress ecosystem conflicts — plugin or theme interactions that only surface on specific hosting configurations. We test against WP 6.4 through trunk, but the WordPress ecosystem has 60,000+ plugins
  • Zero-day vulnerabilities — no amount of static analysis prevents exploitation of previously unknown attack vectors

We mitigate these gaps with manual review on every release, a public GitHub repository where anyone can audit the code, and active monitoring of the WordPress.org support forums for reports from real-world installations.

Why We Published This

Research shows that over 50% of WordPress plugin developers do not patch reported vulnerabilities before public disclosure. Plugins go years without updates. Users have no way to distinguish a well-maintained plugin from an abandoned one except star ratings and “Last updated” dates.

We think the WordPress ecosystem deserves better signals. Publishing our quality pipeline is one way to raise the bar — both for ourselves (now that it is public, we cannot quietly skip checks) and for the ecosystem (other plugin developers can adopt similar practices).

If you are evaluating analytics plugins for your WordPress site, we encourage you to ask every candidate: how do you test? What checks run before a release? Can I see the CI configuration?

Statnive’s entire codebase is open source on GitHub. Every workflow file, every test, every compliance gate described in this post is publicly auditable.

Try Statnive

All of this engineering exists to serve one goal: giving you analytics you can trust on your own WordPress server. No third-party data transfers, no cookies, no tracking scripts that slow down your site.

Install Statnive free from WordPress.org — your data stays on your server, verified by 248 tests and 22 release gates on every release.

Get Statnive Free