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

easy-seo-checker

v1.0.3

Published

Client-side SEO page analyzer (browser-only): DOM analysis, scoring, and actionable suggestions.

Readme

easy-seo-checker

CI npm version MIT License Bundle Size

Lightweight client-side SEO analyzer for web pages.
Analyzes the rendered DOM, calculates an SEO score (0–100) with clear labels, and generates actionable suggestions — all directly in the browser with zero runtime dependencies.

Features

  • 📊 SEO scoring (0–100) with clear labels
  • 🔍 DOM analysis for titles, meta tags, headings, images, links, and more
  • 🧠 Actionable SEO recommendations you can surface in UIs
  • Zero runtime dependencies
  • 🌐 Browser-only (runs after page render)
  • ⚛️ Optional React hook (easy-seo-checker/react)
  • 🎯 Ignore elements with [data-seo-ignore]
  • 📦 Small bundle size

Installation

npm install easy-seo-checker

That's it — the core library has zero runtime dependencies and works with any browser framework.

Framework Compatibility

The core entry (easy-seo-checker) is framework-agnostic. It works anywhere the browser DOM is available:

| Framework | Supported | Entry point | |-----------|-----------|-------------| | Vanilla JS | Yes | easy-seo-checker | | React | Yes | easy-seo-checker + optional easy-seo-checker/react hook | | Angular | Yes | easy-seo-checker | | Vue | Yes | easy-seo-checker | | Svelte | Yes | easy-seo-checker | | Next.js / Nuxt / Angular Universal | Client-side only | Call after mount, not during SSR | | Node.js / Deno / Bun (server) | No | Requires browser DOM |

The optional easy-seo-checker/react sub-path provides a useSeoPageAnalysis hook for React projects. React is listed as an optional peer dependency — non-React projects won't install or download it.

Quick Start

Vanilla / any framework

Run the analyzer after the page has rendered:

import { getSeoPageAnalysis, getScoreLabel } from "easy-seo-checker";

const result = getSeoPageAnalysis(window.location.pathname);

console.log("Score:", result.score);
console.log("Label:", getScoreLabel(result.score));
console.log("Suggestions:", result.recommendations);

With options

import { getSeoPageAnalysis } from "easy-seo-checker";

const result = getSeoPageAnalysis(window.location.pathname, {
  ignoreSelector: ".admin-panel, [data-seo-ignore]",
});

Angular

import { Component, AfterViewInit } from "@angular/core";
import { getSeoPageAnalysis, getScoreLabel } from "easy-seo-checker";

@Component({ selector: "app-seo", template: `<p>Score: {{ result?.score }}</p>` })
export class SeoComponent implements AfterViewInit {
  result: ReturnType<typeof getSeoPageAnalysis> | null = null;

  ngAfterViewInit() {
    this.result = getSeoPageAnalysis(window.location.pathname);
  }
}

Vue

<script setup>
import { ref, onMounted } from "vue";
import { getSeoPageAnalysis, getScoreLabel } from "easy-seo-checker";

const result = ref(null);
onMounted(() => {
  result.value = getSeoPageAnalysis(window.location.pathname);
});
</script>
<template>
  <p v-if="result">Score: {{ result.score }} – {{ getScoreLabel(result.score) }}</p>
</template>

Svelte

<script>
  import { onMount } from "svelte";
  import { getSeoPageAnalysis, getScoreLabel } from "easy-seo-checker";

  let result = null;
  onMount(() => {
    result = getSeoPageAnalysis(window.location.pathname);
  });
</script>

{#if result}
  <p>Score: {result.score} – {getScoreLabel(result.score)}</p>
{/if}

React (optional hook)

import { useEffect } from "react";
import { getScoreLabel } from "easy-seo-checker";
import { useSeoPageAnalysis } from "easy-seo-checker/react";

function SeoReviewPanel() {
  const pathname = typeof window !== "undefined" ? window.location.pathname : null;
  const { result, run, reset, loading, error } = useSeoPageAnalysis(pathname, {
    runOnMount: false,
  });

  useEffect(() => {
    if (!pathname) return;
    run();
  }, [pathname, run]);

  if (loading) return <p>Analyzing…</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!result) return <button onClick={run}>Run SEO analysis</button>;

  return (
    <div>
      <p>
        Score: {result.score} – {getScoreLabel(result.score)}
      </p>
      <ul>
        {result.recommendations.map((r, i) => (
          <li key={i}>{r}</li>
        ))}
      </ul>
      <button onClick={reset}>Clear</button>
    </div>
  );
}

