mitydigital/sitemapamic
Sitemapamic is a Laravel package for generating and serving XML sitemaps. Define URLs or Eloquent models, configure priorities and change frequencies, and output sitemap files or indexes to help search engines discover your site's content.
composer require mitydigital/sitemapamic
php artisan vendor:publish --tag=sitemapamic-config # check the exact tag in the README
php artisan config:clear && php artisan cache:clear
Statamic auto-discovers the addon through Composer, so there is normally nothing to add to config/statamic/addons.php. The two places to look first:
config/sitemapamic.php — the route/path of the generated XML, caching behaviour, and the shape of the sitemap definitions. This is the file you will actually version-control and diff in code review.First use case, in order:
pages collection (and blog/posts if you have one), leave taxonomies off until you've confirmed their routes resolve./sitemap.xml in the browser and confirm you get XML, not a 404 or a Statamic page.curl -sI https://your-site.test/sitemap.xml and check the content type is application/xml or text/xml.Sitemap: https://your-site.test/sitemap.xml to robots.txt, then submit in Search Console.Because the package is small (15 stars, no dependents), read the source in vendor/mitydigital/sitemapamic/src once. It's a few hundred lines and you'll answer most of your own questions faster than the docs will.
Config-as-code. Do the initial setup in the CP, then commit the resulting config/sitemapamic.php and do all subsequent changes in the file. This keeps sitemap shape reviewable in PRs and avoids the classic "works on my machine because I clicked a toggle in production" problem.
Per-entry overrides via blueprint fields. Rather than one global changefreq/priority, add optional fields to your entry blueprints — e.g. sitemap_priority (select: 0.1–1.0) and sitemap_changefreq (select: always/hourly/daily/weekly/monthly/yearly/never) — and an sitemap_exclude toggle. Editors then control the exceptions; the collection default handles the 95% case. Always ship an exclusion toggle: an entry marked noindex in your SEO fieldset but still listed in the sitemap is an active contradiction you'll get flagged for.
Multi-site. Generate one sitemap per site and let the package emit an index, or point each site's robots.txt at its own sitemap URL. Don't try to express hreflang through sitemaps — that belongs in the HTML <head>. Sanity check each site's XML separately; a missed site config is the most common multi-site bug here.
Caching and invalidation. Rely on the package's save/delete hooks for normal editorial publishing. They will not fire for content created outside the entry lifecycle — imports (php artisan import:*), direct DB writes, Artisan commands that touch entries, or API-driven headless flows. After any of those, clear the cache explicitly (or hit the sitemap URL to force regeneration) as part of your deploy/import script, not as an afterthought.
Play nicely with static caching. If you use Statamic's static caching or a CDN, either exclude the sitemap route from the cache or add it to your warmer. A statically cached sitemap.xml from three deploys ago is the single most common "why isn't Google seeing my new pages" ticket.
Custom URLs. Anything not backed by an entry or term — paginated archive pages (/blog/page/2), Livewire/Algolia search results you actually want indexed, legacy redirect targets that 200 — goes in through the utility's custom URL mechanism rather than by hacking the XML view. Keep that list short and documented, because nothing will regenerate it for you when a route changes.
Testing loop. curl -s https://site.test/sitemap.xml | xmllint --noout - catches malformed output instantly. For content checks, grep for a slug you just published; for absence checks, grep for a draft's slug and confirm zero hits.
routes/web.php sitemap, or an SEO addon (SEO Pro / Meta) that also wants to own /sitemap.xml, will silently win or lose depending on registration order. Pick exactly one owner. php artisan route:list | grep -i sitemap tells you who actually answered.lastmod lies. It generally comes from the entry's updated timestamp. Bulk imports that set updated_at to now, or content tweaks that don't touch the entry, produce a sitemap that either spams lastmod on every URL or never changes it. If lastmod is unreliable, consider omitting it — Google ignores it when it's wrong, and wrong data is worse than absent data.wget --spider or Screaming Frog before submitting; 404s in a sitemap are a quality signal against you.php artisan cache:clear, check the static cache directory/static_caching config, check the CDN, then check the package cache key. If the XML still won't change, add a temporary dump in the vendor controller to confirm the route is even hitting the package.How can I help you explore Laravel packages today?