Skip navigation
Scope

Enter at least two characters.
Searching…
No matching documentation found.
Search is temporarily unavailable.

SEO Changelog

Release notes for SEO.

2.0.1

🐛 Bug fixes

  • Only treat debug mode as active when the debug option is true, as Kirby does. Values such as the string "false" no longer set all pages to noindex.
  • Set the error page to noindex by default. This also removes it from the sitemap, llms.txt, IndexNow submissions and the SEO overview, even if its content file is not named error.txt.
  • Output twitter:card with summary_large_image when the page has an Open Graph image file and "Crop OG image" is active. X, Discord and other platforms then show a large image preview.
  • Hide AI features in the Panel when the AI provider has no API key. Custom providers can override Driver::configured().
  • Use the site's meta description in llms.txt
  • Link the Search Console setup guide in the Search Console section
  • Use the www.andkindness.com domain for the license API and the user agent

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0...2.0.1

2.0.0

Kirby SEO 2

Kirby SEO 2 🚀 The first stable release for Kirby 5 includes a site-wide SEO overview, AI Assist, an alt text field, Google Search Console, IndexNow and LLM-friendly content. It's a natural upgrade from 1.x: your content and blueprints keep working.

Kirby SEO 2 requires Kirby 5 and PHP 8.3. A license is required for public sites: buy a license. Read the upgrade guide before updating from 1.x.

composer require tobimori/kirby-seo

🎉 Features

SEO overview

We've added a new SEO area to the Panel. It checks titles, descriptions, alt texts and links across the whole site, and each card takes you to the pages, images or links that need work.

  • Checks for missing, duplicate, too short and too long titles and descriptions, and values inherited from a fallback
  • You can now edit meta titles and descriptions for multiple pages in the table or generate them with AI
  • You can now edit alt texts for multiple images at once
  • You can now check internal and external links for broken targets. With Kirby Queues, the checks run in the background on a schedule.

SEO overview

AI Assist

AI Assist writes meta titles and descriptions based on the page content. It uses the page's language, takes the length of your title template into account and includes unsaved changes. Editors can generate new text or revise the current one.

OpenAI, Anthropic, Google Gemini and OpenRouter are supported out of the box. You can also add your own providers and replace the built-in prompts with your own snippets.

// site/config/config.php
return [
  'tobimori.seo' => [
    'ai' => [
      'provider' => 'anthropic',
      'providers' => [
        'anthropic' => [
          'config' => [
            'apiKey' => 'sk-ant-...',
          ],
        ],
      ],
    ],
  ],
];

Alt text field

The new alt-text field generates alt texts with AI based on the image itself and has a toggle for decorative images. With autogenerate: true, alt texts are generated on upload. On multilingual sites, a single request covers all languages.

# site/blueprints/files/image.yml
fields:
  alt:
    type: alt-text
    autogenerate: true

Google Search Console

The new Google Search Console section shows clicks, impressions, click-through rate, position and top search queries for each page, right next to its content. Editors don't need their own Google account.

Google Search Console section

LLM-friendly content

Kirby SEO can now serve Markdown versions of your pages for AI agents, as well as an llms.txt file for each language. The Markdown comes from a .md.php representation next to the template or from an automatic conversion of the page's main content.

<?php // site/templates/article.md.php ?>
# <?= $page->title() ?>

<?= $page->text()->value() ?>

Agents can open /article.md or request Markdown with the Accept: text/markdown header. Markdown responses send noindex and a link to the original page so search engines don't list them as duplicates.

IndexNow

Kirby SEO now notifies Bing, Yandex and other search engines via IndexNow when pages change. With rules, you can submit related pages as well, such as the parent of a new blog post.

'tobimori.seo' => [
  'indexnow' => [
    'rules' => [
      'article' => ['parent' => true, 'urls' => ['/blog', '/']],
    ],
  ],
],

Title templates with variables

Title template fields now show Page Title and Site Title as buttons and chips instead of raw query syntax. Title, description and template fields use the new seo-writer field with AI buttons.

UTM share

We've added a dialog to the page view to create campaign links with UTM parameters and copy them with a click.

UTM share dialog

Background processing

With Kirby Queues installed, AI alt text generation, IndexNow submissions and link checks run in a queue worker instead of during the Panel request.

Opt out of AI training

