=== Simplicity SEO Audit ===
Contributors: simplicitygr
Tags: seo, audit, seo audit, seo score, site health
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 2.0.6
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Honest SEO audit for WordPress: scans 200 pages with real rendered HTML, not database shortcuts. Fast, stable, no server overload.

== Description ==

Simplicity SEO Audit scans your WordPress site and gives you a clear SEO health score with specific, actionable recommendations. No technical expertise required — install, scan, and see exactly what needs fixing.

= Why 200 pages? =

We scan up to 200 pages on purpose — not because we cannot do more.

Each page is fetched as live HTML, exactly as Google sees it: theme output, page builders, WooCommerce templates, resolved SEO plugin meta. That is accurate, but heavy. A full crawl of thousands of pages inside WordPress would slow down or crash most hosting setups.

200 pages is a proportional random sample across your content types. You get a reliable SEO health picture in 1–3 minutes, without putting your server on its knees.

Other audit plugins may claim "unlimited" scans. Often that means reading the database only, not the real page. We chose accuracy over marketing.

= What makes this different =

* **Real rendered HTML**, not database-only checks
* **Stable scan** on normal WordPress hosting (typically 1–3 minutes)
* **WooCommerce-aware** scoring (products, categories, utility pages excluded)
* **Works with Yoast, Rank Math, SEOPress** — reads their output, does not replace them
* **Honest scope**: SEO audit only. No fake "full site crawl" promises.

= What it does =

* Scans up to 200 pages (posts, pages, products, and taxonomy terms) as a proportional sample — real HTML per page, designed to finish in minutes without overloading your server
* Runs 17 SEO checks across content quality and technical health
* Fetches the actual rendered HTML of each page (like Google sees it), not just the database content
* Gives you a weighted score from 0 to 100 with a letter grade (A to F)
* Shows specific issues with the exact URLs that need attention
* Exports a clean HTML report you can print or share with clients
* Works with WooCommerce, Yoast SEO, Rank Math, SEOPress, and all major page builders

= 17 SEO Checks =

**Content Checks (10):**

1. **Title Tag** (weight: 9) — Checks every page has a title between 30-60 characters. Flags empty, too short, and too long titles.
2. **Meta Description** (weight: 8) — Checks for meta descriptions between 70-160 characters. Flags missing, too short, and too long descriptions.
3. **Headings H1** (weight: 8) — Verifies each page has exactly one H1 tag and checks heading hierarchy (no skipping from H1 to H3).
4. **Image Alt Text** (weight: 5) — Counts images without an alt attribute. Explicit empty alt values are accepted. Score is average coverage across evaluated pages with images.
5. **Internal Links** (weight: 5) — Checks each page has at least one internal link in the content area.
6. **Thin Content** (weight: 4) — Flags pages with fewer than 300 words (posts/pages) or 30 words (taxonomy terms). Supports Greek and all Unicode languages.
7. **Duplicate Titles** (weight: 4) — Finds pages sharing identical title tags.
8. **Duplicate Descriptions** (weight: 4) — Finds pages sharing identical meta descriptions.
9. **Canonical Tag** (weight: 3) — Checks every page has a canonical URL tag.
10. **OG/Twitter Tags** (weight: 3) — Checks for Open Graph and Twitter Card meta tags.

**Technical Checks (7):**

1. **SSL/HTTPS** (weight: 4) — Checks whether the configured public site URL uses HTTPS. This does not validate certificates or redirects.
2. **XML Sitemap** (weight: 3) — Fetches sitemap XML with GET from standard frontend locations and URLs declared in robots.txt. HTML responses are not accepted as sitemap evidence.
3. **Robots.txt** (weight: 3) — Checks for a robots.txt file.
4. **SEO Plugin** (weight: 0) — Detects if Yoast, Rank Math, SEOPress, or another SEO plugin is active.
5. **Schema Markup** (weight: 2) — Checks the homepage for structured data (JSON-LD).
6. **PHP/WP Version** (weight: 2) — Checks for outdated PHP or WordPress versions.
7. **Permalink Structure** (weight: 1) — Verifies pretty permalinks are enabled (not plain ?p=123).

= How the Score Works =

The audit score measures evaluated plugin checks. Content usefulness, search rankings and overall SEO quality require separate review. It uses weighted RMS deficits: 100 - sqrt(sum(normalized_check_weight * mean_page((100 - page_score)^2))). Page deficits are squared before averaging within each check; site-wide checks use their own deficit. Content has a 75% share and technical checks 25%. Unavailable and not-applicable checks are excluded; a sole evaluated category receives the full share.

Large unresolved gaps matter more than small recommendations. There is no additional page-count penalty or page-based grade ceiling. Equal failure proportions have equal impact across sample sizes. A confirmed site-wide crawler block caps the final score at 44.

