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.

Upgrade Summary

The following changes require manual action. All other changes are handled automatically.

Change
Impact
Action

High

Require package manually

High

Remove custom fields

Medium

Update queries

Medium

Update event listeners

Low

Update published views

Low

Update published views

Low

Remove from published config

Low

Remove custom templates

Low

Update custom templates

Low

Delete orphaned images

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-screenshotarrow-up-right 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 guidearrow-up-right 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 tab

  • The 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":

Old Type Name
New Type Name

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:

chevron-rightRemoved sub-typeshashtag
Removed Type
Replacement

generalDefaults

Fields moved directly onto siteSet

indexingDefaults

Fields moved directly onto siteSet

socialMediaDefaults

Fields moved directly onto siteSet

analyticsDefaults

Fields moved directly onto siteSet

faviconsDefaults

Fields moved directly onto siteSet

Removed seoSet Fields

The following fields have been removed from the siteSet type as they are now configured per collection/taxonomy:

  • excluded_collections

  • excluded_taxonomies

  • social_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

The following fields have been removed from the computed type:

Removed Field
Use Instead

title

Raw data title field

og_title

Raw data og_title field

twitter_title

Raw data og_title field

twitter_image

Raw data og_image field

og_image

Raw data og_image field

generated_og_image

Raw data og_image field

A new twitter_card field has been added to the computed type, returning the card size (summary or summary_large_image).

The following fields have been removed from the seoMeta raw type, collectionSet, and taxonomySet types:

Removed Field
Use Instead

site_name_position

Composed into title

twitter_card

seoMeta { computed { twitter_card } }

twitter_title

og_title

twitter_description

og_description

twitter_summary_image

og_image

twitter_summary_large_image

og_image

The following fields have been removed from the siteSet type:

Removed Field
Use Instead

twitter_summary_image

og_image

twitter_summary_large_image

og_image

The title_separator field on the siteSet type has been renamed to separator.

seoSitemaps Query

The seoSitemaps query has been completely restructured for a simpler, flatter API:

Key changes:

  • site is now a required query argument (was optional on nested fields)

  • type argument (collection, taxonomy, custom) replaces the nested fields

  • baseUrl has been removed. Configure your frontend domain in resources/sites.yaml instead.

  • Returns a list of sitemaps with id, type, handle, lastmod, and nested urls array

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 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 saved

  • SeoSetConfigDeleted — Fired when a set's configuration is deleted

  • SeoSetLocalizationDeleted — Fired when a localization is deleted

Low Impact Changes

Custom Views

Affects users who published or customized the _twitter.antlers.html snippet.

Update the following references:

Old Variable
New Variable

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

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.

Automated Changes

Everything in this section is handled by upgrade scripts. No action required. These changes are documented for reference.

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 editing

  • edit seo defaults — Edit collection and taxonomy defaults

  • edit seo content — Access the SEO tab on entries and terms

circle-info

The edit seo defaults and edit seo content permissions work in conjunction with Statamic's native collection and taxonomy permissions. For example, to edit SEO defaults for the Pages collection, a user needs the edit seo defaults permission AND either Statamic's configure collections or edit pages entries permission.

circle-check

Single-Site Data Structure

Single-site installations now use the same data structure as multi-site. Config and localization data are stored separately:

circle-check

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. Tabs now provide the UI grouping within a single publish form.

For file-based installations, the file structure has changed:

circle-check

Disabled Collections and Taxonomies

The disabled configuration option has been removed from config/advanced-seo.php:

Collections and taxonomies can now be disabled individually through the Control Panel by clicking the "Configure" button on each set.

circle-check

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.

circle-check

Eloquent Driver

If you're using the Eloquent driver, the database schema has changed:

The advanced_seo_defaults table has been replaced by seo_set_localizations. A new seo_set_configs table has been added to store configuration data (enabled state, origins, etc.).

circle-check

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, '...') }}.

circle-check

Site Name Position Composed into Title

The seo_site_name_position field has been removed. Its value is now 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 }}

circle-check

Title Separator Renamed

The title_separator field in site defaults has been renamed to separator.

circle-check

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, with only the card size remaining as a Twitter-specific setting.

Removed Fields

The following fields have been removed from entries, terms, and SEO set localizations:

Removed Field
Replacement

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:

Removed Field
Replacement

twitter_summary_image

Uses og_image

twitter_summary_large_image

Uses og_image

circle-check

Twitter Card Setting

The seo_twitter_card field has been moved from a per-localization setting to a per-collection/taxonomy configuration setting. It is now available in the "Social Appearance" section of the collection/taxonomy config.

circle-check

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.

circle-check

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.

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.

circle-check

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.

Setup
Sitemap indexes

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

circle-info

Hreflang tags are unaffected and continue to reference all localized versions across domains.

Last updated