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

Seotamic Laravel Package

cnj/seotamic

Seotamic is a Laravel package for managing SEO metadata across your app. It helps you define titles, descriptions, Open Graph and Twitter card tags, and canonical URLs for pages and Eloquent models, making it easy to improve search visibility and social sharing with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require cnj/seotamic
php artisan vendor:publish --tag=seotamic-config   # inspect the tag list in the README if this misses

Statamic addons are auto-discovered, so there is no provider registration step. Open config/seotamic.php immediately — for a 21-star addon the config file is the real documentation.

Where to look first, in order

  1. config/seotamic.php — defaults, enabled features (sitemap, OG, Twitter, robots), route/URL settings.
  2. vendor/cnj/seotamic/resources/views/ — the head-rendering partial/tag. Read it before you use it; you will almost certainly override it.
  3. vendor/cnj/seotamic/src/Fieldtypes/ — how SEO data is stored (a single seo array field vs. flat handles). This dictates your blueprint work.
  4. vendor/cnj/seotamic/routes/ — whether the sitemap/robots endpoints are registered automatically or need publishing.

First use case (the 30-minute win)

Add the package's SEO fieldset to one collection, render the head partial in your layout, and confirm output in view source.

# resources/blueprints/collections/pages/pages.yaml
import:
  - seotamic/seo   # confirm the exact fieldset handle in the package's resources/fieldsets
{{# resources/views/layout.antlers.html #}}
<head>
  <title>{{ seo:title ?? title }} — {{ site:name }}</title>
  {{ seotamic }}   {{# exact tag name from the README — verify #}}
</head>

Then hit a page, view source, and check that meta title, description, canonical, and OG tags are present and not HTML-escaped. Only after that works should you enable the sitemap and point Google Search Console at it.


Implementation Patterns

Blueprint-per-collection with a shared fieldset

Keep the SEO fields in one fieldset and import it into every indexable collection. This is the only sane way to keep handle names consistent, because the package's rendering partial expects specific handles.

# resources/fieldsets/seo.yaml  (your wrapper, not the package's)
title: SEO
fields:
  -
    import: seotamic/seo

If you need per-collection control (e.g. no OG image on products), wrap the import and add/remove fields locally rather than editing the vendor fieldset.

Globals for site-wide fallbacks

The common production pattern is: entry-level SEO → collection default → global default → Statamic entry title. Put the middle two in a seo_defaults global set and resolve the chain in your own partial, not in the package, so the precedence is visible in your repo:

{{ seo:meta_title
   ?? seo_defaults:meta_title
   ?? title }}

Multisite

Statamic's cascade/localization means SEO fields are per-site automatically. Two things to verify yourself: (a) whether the sitemap emits one file per site or one combined file, and (b) whether hreflang is generated. If hreflang is missing, add it manually in the layout using {{ sites }} — don't wait on the addon.

Sitemap integration

Enable the route in config, then exclude non-indexable content explicitly. The reliable pattern is to drive both <meta name="robots"> and sitemap inclusion from the same field, so a noindex entry can never appear in the sitemap:

{{ if seo:noindex }}
  <meta name="robots" content="noindex,follow">
{{ /if }}

Check whether the addon already does this; if it does, do not duplicate the tag.

Rendering OG/JSON-LD safely

If the package outputs JSON-LD through an Antlers tag, confirm it is not entity-encoded. If it is, publish and override the view rather than adding |raw at the call site — |raw on a whole tag will also unescape user-supplied descriptions.

Testing

Assert on rendered HTML in a feature test. This is cheap and catches the most common failure (empty SEO fields silently rendering <title> — Site Name</title>):

$this->get('/about')
    ->assertSee('<meta property="og:title"', false)
    ->assertSee($entry->get('seo')['meta_title'], false);

Gotchas and Tips

It is a small package — pin it and read the source. 21 stars and zero dependents means you are the QA team. Use an exact version constraint ("cnj/seotamic": "1.2.3"), commit composer.lock, and skim the diff before every composer update. Budget an hour to read src/ end to end; it is a small addon and this is faster than debugging it blind.

Statamic v4 only. The description is explicit, and the v4→v5 fieldtype/asset API changes are exactly the kind that break SEO addons (asset container methods, Augmented interfaces). Do not assume it works on v5 — test on a branch before you upgrade Statamic.

Don't run two SEO addons. If the project already has statamic/advanced-seo or hand-rolled SEO fields, rip one out. Duplicate og:title and conflicting canonical tags are worse than either addon alone, and the conflict is invisible in the Control Panel.

Config and stache caching. After changing config/seotamic.php or blueprints:

php artisan config:clear
php artisan statamic:stache:clear
php artisan cache:clear

Blueprint changes not appearing in the CP is almost always a stale stache, not a bug in the addon.

Empty-string vs. null. Antlers ?? only falls through on null/missing, not "". A saved-but-blank SEO field will render <meta name="description" content=""> and suppress your fallback. Normalize in your partial with {{ if seo:description }}…{{ /if }} before defaulting, or use :| style trimming if the fieldtype returns a string.

OG image is an asset, not a URL. If the field is an assets fieldtype, {{ seo:og_image }} gives you an ID or an augmented asset depending on config. Use {{ seo:og_image:url }} and guard for the empty case; a missing OG image is a silent social-sharing failure that only shows up when someone shares the page.

Static caching and CDNs. If you use Statamic's static cache or a CDN in front, meta tags are baked at build time. Editing an entry's SEO fields invalidates the Statamic cache but may not purge your CDN — wire the purge into the entry saved event.

Canonical on paginated and filtered pages. Pagination (?page=2) and any query-string filtering should either canonical to the base URL or self-canonicalize deliberately. Addon defaults are usually naive here; set the canonical manually in the layout for listing pages.

Extension points to prefer. Published views and config first, custom Antlers tag second, event listener on Statamic\Events\EntrySaved third. Avoid editing vendor/ — with a package this small you will be upgrading often, and a fork means you own the maintenance.

Debugging checklist when tags don't appear: is the field actually in the blueprint for that collection → is the entry saved with values → is the tag inside <head> and not swallowed by a conditional → is the published view overriding the package view with an out-of-date signature → clear stache. That order resolves nearly every report.

Upgrade risk is front-loaded. With a 2026 last-release date and low adoption, treat minor bumps as potentially breaking. Keep the sitemap and head-rendering views overridden in your own repo so a bad release degrades to "old markup" rather than "blank <head>".

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core