Title-length recommendations cost 20% within their check, description lengths 10%, multiple H1s 15%, hierarchy skips 10%, low word counts 25%, missing editorial links 40% and duplicate descriptions 15%. Missing titles, descriptions and H1s retain the full check penalty. Missing social tags or JSON-LD cost 25%; a confirmed missing sitemap costs 40%. These are our product policy weights, not Google scoring rules or validated ranking predictions.

SEO-plugin detection is informational (weight 0). A robots.txt 404/410 does not lower the score; a confirmed crawler block remains critical.

Legal, account-panel and recognized form pages skip irrelevant editorial recommendations. Structural checks still apply. An explicit empty image alt is accepted as a decorative declaration; the audit cannot determine every image's purpose or establish full accessibility compliance.

Partial audits are labelled clearly. After upgrading from earlier scoring rules, run a new scan; saved scores are retained and identified until new evidence is collected.

**Grading scale:**
* A = 90-100 (Excellent)
* B = 75-89 (Good)
* C = 60-74 (Needs improvement)
* D = 45-59 (Poor)
* F = 0-44 (Critical issues)

A score of 100 means no scored findings in the evaluated checks. Scored findings cap the score at 99; excluded informational findings do not. A partial audit can have a high score while checks remain unavailable.

= Taxonomy-Aware Scoring =

Not all pages are equal. The plugin uses a tiered system for taxonomy terms:

* **High priority** (full weight): Posts, pages, product categories — these are your main landing pages
* **Medium priority** (half weight): Other custom taxonomies — supporting pages
* **Low priority** (info only): Tags, product tags and product attributes (e.g., color, size)

Low-priority terms are flagged for information but don't affect your score. This prevents product attributes from unfairly dragging down your SEO score.

Developers can customize tiers with the `ssea_taxonomy_tier` filter.

= Rendered HTML Analysis =

Unlike most lightweight SEO plugins that only read database content, Simplicity SEO Audit fetches the actual rendered HTML of each page — exactly what Google sees. This means:

* H1 tags added by your theme are detected
* Page builder content (Elementor, Divi, WPBakery) is analyzed
* Shortcode output is included in word counts
* Navigation and footer elements are stripped — only the main content area is analyzed
* Title tags, meta descriptions, canonical URLs, and social tags are read from the rendered `<head>`

If a page cannot be fetched (for example, because it is password-protected or blocked by a firewall), checks that require the rendered page are skipped for that URL. This prevents theme or page-builder output from being mistaken for missing content. The scan continues with the remaining pages.

= REST API =

The plugin provides a REST API endpoint for external integrations:

`GET /wp-json/seo-audit/v1/stats?token=YOUR_TOKEN`

The token is auto-generated on activation and stored in the database. The endpoint returns site URL, page counts, audit summary, per-check scores, and pricing tier information. It is read-only and uses timing-safe token comparison.

= Privacy =

* All scanning happens on your own server — no data is sent automatically
* The REST API is token-protected and read-only
* Scan results are stored in your WordPress database only
* All data is deleted when you uninstall (delete) the plugin
* See "Third-Party Services" below for details on the optional connection to seo.simplicity.gr

= Third-Party Services =

