Search by

magenxcommerce / module-best-seller-graph-ql

magenxcommerce

GraphQL coverage for Magento best sellers: a bestSellers query (store-wide or per category) and an Amazon-style per-category best-seller badge on products. Reads the sales_bestsellers_aggregated_* report tables; leaves the core modules untouched.

Package info

github.com/magenxcommerce/module-best-seller-graph-ql

Type:magento2-module

pkg:composer/magenxcommerce/module-best-seller-graph-ql

Statistics

Installs: 0

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

v2.0.1 2026-10-11 11:15 UTC

This package is auto-updated.

Last update: 2026-10-24 21:37:46 UTC


README

Built with AI assistance. This module is built with significant use of Claude Code, under active human review and guidance. It is open source and in active development. AI assistance does not lower the engineering bar: every change must meet the same correctness, security, documentation and maintainability requirements as any other contribution.

No warranty. We are not responsible for any incompatibility. By installing this software, you accept responsibility for its security, upgrades, patches and monitoring.

GraphQL coverage for Magento best sellers. Stock Magento aggregates best-seller data in the sales_bestsellers_aggregated_* report tables but exposes none of it over GraphQL, and those tables have no per-category dimension. This module adds that coverage without touching any core module (the same "extend with GraphQL" split as Magento_CatalogGraphQl beside Magento_Catalog).

What it adds

  • bestSellers(category_id: Int, pageSize: Int): BestSellers — the top-N best-selling products, store-wide or scoped to a single category, ordered by quantity sold over the configured report period. Each BestSellerItem carries a rank and resolves a full ProductInterface (so the storefront can select any product fields it needs). Visibility is checked on ids alone and only the products that make the page are hydrated, so the whole page costs two product queries, not one per row.
  • ProductInterface.best_seller: BestSellerBadge — an Amazon-style per-category badge (rank, category_id, category_name, category_url_key) computed as the product's best rank across the categories it belongs to, or null when it doesn't rank within the configured threshold. Implemented as a batch resolver: an entire grid costs a fixed handful of queries, so it is safe to select on listing pages as well as the PDP.
  • StoreConfig flags — best_seller_enabled, best_seller_count, best_seller_period, best_seller_badge_enabled, best_seller_badge_max_rank (via extendedConfigData, the same pattern as product_alert_allow_price).

Ranking

Reads sales_bestsellers_aggregated_<period> filtered to the request's store id, summing qty_ordered per product. Per-category ranking joins catalog_category_product; a product's badge rank in a category is 1 + (number of products in that category that sold more), so tied products share a rank. The aggregation cron (Reports → refresh statistics, or bin/magento report aggregation) must have run for the tables to be populated.

Two things bound what the ranking can contain:

  • The period is a bucket, not a lifetime total. Each aggregated table holds one row per (period, store, product), and queries are constrained to the current bucket — sales so far today, this month, or this year, in the store's timezone. Early in a bucket the ranking therefore covers a partial period; on Daily, shortly after midnight, it may be empty.
  • Only publicly visible products rank. Products that are disabled, set to "Not Visible Individually", or not assigned to the request's website are dropped, and ranks are numbered afterwards so they stay contiguous. Category ids that do not belong to the store's own tree are rejected, and badges never rank a product against another store view's categories or name a category that is disabled in the store view.
  • Quantities stay private. The query exposes each product's rank, never the units sold — bestSellers is unauthenticated, and raw sales volume is business data.

Configuration

Admin → Stores → Configuration → Magenx → Best Sellers:

  • General: Enable Best Sellers, Number of Products (default 20), Report Period (Daily / Monthly / Yearly, default Monthly).
  • Product Badge: Enable Per-Category Badge, Maximum Badged Rank (default 10).

When the feature is disabled the bestSellers query returns an empty list and the best_seller field resolves to null, so the feature is fully inert.

Install

bin/magento module:enable Magenx_BestSellerGraphQl
bin/magento setup:upgrade
bin/magento setup:di:compile   # production mode

Tests

Unit tests live in Test/Unit and run from a Magento installation that has the module in place — they mock Magento interfaces, so they need magento/framework on the autoloader and cannot run against a bare checkout of this repo:

bin/magento dev:tests:run unit
# or, for this module only:
vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist vendor/magenxcommerce/module-best-seller-graph-ql/Test/Unit