Example Output

{
  score: 82,
  label: "Good",
  recommendations: [
    "Meta description is missing",
    "Add alt text to 3 images",
    "Consider adding structured data (JSON-LD)"
  ]
}

Browser Only

This package runs only in the browser because it relies on:

  • document
  • window
  • location

Do not run during SSR (Next.js, Nuxt, etc.).
Instead, run it after the page mounts (e.g. in useEffect, onMounted, ngAfterViewInit, onMount, etc.).

Ignore Selector

Elements with the attribute [data-seo-ignore] are excluded from analysis by default. Add this attribute to admin UI, modals, or chatbots you want excluded:

<div data-seo-ignore>
  <!-- This block is ignored by the analyzer -->
</div>

You can customize this via the ignoreSelector option or pass your own ignoreSelector when calling getSeoPageAnalysis.

API

Main entry (easy-seo-checker)

| Export | Description | |--------|-------------| | getSeoPageAnalysis(pathname, options?) | Full DOM analysis; returns SeoPageAnalysisResult | | getMainContentRoot(ignoreSelector?) | First main, article, or .content outside ignored containers | | getPageParagraphs(ignoreSelector?) | All <p> elements outside ignored containers | | calculateSeoScore(result) | Score 0–100 from a SeoAnalysisResult | | generateSeoSuggestions(result) | Suggestion strings from a SeoAnalysisResult | | getScoreColor(score) | Hex color string (e.g. "#16a34a" for green) | | getScoreLabel(score) | Label: "Excellent", "Good", "Needs Improvement", or "Poor" |

Options

interface SeoAnalyzerOptions {
  /** CSS selector for elements to exclude. Default: "[data-seo-ignore]" */
  ignoreSelector?: string;
}

React entry (easy-seo-checker/react)

| Export | Description | |--------|-------------| | useSeoPageAnalysis(pathname, options?) | Returns { result, run, reset, loading, error } |

Hook Options

interface UseSeoPageAnalysisOptions extends SeoAnalyzerOptions {
  /** Run analysis once when pathname is set. Default: false */
  runOnMount?: boolean;
}

Types

All types are exported from the main entry:

  • SeoAnalyzerOptions
  • SeoAnalysisResult
  • SeoPageAnalysisResult
  • SeoPageImagesResult
  • SeoPageKeywordsResult
  • SeoPageAiSignalsResult
  • SeoPageContentStructureResult
  • SeoPageKeywordDensityResult
  • SeoPageUrlSlugResult

Score Breakdown (100 points)

| Category | Points | Criteria | |----------|--------|----------| | Meta tags | 30 | Title present (10), title length 30–60 (5), description present (10), description length 120–160 (5) | | Open Graph | 20 | og:title (5), og:description (5), og:image (5), twitter:card (5) | | Headings | 20 | Single H1 (15) or multiple H1s (5), H2 present (5) | | Images | 15 | Scaled by alt-text coverage; full marks if no images | | Links | 10 | Internal links (5), external links (5) | | Structured data | 5 | Valid JSON-LD present |

Use Cases

  • SEO audit tools
  • CMS SEO panels
  • Browser extensions
  • Admin dashboards
  • Static site SEO validation
  • Content publishing workflows

Performance

The analyzer scans the rendered DOM once and is designed to be lightweight.

Typical runtime: <10 ms for most pages (depends on page size and device).

Browser Support

  • Chrome
  • Edge
  • Firefox
  • Safari

Requires modern DOM APIs.

SEO Score: 82 (Good)

✔ Title tag present
✔ H1 found
⚠ Missing meta description
⚠ 3 images missing alt text

You can build your own UI on top of SeoPageAnalysisResult to match your product.

Development

npm install        # Install dependencies
npm run dev        # Watch mode
npm run build      # Production build
npm test           # Run tests
npm run lint       # Run linter

See CONTRIBUTING.md for guidelines.

License

MIT — Akash Arora