npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@webupro/medusa-power-seo

v0.1.0

Published

SEO scoring for Medusa v2 — Rank Math-style product score, per-check breakdown, SERP preview and a catalogue-wide worst-first list, built on @power-seo/content-analysis.

Readme

@webupro/medusa-power-seo

SEO scoring for Medusa v2, built on @power-seo/content-analysis.

Adds a Rank Math-style score to the product page — a dial, a grouped checklist, a live Google preview — and a catalogue-wide list that answers "where do I start?". Multi-locale shops score each language separately.

surface

Install

npm install @webupro/medusa-power-seo
// medusa-config.ts
module.exports = defineConfig({
  plugins: [{ resolve: "@webupro/medusa-power-seo", options: {} }],
})

Restart the backend. The product page gains an SEO score panel and the sidebar gains an SEO scores page.

Configuration

Configuration is environment variables, not plugin options: this plugin registers no module (it has no table of its own), and Medusa forwards plugins[].options to a plugin's modules. Every variable has a default that produces a working single-locale English install.

| Variable | Default | What it does | | --- | --- | --- | | POWER_SEO_STOREFRONT_URL | STOREFRONT_URL, else http://localhost:8000 | Origin of the canonical URL that gets graded | | POWER_SEO_PRODUCT_PATH | /{locale}/products/{handle} | Canonical path template | | POWER_SEO_SOURCE_LOCALE | en | The locale whose copy lives on the product row | | POWER_SEO_LOCALES | (source only) | Extra locales to score, comma-separated | | POWER_SEO_BRAND_SUFFIX | (none) | Appended to a generated <title>, e.g. \| LIFTED | | POWER_SEO_ADMIN_LANG | en | Admin copy language — en, hu or sk | | POWER_SEO_TRANSLATIONS_MODULE | translations | Container key of the module holding locale overlays |

A two-language Slovak shop:

POWER_SEO_STOREFRONT_URL=https://lifted.sk
POWER_SEO_SOURCE_LOCALE=sk
POWER_SEO_LOCALES=hu
POWER_SEO_BRAND_SUFFIX=| LIFTED
POWER_SEO_ADMIN_LANG=hu

Multi-locale scoring

Each locale ships its own <title> and <meta description>, so each earns its own score. The source locale is graded from the product row itself. Every other locale is an overlay read from the shop's translations module, resolved by container key, over rows of (resource_type, resource_id, locale, field, value) — the shape MedusaService generates for a Translation model. The overlay fields are title, description, seo_title, seo_description and seo_keyphrase.

Resolution order per locale, chosen so the score grades the page that actually ships: the locale's own SEO override → the locale's translated copy → the source locale. A source-locale override never outranks a translation, otherwise a Hungarian page would be graded on copy no Hungarian visitor sees.

A shop with no translations module still works — it scores its source locale, and the locale tabs never render.

What gets graded

The analyser runs 99 checks, but most grade a blog article: author schema, source quality, FAQ and TL;DR sections, citation readiness, freshness. A perfectly good product page scores 44% against the full set, which makes the raw number useless to an operator. This plugin grades the 17 checks a product detail page can actually influence and normalises over the ones that ran.

| Section | Checks | | --- | --- | | Basic SEO | title length and keyphrase, keyphrase position, meta description length and keyphrase, keyphrase in URL, description length | | Keyphrase | length, density, first-paragraph presence, distribution, even distribution | | Readability | paragraph length, sentence length | | Technical | URL length, canonical URL, product images |

Deliberately excluded: the E-E-A-T / AEO / search-intent families (article-shaped), heading / link / table-of-contents checks (owned by the storefront template, not by any admin field), image-alt and image-keyphrase (storefronts render the product title as alt, so it is never actually missing), the English-wordlist checks transition-words, word-complexity, title-sentiment, title-power-word and inclusive-language (the library takes a locale but no check reads it, so they mis-grade every other language), and text-presence (it duplicates word-count).

Keyphrase checks are skipped, not failed, until the operator sets a focus keyphrase — grading a product against a phrase nobody chose is noise.

API

| Route | Returns | | --- | --- | | GET /admin/seo-score?locale=&q=&limit= | Every published product, worst first, plus count, average, locales and the admin label pack | | GET /admin/seo-score/:id?locale= | One product with the per-check breakdown and the meta the SERP will show |

Scoring is pure and costs ~3ms per product, so the catalogue is graded per request rather than cached — a stale score is worse than a one-second wait, and there is no invalidation to get wrong. Paging stops at 2000 products.

The focus keyphrase is stored on metadata.seo_keyphrase and is editable in the source locale only; its translation belongs to the shop's translations module.

Development

npm install
npm test            # unit tests — pure, no database
npm run build       # medusa plugin:build

Licence

MIT