This plugin connects to [seo.simplicity.gr](https://seo.simplicity.gr) in the following ways:

1. **CTA Links**: The plugin dashboard includes a "Get the Full Report" link that directs you to seo.simplicity.gr. The link includes your site URL and a locally-generated API token as URL parameters.

2. **REST API Endpoint**: The plugin registers a REST API endpoint (`/wp-json/seo-audit/v1/stats`) that allows seo.simplicity.gr to retrieve your scan summary (score, grade, number of checks, number of issues, and total page count). Access requires a valid API token. No page content, URLs, or personal data is transmitted.

* Service: [seo.simplicity.gr](https://seo.simplicity.gr)
* Provider: [Simplicity](https://www.simplicity.gr)
* Terms of Service: [https://seo.simplicity.gr/terms.html](https://seo.simplicity.gr/terms.html)
* Privacy Policy: [https://seo.simplicity.gr/privacy-policy.html](https://seo.simplicity.gr/privacy-policy.html)

== Installation ==

1. Upload the `simplicity-seo-audit` folder to `/wp-content/plugins/`
2. Activate the plugin through the 'Plugins' menu in WordPress
3. Go to the "Simplicity SEO Audit" menu item in your admin sidebar
4. Click "Scan" and wait for the results (typically 1-3 minutes depending on site size)

Or install via ZIP:

1. Go to Plugins > Add New > Upload Plugin
2. Choose the `simplicity-seo-audit.zip` file
3. Click "Install Now" then "Activate"

== Frequently Asked Questions ==

= How many pages does it scan? =

Up to 200 pages, proportionally sampled across your content types. If your site has 600 products, 30 pages, and 20 posts, the sample will reflect those proportions.

= Why does the scan take a few minutes? =

The plugin fetches the rendered HTML of each page (up to 200 HTTP requests to your own site). This is what makes the results accurate — we see what Google sees. Typical scan time is 1-3 minutes.

= Does it work with WooCommerce? =

Yes. Products, product categories, product tags, and product attributes are all supported with appropriate scoring tiers.

= Does it work with page builders? =

Yes. Because we fetch the rendered HTML, content from Elementor, Divi, WPBakery, Oxygen, Bricks, and other page builders is fully analyzed.

= Why is my thin content score different from other SEO plugins? =

Simplicity SEO Audit counts words in the rendered HTML content area, not just the database post_content. This includes product descriptions, related product sections, and other template-generated content. The word count threshold is 300 for posts/pages and 30 for taxonomy terms.

= What happens if a page cannot be fetched? =

Checks that require rendered page output are skipped for that URL. This avoids treating the database fallback as the final page when theme or page-builder content is unavailable. The scan continues with the other sampled pages.

= Will uninstalling the plugin leave data behind? =

No. When you delete (not just deactivate) the plugin, all scan results, tokens, and transients are removed from the database.

= Can I customize which taxonomies are high/medium/low priority? =

Yes. Use the `ssea_taxonomy_tier` filter:

`add_filter( 'msa_taxonomy_tier', function( $tier, $taxonomy, $post ) {
    if ( $taxonomy === 'brand' ) return 'high';
    return $tier;
}, 10, 3 );`

== Screenshots ==

1. Dashboard with SEO score and check results
2. Detailed issues list with URLs
3. HTML export report

== Changelog ==

= 2.0.6 =
* Use weighted RMS check deficits so large unresolved gaps have greater influence than small recommendations.
* Remove the second penalty for pages with findings and page-based grade ceilings; retain the confirmed site-wide crawler-block ceiling.
* Rebalance advisory penalties. SEO-plugin detection and robots.txt 404/410 no longer lower the score.
* Dashboard and exports explain the score's scope. A fresh scan is required after upgrading the scoring model.
* Fixed the scan-age display in non-UTC time zones and show the installed plugin version in the dashboard footer.
* Reduced the impact of editorial recommendations for metadata length, heading hierarchy, content length and internal links; purpose-aware exclusions for legal, account and form pages.
* Fixed decorative alt="" being reported as missing. Absent alt attributes remain findings; the report no longer implies full WCAG compliance.
* Sitemap checks use bounded GET requests, validate XML roots and discover nonstandard locations through robots.txt. Inconclusive requests remain unscored.
* Final scoring evaluates all saved page metrics together, fixing equal weighting of unequal scan batches and the denominator used by duplicate checks.
* Rendered missing titles and descriptions can no longer be concealed by database fallback values.
* Dashboard and exports identify partial audits and reports needing a fresh scan after scoring changes.
* Saved reports detect scoring-model changes even when the report layout version stays the same.
* Open Graph descriptions no longer conceal missing standard meta descriptions.
* HTTPS checks use the public site URL, avoiding false warnings from HTTP workers or reverse proxies.

= 2.0.5 =
* Fixed false “Missing H1” report cards when an existing H1 is followed by a skipped heading level. Missing, multiple, and hierarchy findings now have separate cards and affected-page lists.
* Fixed the same score-based mislabelling for short/long title tags and meta descriptions. Severity now follows the actual finding, not the aggregate score.
* Dashboard, HTML and CSV reports now share the same finding classification. Saved report cards are rebuilt from their original findings on read, without changing the scan date.
* Unavailable checks are shown as not evaluated and excluded from weighted scoring; fixed the Passed counter and mixed post-type labels.
* Missing robots.txt no longer means crawling is blocked. Inconclusive robots/sitemap responses are not reported as missing; added the WordPress core sitemap endpoint.

= 2.0.4 =
* Prevented false content-check findings when rendered page or body HTML is unavailable, including thin content, internal links, image alt text, titles, descriptions, and duplicate metadata.
* Canonical and OG/Twitter checks now inspect the rendered page head instead of inferring tags from an active SEO plugin.
* Technical HTTP checks no longer report missing schema, sitemap, or robots.txt when the server cannot reach its own URL.

= 2.0.3 =
* Fixed false “Missing H1” findings when the server cannot fetch a page's rendered HTML. Theme-generated H1s are no longer assessed from the raw database fallback.

= 2.0.2 =
* Fixed content extraction false positives: H1, thin content, internal links, and image alt checks now scan broader page wrappers (not only `.entry-content`)
* Skip empty `<main>` matches, expand narrow containers to include parent page titles, and preserve page-header H1s in body fallback
* WooCommerce/product wrappers (`#primary`, `#content`, `.entry-summary`, `.type-product`) are preferred before narrow editor blocks

= 2.0.1 =
* Enhanced Scoring Engine: calibrated realistic scoring with 75/25 content-to-technical weight split, preventing technical checks from masking content defects
* Site Health Ratio: score now incorporates the percentage of defect-free pages across sampled content
* Fixed Image Alt Text check threshold to ensure pages with missing alt attributes are properly reported
* Fixed Drawer issue mapping to accurately display only affected pages in the collapsible view
* Refined Heading check severity: missing H1 tags remain critical while hierarchy jumps are classified as warnings
* Truthful Grade Caps: enforced realistic quality ceilings preventing sites with recurring critical errors from receiving inflated grades

= 2.0.0 =
* Major UI Redesign: modern, high-contrast dashboard with clean card architecture, delicate colored status borders, and glowing shadows
* Real-time Interactive Scanning: batch controller with animated progress indicator and live batch status notifications
* Interactive Status Filtering: filter checks dynamically by Critical Errors, Warnings, and Passed checks directly from the Health Distribution card
* Detailed Page Drawer: collapsible drawer for all affected URLs with direct "Edit in WP" and "View" links
* CSV Spreadsheet Export: one-click CSV export with UTF-8 BOM encoding for full Microsoft Excel compatibility with international characters
* HTML Report Redesign: standalone report matches dashboard aesthetics with soft bordered cards and print-ready layout
* Fixed Permalinks routing: full Apache rewrite support for URL inspection links
* Streamlined WordPress Menu: clean 20x20 crisp icon and single-line "Simplicity SEO" label matching core admin styling
* Enhanced Scoring Engine: calibrated weighted averages aligned with industry standard SEO audit methodologies

= 1.2.4 =
* WooCommerce: product thin-content threshold lowered to 120 words (was 300)
* WooCommerce: product title minimum lowered to 15 chars; product tags are info-only
* Exclude cart, checkout, my-account, wishlist and similar utility pages from scoring
* Stronger title suffix stripping (site name + domain, even with extra branding text)

= 1.2.3 =
* Exclude theme layout CPTs (ThemeREX cpt_layouts, Impreza page blocks) from scan sampling
* Skip content checks for pages with rendered noindex in the HTML head
* Smarter robots.txt check: only flag Disallow: / under User-agent: *
* Title length checks ignore common site-name suffixes (e.g. " - Site Name")
* Duplicate title/description issues label Term IDs clearly (not negative post IDs)

= 1.2.2 =
* Fix false "Missing meta description" reports when Yoast/Rank Math templates (%%variables%%) are used — now reads the rendered HTML head like search engines do
* Title tag checks and duplicate detection also use rendered page titles when SEO plugin templates are in use

= 1.2.1 =
* Plugin Check / review: removed set_time_limit() calls from the scanner
* Plugin Check / review: HTML export loads CSS via wp_enqueue_style() / wp_print_styles(), not echoed style or link tags
* Updated Tested up to: 7.0

= 1.2.0 =
* Full internationalization — English default with Greek translation included
* All UI strings are now translatable via standard WordPress i18n
* Added languages/ directory with .pot template and Greek .po/.mo files
* Fixed CORS headers for REST API (moved to rest_pre_serve_request filter)
* Performance: cached site counter results to eliminate duplicate DB queries
* Performance: cached SEO plugin detection per request
* Performance: replaced ORDER BY RAND() with PHP shuffle for faster URL sampling
* Added scan duration notice ("This may take 1–3 minutes...")
* Fixed singular/plural for "pages need improvement"
* Improved CTA copy and label consistency across dashboard and export

= 1.1.0 =
* Added rendered HTML analysis — pages are fetched like a search engine, detecting theme H1s, page builder content, and shortcode output
* Added taxonomy-aware tiered scoring — product attributes get zero penalty, tags half penalty, categories full weight
* Fixed scoring to use ratio-based calculation instead of cumulative penalties — scores now reflect actual percentage of pages with issues
* Fixed Unicode word counting — Greek and other non-Latin languages are now counted correctly
* Added HTML report export button in the dashboard
* Added "X pages need improvement" messages on each check
* Added score cap at 99 when issues exist — 100 means truly perfect
* Fixed admin notices from other plugins overlapping the dashboard
* Added uninstall.php to zip for clean data removal
* Improved content area extraction with semantic HTML selectors (main, article, role="main")
* Heading and internal links checks now skip taxonomy terms (theme-generated, not editorial)
* Duplicate detection skips low-priority taxonomy terms

= 1.0.0 =
* Initial release
* 17 SEO checks (10 content + 7 technical)
* 4-batch scanning process for up to 200 pages
* Weighted scoring with letter grades
* WooCommerce and taxonomy term support
* REST API with token authentication
* Yoast SEO, Rank Math, and SEOPress integration
* Proportional sampling across content types
* Noindex page filtering
