Upgrade 2.0 to 3.0
Upgrade from Advanced SEO 2.0 to 3.0. Most breaking changes are handled by automated upgrade scripts.
Advanced SEO 3.0 introduces a significant internal refactor that improves the architecture, maintainability, and user experience of the addon. Most breaking changes have automated upgrade scripts, so the upgrade should be seamless for most users. First read through this guide to see if there's anything you need to adjust. Most items only apply if you've customized blueprints, published views, or written custom code against the GraphQL or sitemap APIs.
Upgrade using Composer
In your composer.json, change the requirement from:
- "aerni/advanced-seo": "^2.0"
+ "aerni/advanced-seo": "^3.0"Then run:
composer update aerni/advanced-seo --with-dependenciesAutomated upgrade scripts should run right after installation. If they don't trigger, see Troubleshooting.
Upgrade Summary
The following changes require manual action. All other changes are handled automatically.
High Impact Changes
Requirements
PHP 8.4+
Laravel 12+
Statamic 6+
Screenshot Package
Affects users of the social images generator.
The social images generator now uses spatie/laravel-screenshot and is no longer bundled as a dependency. This package supports Browsershot and Cloudflare Browser Rendering as screenshot drivers.
To restore existing functionality, require both the screenshot package and Browsershot:
Alternatively, you can use Cloudflare Browser Rendering instead of Browsershot. Refer to the installation guide for details. To customize screenshot settings, publish the config:
Blueprint Customization Removed
Affects users who customized Advanced SEO fieldsets or used the advanced_seo fieldtype in their blueprints.
Support for blueprint customization has been removed. This includes:
The Advanced SEO fieldsets (e.g.
Advanced SEO (Main),Title & Description,Open Graph, etc.) that could be edited to customize which fields appear in the SEO tabThe Advanced SEO fieldtype (
advanced_seo) that allowed placing individual SEO fields anywhere in a blueprint
Remove any advanced_seo fieldtype fields from your blueprints and delete any customized Advanced SEO fieldsets. The SEO tab fields are now managed entirely by the addon and cannot be customized.
Medium Impact Changes
GraphQL
Affects users of the GraphQL API. All GraphQL changes require updating your queries.
Renamed Query and Types
The seoDefaults query has been renamed to seoSet:
All type names have been updated to use "Set" instead of "Defaults":
siteDefaults
siteSet
contentDefaults
collectionSet / taxonomySet
Flattened Site Set Structure
The siteDefaults type previously contained nested sub-types. These have been consolidated into a single flat siteSet type:
Removed seoSet Fields
The following fields have been removed from the siteSet type as they are now configured per collection/taxonomy:
excluded_collectionsexcluded_taxonomiessocial_images_generator_collections
Disabled Features
Fields belonging to disabled features are now completely removed from the schema. Previously, disabled feature fields were still present but returned null. Now, if a feature is disabled in config/advanced-seo.php, its fields will not appear in the schema at all.
Removed baseUrl Argument
The baseUrl argument has been removed from the seoMeta query. To rewrite absolute URLs for headless setups, configure your frontend domain in Statamic's sites configuration (resources/sites.yaml) instead.
computed Field Changes
Added
twitter_card
Returns the card size (summary or summary_large_image)
Removed
title
Use raw data title field
Removed
og_title
Use raw data og_title field
Removed
twitter_title
Use raw data og_title field
Removed
twitter_image
Use raw data og_image field
Removed
og_image
Use raw data og_image field
Removed
generated_og_image
Use raw data og_image field
siteSet Field Changes
Added
twitter_card
Returns the card size (summary or summary_large_image)
Renamed
title_separator → separator
Renamed
cloudflare_web_analytics → cloudflare_beacon_token
More descriptive name
Renamed
google_tag_manager → gtm_container_id
More descriptive name
Removed
nofollow
Now per-collection/entry only
Removed
use_fathom
Check fathom_id presence instead
Removed
use_cloudflare_web_analytics
Check cloudflare_beacon_token presence instead
Removed
use_google_tag_manager
Check gtm_container_id presence instead
Removed
twitter_summary_image
Use og_image
Removed
twitter_summary_large_image
Use og_image
seoMeta Raw Type Field Changes
Removed
site_name_position
Composed into title
Removed
twitter_card
Use seoSet { site { twitter_card } } or seoMeta { computed { twitter_card } }
Removed
twitter_title
Use og_title
Removed
twitter_description
Use og_description
Removed
twitter_summary_image
Use og_image
Removed
twitter_summary_large_image
Use og_image
Removed
sitemap_priority
Google and Bing ignore this value
Removed
sitemap_change_frequency
Google and Bing ignore this value
collectionSet and taxonomySet Field Changes
Removed
site_name_position
Composed into title
Removed
twitter_card
Use seoSet { site { twitter_card } } or seoMeta { computed { twitter_card } }
Removed
twitter_title
Use og_title
Removed
twitter_description
Use og_description
Removed
twitter_summary_image
Use og_image
Removed
twitter_summary_large_image
Use og_image
Removed
sitemap_priority
Google and Bing ignore this value
Removed
sitemap_change_frequency
Google and Bing ignore this value
Removed
canonical_type
Per-entry/term only (still on seoMeta)
Removed
canonical_entry
Per-entry/term only (still on seoMeta)
Removed
canonical_custom
Per-entry/term only (still on seoMeta)
seoSitemaps Query
The seoSitemaps query has been completely restructured for a simpler, flatter API:
Key changes:
siteis now a required query argument (was optional on nested fields)typeargument (collection,taxonomy,custom) replaces the nested fieldsbaseUrlhas been removed. Configure your frontend domain inresources/sites.yamlinstead.Returns a list of sitemaps with
id,type,handle,lastmod, and nestedurlsarray
Custom Sitemap Registration
Affects users who registered custom sitemaps.
The custom sitemaps API has been reworked. Closure-based registration via Sitemap::register() is no longer supported. Custom sitemaps now explicitly declare their site using the $site property, and the sitemap index automatically includes them. The site defaults to the default Statamic site if not set.
Inline Sitemaps
Drop the Sitemap::register() closure wrapper and call register() directly on the sitemap:
Class-Based Sitemaps
Class-based sitemaps now extend CustomSitemap instead of BaseSitemap. Define the $handle and $site as properties and use $this->makeUrl() instead of the facade:
You can register class-based sitemaps in a service provider or via the config:
See Custom Sitemaps for the full API reference.
Events
Affects users listening for SeoDefaultSetSaved.
The SeoDefaultSetSaved event has been renamed to SeoSetLocalizationSaved. The public property has been renamed from $defaults to $localization.
New events have been added:
SeoSetConfigSaved— Fired when a set's configuration is savedSeoSetConfigDeleted— Fired when a set's configuration is deletedSeoSetLocalizationDeleted— Fired when a localization is deleted
Low Impact Changes
Custom Views
Affects users who published or customized the _twitter.antlers.html or _analytics.antlers.html snippets.
Update the following references:
seo:twitter_title
seo:og_title
seo:twitter_description
seo:og_description
seo:twitter_image
seo:og_image
seo:twitter_image:alt
seo:og_image:alt
seo:cloudflare_web_analytics
seo:cloudflare_beacon_token
seo:google_tag_manager
seo:gtm_container_id
Unified Social Image Field
Affects users who published or customized views referencing seo:generated_og_image.
The seo_generated_og_image field has been removed. The seo_og_image field now handles both generated and user-defined images automatically based on the seo_generate_social_images toggle state.
When the toggle is enabled, seo_og_image returns the generated image. When disabled, it returns the user-defined image.
Update any views that reference seo:generated_og_image to use seo:og_image.
Generator Config Changes
Affects users who published config/advanced-seo.php with the generate_on_save option.
The generate_on_save option has been removed from the generator config:
Remove this option from your published config file if present.
Social image generation now works as follows:
After saving — Images are generated using Laravel's
defer(), which runs after the response is sent (sync driver) or dispatches a queued job. Content hashing ensures images are only regenerated when content actually changes.On demand — If a generated image is missing, it will be regenerated on-the-fly on the next frontend request.
Removed Twitter Image Generation
Affects users with custom social images generator themes.
The social images generator no longer generates separate Twitter images. Only the Open Graph image is generated. The twitter_summary and twitter_summary_large_image config presets are still used to resize the shared image for the Twitter meta tags via Glide, but no separate images are generated.
Remove the twitter_summary.antlers.html and twitter_summary_large_image.antlers.html templates from your custom themes. Only open_graph.antlers.html is used.
Template Changes
Affects users whose social image templates reference the $group variable.
The $group variable has been removed from the data passed to social images generator templates. If your templates reference this variable, update them.
Image Storage Directory
Affects users of the social images generator.
Generated social images are now stored in social_images/collection-{handle}/ and social_images/taxonomy-{handle}/ subdirectories instead of social_images/{handle}/. This adds support for taxonomy terms and avoids collisions between collections and taxonomies with the same handle.
Existing images in the old directory structure will not be migrated automatically. They will be regenerated in the new location on the next save or frontend request. You may delete the orphaned images in the old directories.
Twitter Card Setting
Affects users who previously set the X (Twitter) card size to summary (Small) on any entry, term, or collection/taxonomy default.
The X (Twitter) card size is no longer configurable per entry, term, or collection/taxonomy. It has been moved to the site defaults and applies globally. The default card size is summary_large_image (Large). If you previously used summary (Small), set your preferred card size in the site defaults after upgrading.
Automated Changes
Everything in this section is handled by upgrade scripts. No action required. These changes are documented for reference.
Pro Edition
Existing users are automatically upgraded to the Pro edition by adding 'aerni/advanced-seo' => 'pro' to config/statamic/editions.php. This preserves full feature access since Advanced SEO 2.0 didn't have a free edition.
Permissions
The permission system has been simplified. Old granular permissions have been replaced with three new permissions:
configure seo— Full access to all SEO settings, defaults, and content editingedit seo defaults— Edit collection and taxonomy defaultsedit seo content— Access the SEO tab on entries and terms
All existing roles receive the edit seo content permission to maintain backward compatibility.
Single-Site Data Structure
Single-site installations now use the same data structure as multi-site, with site-scoped localization files:
Site SEO Sets
The five separate site SEO sets (site::general, site::indexing, site::social_media, site::analytics, site::favicons) have been consolidated into a single site::defaults set, with tabs providing the UI grouping. For file-based installations, the file structure has changed accordingly:
Disabled Collections and Taxonomies
The disabled configuration option has been removed from config/advanced-seo.php. Collections and taxonomies are now disabled individually through the Control Panel via the "Configure" button on each set.
Localization Origin Field
The origin field has been removed from localizations. Origin configuration is now stored centrally in the set config using an origins array.
Eloquent Driver
The advanced_seo_defaults table has been replaced by seo_set_localizations. A new seo_set_configs table stores configuration data (enabled state, origins, etc.). New migrations are published and run automatically, and the old table is dropped after data is migrated.
SEO Field Values
Simplified Field UI
The SEO source fields have been simplified from a three-state toggle (Auto/Default/Custom) to a two-state inheritance model. Fields are now either inherited (showing the default value) or custom (user-set value). The toggle has been removed. Transitioning between states now happens implicitly through editing and a Reset action.
Field Handle Syntax Replaced
The @field:handle syntax for referencing other fields has been replaced with standard Antlers {{ handle }} syntax. You can now use the full power of Antlers in your SEO fields, including modifiers like {{ content | truncate(90, '...') }}. The @auto and @null sentinel values are also migrated.
Site Name Position Composed into Title
The seo_site_name_position field has been removed. Its value is composed directly into the seo_title field using Antlers syntax, giving you full control over the title format:
Position
Resulting seo_title
start
{{ site_name }} {{ separator }} {{ title }}
end
{{ title }} {{ separator }} {{ site_name }}
disabled
{{ title }}
Title Separator Renamed
The title_separator field in site defaults has been renamed to separator.
X (Twitter) Social Sharing
The X (Twitter) social sharing has been significantly simplified. Instead of maintaining separate Twitter-specific fields, the addon now uses a unified social image shared between Open Graph and Twitter. The card size is now a site-level default.
Removed Fields
The following fields have been removed from entries, terms, and SEO set localizations:
seo_twitter_card
seo_twitter_title
Uses seo_og_title
seo_twitter_description
Uses seo_og_description
seo_twitter_summary_image
Uses seo_og_image
seo_twitter_summary_large_image
Uses seo_og_image
The following fields have been removed from the site-wide social media defaults:
twitter_summary_image
Uses og_image
twitter_summary_large_image
Uses og_image
Nofollow Removed from Site Defaults
The site-wide nofollow toggle has been removed from the site defaults. It has no practical use case (if you need to prevent crawling entirely, the crawling.environments configuration already forces both noindex and nofollow when the environment is not listed). Nofollow is now managed per collection/taxonomy in the content defaults and per entry/term.
Social Images Generator
Per-Collection Settings
The social_images_generator_collections field has been removed from the site defaults. The social images generator is now enabled per-collection using the social_images_generator toggle in the collection config.
Removed Social Image Preview Targets
The social images generator no longer registers live preview targets for entries. Social image previews are now shown directly in the publish form via a new inline preview fieldtype with real-time theme switching.
Canonical URL
Removed from Collection/Taxonomy Defaults
The canonical URL fields (seo_canonical_type, seo_canonical_entry, seo_canonical_custom) have been removed from collection and taxonomy defaults. Canonical URLs are now configured per-entry/term only, since setting a default canonical for an entire collection is not a meaningful SEO configuration.
Entries and terms that inherited the default current canonical type are unaffected — current is now the hardcoded default on the entry/term level.
Renamed Canonical Type and New Term Support
The other canonical type has been renamed to entry. The canonical type field now uses a button group with three options: Current, Entry, and URL. If you reference seo_canonical_type values in code or templates, update other to entry.
Sitemaps
Per-Collection/Taxonomy Settings
The excluded_collections and excluded_taxonomies fields have been removed from the site defaults. The sitemap is now enabled per-collection/taxonomy using the sitemap toggle in the collection/taxonomy config.
If a collection or taxonomy was excluded from the sitemap in any site, the migration conservatively disables the sitemap for that entire collection/taxonomy. After upgrading, review your sitemap settings in the Control Panel and re-enable any collections or taxonomies that should be included.
Removed Priority and Change Frequency Fields
The Priority and Change Frequency sitemap fields have been removed from entries, terms, and collection/taxonomy defaults. Google and Bing ignore these values. Auto-generated sitemaps no longer output <priority> or <changefreq> XML elements, though the custom sitemaps API still supports them.
Domain Scoping
Each domain now gets its own sitemap index, and its sitemaps only contain URLs from sites on that domain. Previously, a single sitemap index included URLs from all sites regardless of domain.
example.com, example.com/de, example.com/fr
One index on example.com (unchanged)
example.com, example.com/de, example.fr
One index on example.com, one on example.fr
example.com, example.de, example.fr
One index per domain
Troubleshooting
If the automated upgrade script fails or doesn't run, you can trigger it manually using Statamic's built-in command. Pass any version below 3.0.0 as the version you are upgrading from:
Last updated