How Gumroad Discover ranks products: what the code says
Most advice about Gumroad Discover is a guess. Post often, add more products, use a nice cover. Some of it may help. None of it shows up in the ranking code the author read.
This is a plain summary of the sort order in the public antiwork/gumroad repository, read on 2026-10-11, plus a list of what was not found. The author has zero sales on their own store as of 2026-10, so there is no personal result to add. Only the code.
The default order
In discover_controller.rb, if the visitor picks no sort and curated products exist for them, the sort is set to "curated", and those curated products get a boost. If no curated products exist for that visitor, the default is "featured". So "the default is featured" is only true for a visitor without curated products. How curated products and their score are produced is unknown; the author did not trace it.
In searchable.rb, "featured" resolves to two keys, in this order:
total_fee_cents, descendingsales_volume, descending
Both are calculated over a window named DEFAULT_SALES_VOLUME_RECENTNESS, set to three months. Put simply, the product that earned Gumroad the most in fees over the last three months comes first. Ties are broken by sales volume.
That is a revenue ranking, not a quality ranking, and nothing in it is about freshness.
Inference, not code: the fee is presumably derived from the sale price, but the author did not read the exact fee formula. If so, a $30 product with five sales would sit well above a $1 product with five sales. By the same logic a free product has no fee income, so if it is recommendable at all it would sit near the bottom of the default order.
The other sorts
The sorts a buyer can pick are defined in product_sort_key.rb and applied in searchable.rb:
| Sort | What the code does |
|---|---|
| featured | total fee cents, then sales volume, over the last 3 months |
| best sellers | past-year fee cents, descending |
| curated | an internal score, then past-year fee cents |
| hot and new | only products created within 90 days, by sales volume |
| newest | creation date, newest first |
| recently updated | content update date, newest first |
There are also price (ascending or descending), most reviewed (review count), highest rated (average rating, then review count) and staff picked (staff-pick date, newest first).
The tie
At the end of the sort block a comment says that in the event of a tie, results are sorted by newest, meaning created_at descending is the last key. The plain consequence: in the default view, freshness only matters as a tie-break between products that are otherwise equal. The one sort that favors fresh products on purpose is "hot and new", and the buyer has to choose it.
What refreshes the numbers
A background worker, ReindexRecommendableProductsWorker, goes over products flagged as recommendable and queues an update for each. It adds the volume figures (sales_volume, total_fee_cents, past_year_fee_cents) to the update only for products with a purchase in the last three months. What happens to the stored numbers of products without a recent sale is not shown in the file read, so it is unknown.
What was not found
No ranking term for any of these turned up in the files read:
- how often you post or update
- how many products you have
- cover image quality or description length
- a temporary "new listing boost"
"Did not find" is not "does not exist". The repository is large, the author read a handful of files, and Gumroad could use signals that live outside this code. A few blog posts claim a boost for new listings. The code read does not confirm it.
What this suggests
These are the author's inferences, not facts from the code:
- Because ranking follows fees earned, early sales probably matter more than listing polish once a product is in Discover at all.
- Because entry needs a sale first (see why products are missing from Discover), the ranking order only matters after that.
- Posting many new products may do little for Discover rank.
Caveats
- Code read on 2026-10-11 on the
mainbranch. It can change at any time. - The author read the code and did not run it, so this is "what the code appears to say".
- Fee amounts are covered in a later article.
- The author is a seller, not a Gumroad engineer, and can misread a sort clause.
Read it yourself
The repository is public. The sort logic is in app/modules/product/searchable.rb, the default-sort choice in app/controllers/discover_controller.rb, and the refresh job in app/sidekiq/reindex_recommendable_products_worker.rb.
The author's 30-day experiment
In 2026-10 the author is testing how a store with about 40 products and no sales behaves when a few products get outside traffic. There are no results yet. When there are, they will be written up, including a result of zero: [case study link, not yet published].
Sources
- antiwork/gumroad: app/modules/product/searchable.rb (main, read 2026-10-11)
- antiwork/gumroad: app/controllers/discover_controller.rb (main, read 2026-10-11)
- antiwork/gumroad: app/controllers/concerns/search_products.rb (main, read 2026-10-10)
- antiwork/gumroad: app/models/product_sort_key.rb (main, read 2026-10-10)
- antiwork/gumroad: app/sidekiq/reindex_recommendable_products_worker.rb (main, read 2026-10-11)