PHPackages                             anvildev/craft-simple-seo - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. anvildev/craft-simple-seo

ActiveCraft-plugin

anvildev/craft-simple-seo
=========================

Simple SEO fields for Craft CMS — meta title &amp; description, social image, canonical, robots, and an XML sitemap

1.0.2(yesterday)01↓50%[1 PRs](https://github.com/anvildevxyz/craft-simple-seo/pulls)proprietaryPHPPHP ^8.2CI passing

Since Aug 16Pushed todayCompare

[ Source](https://github.com/anvildevxyz/craft-simple-seo)[ Packagist](https://packagist.org/packages/anvildev/craft-simple-seo)[ RSS](/packages/anvildev-craft-simple-seo/feed)WikiDiscussions main Synced today

READMEChangelog (2)Dependencies (8)Versions (4)Used By (0)

Simple SEO
==========

[](#simple-seo)

Simple SEO fields for Craft CMS — meta title, description, social image, canonical, robots, and an XML sitemap. Nothing else.

The maintained, lightweight alternative for small Craft sites, with a [one-command migration from ether/seo](docs/migrating-from-ether-seo.md).

**[Documentation →](docs/README.md)**

Install
-------

[](#install)

```
composer require anvildev/craft-simple-seo
php craft plugin/install simple-seo
```

Then add an **SEO** field to the entry types you want editors to control, and render the tags with the one-liner below. `/sitemap.xml` and `/robots.txt` work with zero configuration.

Scope charter
-------------

[](#scope-charter)

Simple SEO stays small on purpose — that's the product, the price, and the support model. Feature requests outside the charter are closed with a pointer, not implemented.

**In scope:**

- SEO field type: meta title, description, social image, per-entry robots (noindex/nofollow plus the full directive set), canonical override
- Live SERP + social preview (fully client-side)
- One-line Twig meta rendering (title, description, canonical, robots, Open Graph, Twitter)
- Canonical URLs (link tag + optional header, always in agreement)
- Robots handling that can never de-index a site by accident, plus a per-site, CP-editable `robots.txt`
- Permission-based access, so a non-admin SEO role can own the settings (robots.txt gated separately)
- XML sitemap: multi-site, cached, never silently empty
- GraphQL read access to field values and resolved meta

**Out of scope, permanently:**

- **Redirects** → use [Retour](https://plugins.craftcms.com/retour). The Ether SEO migration exports redirect data as a Retour-importable CSV.
- **Content analysis / focus keywords** → intentionally absent; it's the most fragile, support-heavy part of every SEO plugin.
- **Structured data / schema builder, llms.txt, GEO** → use [Beacon](https://plugins.craftcms.com/beacon).

Usage
-----

[](#usage)

Add the SEO field to your entry types, then render everything with one line in your layout's ``:

```
{{ craft.simpleSeo.renderMeta(entry) }}
```

That outputs the ``, meta description, canonical, robots (only when set — absent means index,follow), Open Graph, and Twitter tags, with the full fallback chain applied (field value → per-site default → entry title). Per-template overrides:

```
{{ craft.simpleSeo.renderMeta(entry, { ogType: 'article' }) }}
```

Headless? The same resolved data as an array:

```
{% set meta = craft.simpleSeo.resolveMeta(entry) %}
```

Or over GraphQL — `simpleSeo` on any entry/category is the fully resolved meta, and the field itself supports sub-selections:

```
{
  entry(uri: "about") {
    simpleSeo { title description canonical robots ogImageUrl twitterCard }
    seo { title noindex socialImageUrl }   # raw field value
  }
}
```

The `/sitemap.xml` and `/robots.txt` routes are controller-backed (no templates involved), so they keep working in `headlessMode`.

Configuration
-------------

[](#configuration)

Create `config/simple-seo.php` to override config-level settings:

```
return [
    // Emit the Link: ; rel="canonical" header (always identical to the tag).
    'canonicalLinkHeader' => true,

    // Query params kept on element-derived canonical URLs (default: all stripped).
    'canonicalAllowedQueryParams' => ['category'],

    // Hide a whole environment from search engines (staging). Config-file only,
    // deliberately no CP control. Forces noindex/nofollow meta + X-Robots-Tag on
    // every front-end response, disallows everything in robots.txt, and shows a
    // persistent CP warning banner while active.
    'siteWideNoindex' => App::env('CRAFT_ENVIRONMENT') !== 'production',
];
```

With `siteWideNoindex` at its default (`false`), the plugin **cannot** emit a site-wide noindex — no CP setting, save, or template call can cause it. This invariant is enforced by tests.

The plugin also serves an environment-aware `/robots.txt` (a physical `web/robots.txt` always wins over the route).

Sitemap
-------

[](#sitemap)

`/sitemap.xml` works with zero configuration: every section with URLs is included, entries marked noindex are excluded, multi-site entries carry hreflang alternates, and files are cached until an entry or section changes. Per-site section toggles and an optional per-section `` live on the Sitemap settings screen.

When something's missing, nothing is ever silently empty: empty sitemap files carry an XML comment explaining why, and anyone with **Access Simple SEO** can open `/sitemap.xml?explain` for the full per-section diagnosis.

Canonical behavior: UTF-8 slugs are always percent-encoded, paginated pages canonicalize to themselves, and author-entered canonical overrides keep their query params verbatim.

Migrating from Ether SEO
------------------------

[](#migrating-from-ether-seo)

```
php craft simple-seo/migrate/ether           # dry run — reports everything, writes nothing
php craft simple-seo/migrate/ether --apply   # migrate for real
```

The migration converts every ether SEO field **in place** (same field ID/UID/handle — your field layouts keep working untouched), mapping titles, descriptions, social images, robots, and canonicals per site. Ether's redirects are exported as a Retour-importable CSV (`--csv=path` to choose where). Focus keywords are dropped — Simple SEO has no content analysis on purpose — and the report says exactly how many. Re-running is always safe: already-migrated values are recognized and skipped.

Requirements
------------

[](#requirements)

- Craft CMS 5.0+
- PHP 8.2+

Development
-----------

[](#development)

```
composer install
composer check              # ECS + PHPStan + unit tests
composer test:integration   # Codeception integration suite (needs a test DB — see tests/.env)
```

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 90.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/14887bb1919bab144c90ac942f29dbf70f1815401409812191a6a87a871cea2f?d=identicon)[anvildevxyz](/maintainers/anvildevxyz)

---

Top Contributors

[![anvildevxyz](https://avatars.githubusercontent.com/u/263022857?v=4)](https://github.com/anvildevxyz "anvildevxyz (10 commits)")[![fabianhaef](https://avatars.githubusercontent.com/u/55360588?v=4)](https://github.com/fabianhaef "fabianhaef (1 commits)")

---

Tags

cmsCraftcraftcmsSitemapseometa

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/anvildev-craft-simple-seo/health.svg)

```
[![Health](https://phpackages.com/badges/anvildev-craft-simple-seo/health.svg)](https://phpackages.com/packages/anvildev-craft-simple-seo)
```

###  Alternatives

[nystudio107/craft-seomatic

SEOmatic facilitates modern SEO best practices &amp; implementation for Craft CMS 5. It is a turnkey SEO system that is comprehensive, powerful, and flexible.

1741.5M73](/packages/nystudio107-craft-seomatic)[verbb/formie

The most user-friendly forms plugin for Craft.

101400.6k78](/packages/verbb-formie)[vaersaagod/seomate

SEO, mate! It's important.

4443.4k3](/packages/vaersaagod-seomate)[verbb/hyper

A user-friendly links field for Craft.

24153.5k14](/packages/verbb-hyper)[verbb/vizy

A flexible visual editor field for Craft.

4251.5k1](/packages/verbb-vizy)[verbb/events

A full-featured plugin for event management and ticketing.

2312.1k](/packages/verbb-events)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
