Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Seo Pro Laravel Package

statamic/seo-pro

SEO Pro is a comprehensive SEO addon for Statamic. It adds an intuitive SEO fieldtype for meta titles and descriptions, Open Graph and Twitter Card tags, XML sitemaps, redirects, canonical URLs, and social image support, helping you improve search visibility without leaving the control panel.

View on GitHub
Deep Wiki
Context7

Getting Started

Prereqs, in the order they actually bite:

  1. Match Statamic major to addon major. The 7.x line targets a specific Statamic major; pairing a v7 addon with an older Statamic (or the inverse) is the single most common install failure. Check composer.json constraints and the release tag before running composer require.
  2. PHP version alignment against that same constraint block.
  3. A license key from your statamic.com account — this is a commercial addon, not a free one.

Install and wire the license:

composer require statamic/seo-pro

Statamic auto-discovers addons; there's no service provider to register by hand. Put the license key in .env (the STATAMIC_SEO_PRO_LICENSE_KEY-style variable the docs specify) and clear config cache. If the CP still shows an unlicensed banner, you have a cached config, not a bad key.

Publish and read the config first. It's the map of the whole package:

php artisan vendor:publish   # choose the SEO Pro provider/tag

Skim config/seo-pro.php for the sitemap, redirects, reports/queue, social-preview, and cascade sections. Every behavior discussed below is downstream of a key in that file.

Attach it to content — one collection, not all of them. In the CP, open a blueprint and import the shipped SEO fieldset (or add the seo_pro fieldtype manually if you need a trimmed field set). Resist sweeping every blueprint on day one; you want one worked example before you commit the content model.

Render the head centrally. Drop the package's tag ({{ seo_pro }}, or the split variants like {{ seo_pro:meta }} where your version exposes them) into your layout <head>, and remove any hand-written <title> / <meta name="description" /> you already had. Leaving both in place ships duplicates that are invisible in the CP preview and obvious in a SERP.

First use case that proves the whole stack (15 minutes):

  1. Pick your posts/blog collection; publish one entry with a meta title and description set in the CP.
  2. View source (not DevTools) and confirm title, description, canonical, and OG tags render.
  3. Hit /sitemap.xml — the entry appears; a draft or noindexed entry does not.
  4. Create one 301 redirect and verify it in a private window.

That loop surfaces version mismatch, license, and cache problems immediately, before you've multiplied them across ten blueprints.

Implementation Patterns

Blueprint pattern: import the fieldset, don't hand-roll the fields. The shipped fieldset is what the upgrade paths assume. When you need control over which source fields feed the title/description, configure the fieldtype's source selectors rather than duplicating field definitions per blueprint — one place to change beats ten.

Lean on the cascade; don't repeat yourself. Site defaults → collection defaults → entry override. Set title/description templates and social defaults once at site level, narrow them per collection, and only fill entry fields where an editor genuinely needs a custom value. Two rules keep this sane:

  • Never copy inherited values down into entries "just in case" — they freeze and stop tracking the cascade.
  • An empty field falls back. Removing an inherited value requires an explicit override, not a blank.

Render the head once, and handle the routes SEO Pro doesn't own. Entry and term routes work because there's an implicit cascade context. Custom routes, error pages, and controller-rendered views fall back to defaults — so guard the tag and provide a fallback <title>. This is the most common "why is this page's SEO garbage" ticket on a real site.

Multisite is its own path — test it as one. Configure defaults per site rather than globally, verify canonical and hreflang output per locale, and check each site's sitemap individually. Never infer multisite correctness from a single-site smoke test: #688 (a v7.15.1 fix for editing entries without URLs in multisite) is direct evidence that this path has edge cases the single-site path never hits.

Redirect drivers: choose deliberately.

  • File-based is fine, diffable, and version-controllable — good default for a small, stable redirect map.
  • Database driver is the better fit when editors own thousands of records and you want queryable history.

Enable auto-creation on slug change where your version exposes it; it quietly solves the "renamed the entry, broke every inbound link" problem. Bulk-import your legacy redirect map once (a seeder/migration against the active driver), then let the CP own it from there.

Sitemap: opt in per collection, not globally. Verify noindexed entries stay out. For custom routes that deserve inclusion (a product landing page, a docs section outside the collections), add them through config rather than generating a second sitemap and submitting two properties.

Queue discipline for reports. Report cost scales with entries × fields × locales. Past a few hundred entries, run report generation through the queue (deferred or background) so it doesn't block editor saves, keep a worker running, and schedule regeneration rather than relying on editors to press the button. Note that #686 is the line in the sand: under those drivers, errors were previously not recorded at all — so the driver choice now also determines whether you can see failures.

Headless / content API. SEO data lives in the entry's seo field and does not magically arrive in your API resource in the shape your front end wants. Budget an explicit work item: include the field in the resource/transformer, then map it to <title>, meta description, OG tags, and canonical in the consuming app. No patch release fixes this gap for you — it's an integration task, not a bug.

Local/staging safety: force noindex outside production via config or a globals-level switch. Two minutes of work that prevents staging outranking production.

Testing is what makes patch bumps routine. Feature-test the rendered head (assert title, description, canonical, and the og: tags for a known fixture) and snapshot the sitemap for that same fixture. With that harness, a version bump is a diff instead of a leap of faith — which matters because this addon ships frequently.

Gotchas and Tips

  • Version matrix first, every time. Write the supported Statamic-major ↔ addon-major pairing into your runbook. The next developer will not guess it correctly, and this is the #1 install failure.
  • Expect an error influx right after upgrading past v7.15.1. #686 means errors under deferred/background were previously swallowed. A sudden spike in the report is a correctness fix surfacing old problems, not a regression — brief stakeholders before deploying so nobody rolls it back.
  • Retire multisite workarounds. #688 fixed editing entries without URLs (container/structured-only content) in multisite. Any guard code or editorial process built around that bug is now dead weight; delete it.
  • Re-merge CP customizations and translation overrides after upgrading. #690 touched report status colors and dark-mode values; #682 touched German. If you run a custom CP theme or have files under lang/vendor/seo-pro, diff them on every release.
  • Debug in view source, not DevTools. DevTools shows the post-JS DOM; if your front end rewrites meta tags, the head you're inspecting is not the one crawlers get. And when a report never completes, check the queue's failed_jobs table — the job died, not the addon.
  • Static caching vs. redirects. With Statamic's static cache, a stale cache can serve a 200 for a URL you just redirected. Ensure redirect handling runs before the static cache and clear the cache when redirects change.
  • Redirect hygiene: absolute destinations, no self-referencing redirects, no chains, and be explicit about www vs. non-www and trailing slashes. Loops are almost always host/proxy config, not the addon.
  • Social preview images are expensive. Generation needs headless Chrome (Browsershot/Puppeteer). Keep it queued and cached, never on the request path, and verify the worker host actually has the binary — a worker without it fails silently in the queue.
  • Don't squat on seo / seo_pro as field handles. Collisions present as confusing fallback behavior rather than errors, which is far worse to debug.
  • Extension points are the buy-vs-build gate. Custom cascade classes, custom sitemap URLs, and view overrides cover most needs. If your content model needs bespoke scoring rules beyond what's exposed, you're one step from a fork — validate that surface during the trial, because forking defeats the reason you bought it.
  • Know the license-lapse behavior explicitly. Establish whether expiration degrades reporting, blocks CP editing, or only stops updates, and model that into your risk register.
  • Clear caches after every config change. php artisan config:clear && php artisan cache:clear. Half the "it's ignoring my setting" reports die here.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource