SEO Analyzer logo

SEO Analyzer

By Kowdja

SEO Analyzer adds focus‑keyphrase analysis, on‑page SEO checks, readability guidance, metadata previews, per‑entry content scores, and a site‑wide SEO dashboard to Strapi 5. Analysis is advisory and never blocks saving or publishing.

Latest version

v1.0.0

released July 17, 2026

npm install @kowdja/strapi-plugin-seo-analyzer

SEO Analyzer for Strapi

SEO Analyzer adds focus-keyphrase analysis, on-page SEO checks, English readability guidance, metadata previews, Content Manager scores, and a snapshot-based audit dashboard to Strapi 5.

The plugin is advisory: analysis never prevents saving or publishing.

Screenshots

SEO dashboard

Global score, analysis coverage, priority queue, recurring issues, and the full content inventory in one place.

SEO Analyzer dashboard

Home widget

An at-a-glance SEO health widget on the Strapi home page.

SEO health home widget

Score in the Content Manager

A per-entry SEO score column and editor sidebar, right where you edit content.

SEO score in the Content Manager

Compatibility

  • Strapi >=5.50.1 <6
  • Node.js 20, 22, or 24
  • React 18

Install

npm install @kowdja/strapi-plugin-seo-analyzer
npx @kowdja/strapi-plugin-seo-analyzer init

The initializer safely installs src/components/shared/seo.json when it does not exist. It never overwrites an existing component. Add shared.seo to each eligible content type as a non-repeatable component field named seo.

Enable the plugin in config/plugins.js:

module.exports = ({ env }) => ({
  'seo-analyzer': {
    enabled: true,
    config: {
      siteUrl: env('WEBSITE_URL'),
      resolver: {
        enabled: Boolean(env('SEO_ANALYZER_RESOLVER_URL')),
        url: env('SEO_ANALYZER_RESOLVER_URL'),
        secret: env('SEO_ANALYZER_RESOLVER_SECRET'),
        timeoutMs: 2000,
      },
    },
  },
});

Rebuild the admin after installation:

npm run build
npm run develop

Features

  • Live primary focus-keyphrase analysis with up to ten secondary phrases.
  • Page SEO and English readability category scores.
  • Browser and social metadata previews with value-source labels.
  • Per-content-type field mappings and assessment switches.
  • SEO score column in eligible Content Manager collection lists.
  • Action-first SEO dashboard with score distribution, category averages, recurring issues, and a prioritised content inventory.
  • Native Strapi home widget for global score, coverage, active problems, and the most common issue.
  • Background inventory synchronization for every eligible document and locale.
  • Duplicate keyphrase checks within the current locale.
  • Optional frontend metadata resolution for generated canonical and social tags.

Configuration

interface SeoAnalyzerConfig {
  analyzerVersion?: string;
  maxSecondaryKeyphrases?: number;
  siteUrl?: string;
  siteHostnames?: string[];
  seoComponentUid?: string;
  seoField?: string;
  analysisPayloadLimit?: number;
  resolver?: {
    enabled?: boolean;
    url?: string;
    secret?: string;
    timeoutMs?: number;
    retrySavedAnalysis?: boolean;
  };
  migration?: { importLegacySeoStore?: boolean };
  inventory?: {
    syncOnStartup?: boolean;
    batchSize?: number;
    concurrency?: number;
  };
}

Defaults use shared.seo, the root field seo, a 2 MB analysis limit, ten secondary keyphrases, a disabled resolver, and a background inventory sync of 25 documents per batch.

SEO dashboard and home widget

The SEO Analyzer menu opens a local content-quality dashboard. It includes a global score, current-analysis coverage, active problems, missing focus keyphrases, score distribution, category averages, a priority queue, recurring issues, and a filterable content inventory. Titles and scores open the matching Content Manager entry and locale.

The global score is the arithmetic average of current, complete, scored published documents in the selected scope. It is a content-optimization score; it does not measure rankings, traffic, backlinks, crawl health, or Search Console performance. Draft content is available through the status filter.

SEO Analyzer also registers an optional native SEO health widget. Existing Strapi home layouts are not changed: add the widget from the homepage's Add widget control. It is visible only to users with SEO Analyzer access.

At startup, the plugin indexes existing SEO-enabled content in the background. This never blocks Strapi startup, saves, or publication. Administrators with the run-backfill permission can restart the scan from the dashboard.

siteUrl and siteHostnames classify absolute links. Root-relative links are always internal. Without site identity, absolute links are not assumed to be internal.

Analysis without a resolver

Local focus-keyphrase, content, link, image, and readability checks work without a frontend. Checks that require rendered metadata return N/A and are excluded from scoring. They do not become failures.

Optional frontend resolver

The resolver is a framework-neutral authenticated HTTP endpoint. Its public request and response types are exported from @kowdja/strapi-plugin-seo-analyzer/types. A Nuxt example is included under examples/nuxt-resolver.

Remote resolver URLs must use HTTPS. HTTP is accepted for localhost only. Unsaved document content is sent to the configured endpoint during live analysis. The plugin sends no content elsewhere and collects no telemetry.

Resolver failures produce provisional analysis and never block publication.

Permissions

The plugin registers these admin actions:

  • plugin::seo-analyzer.read
  • plugin::seo-analyzer.analyze
  • plugin::seo-analyzer.manage-settings
  • plugin::seo-analyzer.run-backfill

Assign actions to non-super-admin roles in the Strapi administration panel. Snapshots have no public Content API routes.

Scoring

Applicable checks receive 0, 3, 6, or 9 points. N/A checks are excluded. The overall score weights Focus Keyphrase at 40%, Page SEO at 40%, and Readability at 20%. Secondary keyphrases do not affect the overall score.

English is the only language with linguistic readability scoring in 1.x. Unsupported languages receive N/A rather than a penalty.

Legacy migration

For an existing installation that previously used plugin store name seo, enable the importer for one verified deployment:

migration: { importLegacySeoStore: true }

The importer is opt-in, idempotent, does not overwrite populated settings, and records a completion marker. Remove the option after verifying mappings and role permissions. Existing shared.seo content is not rewritten. The snapshot table keeps the collection name seo_analysis_snapshots.

Troubleshooting

  • Plugin is absent: rebuild the Strapi admin after enabling it.
  • Readability is N/A: select editorial body fields in SEO setup and use an English locale with at least three sentences.
  • Canonical/social checks are N/A: enable a frontend resolver or provide explicit metadata fields.
  • Scores are missing in a list: confirm that the content type has the configured SEO component and that it has been saved at least once.
  • Coverage is incomplete: wait for the background inventory sync to finish or use Refresh inventory in the SEO dashboard.

Upgrading and uninstalling

Back up the database before schema upgrades. Removing the npm package does not delete shared.seo content or the seo_analysis_snapshots table. Remove those explicitly only after confirming they are no longer needed.

Development

See CONTRIBUTING.md. For local package development use npm run watch:link or build the package and install it through a file: dependency.

License and attribution

MIT. See LICENSE, NOTICE.md, and UPSTREAM.md.

Submit your content

Share your work with the community and get it listed in the Strapi ecosystem for everyone to discover and use.

Submit
Submit your content