You can now opt out of AI training with the new ai and imageai robots types. They output noai and noimageai, and editors can allow AI training again for individual pages or the whole site.

'tobimori.seo' => [
  'robots' => [
    'types' => ['index', 'follow', 'archive', 'imageindex', 'snippet', 'ai', 'imageai'],
  ],
],

Optimized head order

You can now use seo/head with slots to output the <title> before your stylesheets and scripts, and the other meta tags after them (#112).

<?php snippet('seo/head', slots: true) ?>
  <link rel="stylesheet" href="/assets/css/main.css">
<?php endsnippet() ?>

Kirby Agents

The SEO writer and alt text fields now support Kirby Agents, so agents can read and edit metadata and alt texts.

And more …

  • New license activation in the Panel
  • Panel previews respect dark mode and use the current Google design
  • New canonical.trailingSlash option (#136)
  • Mastodon profile links are output as <link rel="me"> (#92)
  • New components option to replace built-in classes

✨ Enhancements

  • The sitemap lists each translation of a page as its own entry, with the same hreflang alternates on every entry
  • hreflang tags only list existing, indexable translations
  • Pages with a non-canonical URL, for example with query parameters, do not output hreflang tags (#98)
  • x-default points to the page's language-neutral URL (#177), with the default language's slug (#146)
  • The sitemap stylesheet shows language alternates and a cleaner table
  • IndexNow skips pages with noindex
  • Panel previews use the page's canonical URL (#185, thanks @antons)

⚡ Performance

  • Kirby SEO caches indexable pages and page, image and link check results. This speeds up the SEO overview and sitemap on large sites.
  • The sitemap index and llms.txt use the pages cache

🐛 Bug fixes

  • og:image:width and og:image:height use the cropped image's dimensions (#91)
  • The sitemap URL in robots.txt is correct on multilingual sites (#124)
  • The sitemap uses the canonical base URL, and its stylesheet loads on sites in a subfolder (#88)
  • The sitemap returns content for HEAD requests. This fixes "Sitemap could not be read" errors in Google Search Console (#164, thanks @tomsl123).

🚨 Breaking changes

The upgrade guide covers the steps for updating.

  • Kirby SEO 2 requires Kirby 5 and PHP 8.3
  • A license is required for public sites. Kirby SEO 1.x remains available under the MIT license.
  • lang, sitemap.lang and default.lang are now locale, sitemap.locale and default.locale. The old names are ignored.
  • The spatie/schema-org package is no longer installed with Kirby SEO (#48). Install spatie/schema-org:^5.0 (PHP 8.4) if you output Schema.org data.
  • Twitter options, fields and twitter:* tags are removed. X reads the Open Graph tags.
  • A page's meta description now takes priority over the site's Open Graph description for og:description. The fallbackFields cascade level is enabled by default.
  • Title templates only resolve {{ title }} and {{ site.title }}, because editors can change them in the Panel. To use all Kirby queries as in 1.x, set the new kql option to true. Only enable it if you trust all Panel users.
  • $page->metadata() and $page->robots() take a Kirby\Cms\Language object instead of a language code
  • SitemapUrl::lastmod() takes a Unix timestamp instead of a date string

☠️ Deprecated

  • canonicalBase → use canonical.base
  • robots.active → use robots.enabled
  • sitemap.active → use sitemap.enabled

🌐 Translations

📚 Docs

The new documentation includes a quickstart, a page for each feature, customization guides, an options reference and an upgrade guide.

🧹 Housekeeping

  • Static analysis with Mago for all PHP code
  • Updated dependencies

Thanks to everyone who tested the alphas, betas and release candidates, reported issues and sent pull requests: @olach, @wietseneven, @jan-herman, @ovenum, @lukasleitsch, @danburzo, @tomsl123, @FloWinge, @antons, @notz and @FlorianBoe.

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.1.2...2.0.0

2.0.0-rc.2

Pre-release

⚠️ Breaking changes

  • Schema.org support now requires spatie/schema-org ^5.0, which needs PHP 8.4. Composer no longer installs Kirby SEO next to older versions of the package.

✨ Enhancements

  • List each indexable translation as its own sitemap entry, with the same hreflang alternates on every entry
  • Leave out translations with noindex from hreflang tags
  • Use the Interactions API for the Gemini provider
  • Update the default AI Assist models to Claude Haiku 5.5 (Anthropic), GPT-6 Luna (OpenAI and OpenRouter) and Gemini 3.5 Flash-Lite (Gemini). Models set in your config stay unchanged.

🐛 Bug fixes

  • Generate a valid IndexNow key. The key was always empty, and search engines could not verify submissions.
  • Keep the Search Console OAuth state in the session and only redirect back to Panel URLs
  • Build the Search Console connect URL from the site URL, which fixes sites installed in a subfolder
  • Send Anthropic system messages as the top-level system parameter
  • Escape & in sitemap URLs, write URL elements in schema order and link sitemap index entries without a language prefix
  • Accept an int timestamp in SitemapUrl::lastmod()
  • Fix errors in debug mode on pages that use metaDefaults
  • Find anchors with numeric IDs such as #2024 in the link audit
  • Build pagination links in the link audit from the checked page instead of the Panel API URL
  • Return the updated row after saving a page with a numeric ID in the SEO overview
  • Show the inherited value in empty "Crop OG Image" fields. The site field is now a select like the page field.
  • Return Markdown for paginated pages such as notes.md/page:2
  • Reject HTML tags in SEO writer fields edited through Kirby Agents

The first link check after the update checks all links again.

📖 Documentation

  • Add a guide for upgrading from Kirby SEO 1.x
  • Add pages for the SEO overview and background processing
  • Fix outdated statements across the docs, e.g. for robots.txt, the Search Console setup and custom AI providers

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-rc.1...2.0.0-rc.2

2.0.0-rc.1

Pre-release

✨ Enhancements

  • Limit the SEO overview to pages that search engines can index
  • Show title-template prefixes and suffixes in the meta title column

⚡ Performance

  • Speed up the SEO overview and sitemap on large sites by caching indexable pages and page, image and link audit results

🐛 Bug fixes

  • Start the initial link scan when queue processing is enabled
  • Keep overview results current after changes to parent pages, languages or relevant SEO options
  • Apply page-specific robots rules when built-in robots handling is disabled
  • Reload the SEO view after license activation so the activation banner disappears
  • Log failed IndexNow requests from queue jobs

🔑 Licensing

  • Require a Kirby SEO Enterprise license on sites that use Kirby Enterprise

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-rc.0...2.0.0-rc.1

2.0.0-rc.0

Pre-release

Kirby SEO 2 is now a release candidate. A license is required for public sites: buy a license.

✨ New features

  • SEO overview in the Panel with stats and tabs for pages, images and links (#195)
    • Check titles and descriptions for missing, duplicate, fallback and length issues
    • Edit and generate meta fields with AI for many pages at once
    • Edit alt texts for many images at once
    • Check all links for broken targets
  • Kirby Agents integration for the SEO writer and alt text fields (#196)
  • Markdown versions of pages and llms.txt for LLMs (#191)
  • License activation in the Panel. Licenses are checked offline, and you can also add a license file manually as site/config/.seo-license

✨ Enhancements

  • AI assist uses the unsaved changes of a page
  • IndexNow skips pages with a noindex robots rule
  • robots.enabled is now the default for the deprecated robots.active option

⚡ Performance

  • The sitemap index and llms.txt use the pages cache
  • Meta lookups are memoized during a render
  • The SEO overview only checks pages again when they change

🐛 Bug fixes

  • Return 404 for an unknown sitemap
  • Throw an error for invalid sitemap alternates
  • Parse the heading structure as UTF-8
  • Skip AI alt texts for images that can't be resized without ext-imagick
  • Handle requests without a page path

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-beta.5...2.0.0-rc.0

2.0.0-beta.5

Pre-release

🐛 Bug fixes

  • Fix canonical URL comparison when canonical.trailingSlash is enabled (@notz, #188)
  • Add missing labels and IDs to SEO Writer and SEO preview form controls (@FlorianBoe, #187)
  • Prevent fatal errors for non-resizable Open Graph images and hide them from the default image picker (#190)

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-beta.4...2.0.0-beta.5

2.0.0-beta.4

Pre-release

✨ Enhancements

  • Support OpenAI completions API syntax
  • Use canonical URLs in the SEO preview (@antons, #185)

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-beta.3...2.0.0-beta.4

2.0.0-beta.3

Pre-release

🚨 Breaking changes

  • Enable fallbackFields cascade level by default: a page's description is now used as og:description before site-wide Open Graph values are reached, preventing site-level OG descriptions from overriding page-specific meta descriptions. Remove fallbackFields from the cascade to restore the previous behavior. See the Meta Cascade docs for details.

✨ Enhancements

  • Improve sitemap XSL stylesheet with language alternate badges, cleaner URL display, and fixed table layout
  • Resolve template variable labels in SEO Writer placeholder text

🐛 Bug fixes

  • Fix sitemap stylesheet URL not resolving correctly on multi-language sites
  • Remove unnecessary role="presentation" attribute from decorative images in alt text output

2.0.0-beta.2

Pre-release

🐛 Bug fixes

  • Fix SEO Writer regression

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-beta.1...2.0.0-beta.2

2.0.0-beta.1

Pre-release

🎉 Features

  • Add alt text field (alt-text) with AI-powered alt text generation from images, with auto-generation on upload
  • Add Google Gemini as a built-in AI provider
  • Add background processing support for alt text generation via kirby-queues

✨ Enhancements

  • Add multimodal image support to AI drivers (Anthropic, OpenAI, Gemini)

🐛 Bug fixes

  • Fix robots indicator button not displaying correctly (#184)

♻️ Refactored

  • Extract shared AI streaming utilities (useAiStream, consumeSSEStream) from field components

Full Changelog: https://github.com/tobimori/kirby-seo/compare/2.0.0-alpha.13...2.0.0-beta.1

2.0.0-alpha.13

Pre-release

🐛 Bug Fixes

  • Fix double-encoded HTML entities in meta tag output when using Writer fields (#183)

2.0.0-alpha.12

Pre-release

🐛 Bug Fixes

  • Fix x-default hreflang pointing to language-specific URL instead of language-neutral switcher URL in multi-language setups (#177)

2.0.0-alpha.11

Pre-release

🐛 Bug Fixes

  • Fix language code not being passed in page.update:after hook, breaking multi-language page updates
  • Fix hook running on pages without SEO tab, breaking compatibility with other plugins like DreamForm

2.0.0-alpha.10

Pre-release

🎉 Features

  • Add Google Search Console integration - view search performance data directly in the Kirby panel
  • Add dynamic blueprint selection - automatically chooses between site and page SEO blueprints (#169)
  • Add support for object notation in AI provider configuration (#168)

2.0.0-alpha.9

Pre-release

🎉 Features

  • Add new UTM parameter sharing dialog

🐛 Bug Fixes

  • Fix HTML entities not being decoded in SEO preview section (thanks @ovenum)
  • Fix deprecated pathinfo() call when parse_url() returns null (thanks @FloWinge)

2.0.0-alpha.8

Pre-release

🐛 Bug Fixes

  • Fix "using $this when not in object context" error when saving pages (#167)
  • Fix favicon not displaying in Google preview component

2.0.0-alpha.7

Pre-release

🎉 Features

  • Add IndexNow support for instant search engine notifications
  • Add components config syntax for easier component customization

2.0.0-alpha.6

Pre-release

🎉 Features

  • Add AI-powered meta tag generation with OpenAI and Anthropic support
  • Add custom SEO writer field with specialized toolbar buttons

🐛 Bug Fixes

  • Fix sitemap returning 404 for HEAD requests - caused "Sitemap could not be read" errors in Google Search Console (#164, thanks @tomsl123)
  • Fix sitemap XSL stylesheet loading with wrong language prefix on multi-language sites (#160)

✨ Enhancements

  • Add proper HTTP method handling for sitemap routes (OPTIONS returns 204, unsupported methods return 405)
  • Fix writer toolbar button width (thanks @danburzo)

🌐 Translations

  • Add Romanian translation (thanks @danburzo)

2.0.0-alpha.5

Pre-release

🎉 Features

  • Add custom SEO nodes for writer field
  • Add custom SEO writer field
  • Strip allowed HTML tags from meta tags for cleaner output

✨ Enhancements

  • Improve site preview styling

2.0.0-alpha.4

Pre-release

🎉 Features

  • Add dark mode support for SEO previews
  • Update Google SEO preview component to match current Google design

🐛 Bug Fixes

  • Fix "Storage for the page is immutable" error when saving pages with kirby-seo fields (#145, thanks @ovenum)
  • Fix x-default alternate link using wrong slug on non-default languages (#146)
  • Fix Kirby template braces not being escaped in placeholder text (thanks @lukasleitsch)

♻️ Refactored

  • Simplify files query in og-image.php (thanks @ovenum)

2.0.0-alpha.3

Pre-release

🐛 Bug Fixes

  • Fix all pages returning 404 when robots.index option is set to true (#140)

2.0.0-alpha.2

Pre-release

🐛 Bug Fixes

  • Fix "Value of type null is not callable" error caused by missing default.lang option (#139)

2.0.0-alpha.1

Pre-release

🚨 Breaking Changes

  • Requires Kirby 5
  • Remove schema-org package from default plugin distribution - install separately if needed (#48)
  • Major refactor of language handling for multi-language sites (#128)

🎉 Features

  • Add priority meta tags support (#112)
  • Add trailing slash configuration (#136)
  • Add Mastodon profile link as rel="me" (#92)
  • Skip alternate hreflang tags when URL is not canonical (#98)

🐛 Bug Fixes

  • Fix OG image width/height not being set correctly (#91)
  • Fix wrong sitemap URL on multi-language pages (#124)
  • Fix sitemap URL not using canonical base URL (#88)

🌐 Translations

1.1.2

🐛 Bug Fixes

  • Google Search preview now shows the title correctly with the title preview (#90)

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.1.1...1.1.2

1.1.1

🐛 Bug Fixes

  • Empty robots fields do not throw error when saving anymore

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.1.0...1.1.1

1.1.0

🚀 Features

  • /sitemap now redirects to /sitemap.xml (#84) You can disable this behaviour by setting tobimori.seo.sitemap.redirect to false.

🐛 Bug FIxes

  • Robots section defaults are now set correctly by Kirby logic & using a page.update hook (#89)
  • Robots page settings now don't show up if Robots is disabled (#87)

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.0.0...1.1.0

1.0.0

First stable production release of kirby-seo.

💣 Breaking changes

If you previously used kirby-seo 0.4.0 or earlier, please follow the Migration guide.

🚀 New Features

  • Kirby 4.0 redesign compatibility (#12)
  • Complete refactor of the Meta class & cascading behaviour
  • Customizable cascade option
  • New languages: Turkish 🇹🇷 & Portuguese 🇵🇹 (#49 / #69)
  • New Sitemap functionality (#47)
  • Custom meta tags with programmatic cascade (#23)
  • Use meta tag names instead of field names in programmatic cascade

...and tons of bug fixes! 🐛 (Take a look at early releases for a detailed summary)

This release was a ton of work and is available completely free of charge. If you use kirby-seo in a commercial project, I'd highly appreciate a sponsorship on GitHub (one-time available as well). If you need a commercial invoice or priority support, send me an email at seo@moeritz.io and we can figure things out.

Thanks to all contributors and everyone who created issues as well. @afbora, @JuKra00, @andrepimpao, @luxuryluke, @holmey

Full Changelog: https://github.com/tobimori/kirby-seo/compare/0.4.0...1.0.0

1.0.0-rc.7

Pre-release

🐛 Bug Fixes

  • Programmatic meta tags are now tracked correctly and no longer output twice
  • Robots check for canonical and alternate tags no longer causes an infinite loop (#83)
  • Sitemap title in XSL template is now escaped to support ampersands, thanks to @JuKra00 (#81 / #82)

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.0.0-rc.6...1.0.0-rc.7

1.0.0-rc.6

Pre-release

🐛 Bug Fixes

  • $site->lang() now returns the config language in the correct format for the <html> tag (#77)
  • canonical and alternate tags are not output anymore if the page is set to noindex or the robots module is disabled
  • Section label of heading-structure now looks as expected

📝 Docs

  • Schema.org usage is now documented (#70)
  • Sitemap docs now hint to robots docs for whether a page is indexed or not (#68)
  • heading-structure section is now documented

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.0.0-rc.5...1.0.0-rc.6

1.0.0-rc.5

Pre-release

🐛 Bug Fixes

  • Regex pattern used for accessing the page context programmatic blueprints now supports - and _

Full Changelog: https://github.com/tobimori/kirby-seo/compare/1.0.0-rc.4...1.0.0-rc.5