Skip to main content
Version: 2.0.0

SEO on Plugin Pages

yStore plugin pages (cart, checkout, customer account, catalog search, order confirmation, etc.) are rendered through the plugin's own Twig layout and controllers. This guide explains how SEO metadata is set on those pages and how to override it in your theme.


How it works

Every plugin page uses the base layout at yui/layouts/1column.twig. The <head> includes yui/blocks/_head/meta.twig — the single place where SEO metadata is rendered for all plugin pages:

{# yui/blocks/_head/meta.twig — simplified #}

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<meta name="referrer" content="origin-when-cross-origin" />

{# If the controller passed seoTitle + seoDescription, register them with ether/seo #}
{% if seoTitle is defined and seoTitle is not empty
and seoDescription is defined and seoDescription is not empty %}
{% set seo = craft.seo.custom(seoTitle, seoDescription) %}
{% endif %}

{# ether/seo renders all <title>, <meta name="description">, og: tags, and canonical #}
{% hook "seo" %}

The flow for every plugin page request:

What ether/seo renders

The {% hook "seo" %} outputs all the standard tags automatically:

  • <title> — from seoTitle
  • <meta name="description"> — from seoDescription
  • <link rel="canonical"> — based on the current URL
  • Open Graph tags (og:title, og:description, og:url, og:type)
  • Twitter card tags (if enabled in SEO plugin settings)

Default SEO values per page

Every plugin page ships with a default title and description. These are translated strings, so they respect the active site locale.

PageDefault seoTitleDefault seoDescription
Shopping CartShopping CartExplore a wide selection of items and effortlessly manage your purchases...
CheckoutCheckoutSeamlessly complete your purchase with our secure and efficient checkout process.
Order SuccessThank You for Your PurchaseCongratulations on your successful order!
Order FailedSomething was wrong with your order!We apologize, but it seems there was an issue processing your order.
Payment gateway redirect page

The payment redirect form (yui/pages/checkout/redirect-form.twig) is a bare HTML page that auto-submits to the payment gateway. It hardcodes <meta name="robots" content="noindex"> and has no full layout — this page is intentionally kept out of search indexes and out of the SEO plugin flow.


Overriding SEO in your theme

Method 1 — Override seoTitle and seoDescription in a template

In your theme, you can override the plugin's page templates. Set the seoTitle and seoDescription variables before the layout is rendered and they will be picked up by meta.twig automatically.

{# mytheme/templates/yui/pages/cart/view.twig #}

{% extends "yui/layouts/1column.twig" %}

{# Override the SEO variables before they reach meta.twig #}
{% set seoTitle = "Your Cart | " ~ siteName %}
{% set seoDescription = "Review your selected items before checkout." %}

{% block main %}
{# your cart content #}
{% endblock %}

The layout will call craft.seo.custom(seoTitle, seoDescription) with your values instead of the plugin defaults.


Method 2 — Use craft.seo.custom() directly

If you need finer control (e.g. dynamic title from a variable), call craft.seo.custom() yourself anywhere before {% hook "seo" %} fires:

{% set seo = craft.seo.custom(
"Your Cart (" ~ itemCount ~ " items) | " ~ siteName,
"Review your " ~ itemCount ~ " items and proceed to checkout."
) %}
craft.seo.custom() reference

craft.seo.custom(title, description) is provided by the ether/seo Craft plugin, which yStore requires. It registers the values for the current request so the {% hook "seo" %} renders them into the appropriate tags.


Method 3 — Add tags via {% block head %}

The layout exposes a head block for additional per-page tags — without overriding the main SEO setup:

{% extends "yui/layouts/1column.twig" %}

{% block head %}
{# Prevent cart from being indexed #}
<meta name="robots" content="noindex, follow">

{# Custom Open Graph image for checkout #}
<meta property="og:image" content="{{ siteUrl('assets/checkout-og.jpg') }}">
{% endblock %}

Method 4 — Use layout hooks

The layout exposes two Craft hooks for injecting into <head> from a plugin or module without overriding templates:

HookPosition
after-head-startFirst thing inside <head> — before any plugin tags
before-head-endLast thing inside <head> — after all plugin tags
// In your module's init()
\Craft::$app->view->hook('after-head-start', function (array &$context): string {
// Add a tag only on the cart page
if (\Craft::$app->request->getPathInfo() === 'shop/cart/view') {
return '<meta name="robots" content="noindex, follow">';
}
return '';
});

Making plugin pages noindex

Transactional pages (cart, checkout, account) should generally be excluded from search indexes. The recommended approach is to add the robots directive in your theme template override:

{# mytheme/templates/yui/pages/cart/view.twig #}
{% extends "yui/layouts/1column.twig" %}

{% block head %}
<meta name="robots" content="noindex, follow">
{% endblock %}

{% block main %}
{# cart content ... #}
{% endblock %}

Canonical tags

ether/seo automatically generates a canonical tag for each page based on the current URL. For plugin pages this is correct out of the box — the cart URL (/shop/cart/view) becomes its own canonical.

If you need to override the canonical (e.g. to suppress query-string variants):

{% block head %}
{# Remove ether/seo canonical and set your own #}
<link rel="canonical" href="{{ siteUrl('shop/cart/view') }}">
{% endblock %}
Query strings

Plugin pages like the catalog search pass ?q=... query parameters. ether/seo uses the current URL including the query string. If you want the canonical to point to the bare URL, override it in the head block as shown above.


Translating default titles and descriptions

The default seoTitle and seoDescription values are Craft translation strings in the yui category. You can override them in your theme's translation file without touching the plugin:

// translations/en/yui.php (in your theme or module)
return [
'Shopping Cart' => 'Cart | My Store',
'Checkout' => 'Secure Checkout | My Store',
'Search Results' => 'Search | My Store',
'My Account' => 'Account | My Store',
// ...
];

Place this file in your Craft project at translations/{locale}/yui.php. Craft merges translation overrides automatically — your strings take precedence over the plugin's defaults.


Sitemap integration

yStore registers product URLs in the ether/seo sitemap automatically via SeoService. When you run a product sync or update, product URLs are inserted or updated in the sitemap under the customUrls group.

To regenerate the sitemap manually:

# Sync all product URLs into the sitemap
php craft yui/seo/update-sitemap

# Reset and rebuild from scratch
php craft yui/seo/update-sitemap --reset
ether/seo sitemap settings

Non-product pages (cart, checkout, account) are not added to the sitemap — this is intentional. Only content that search engines should crawl (products, CMS pages) belongs in the sitemap. Configure ether/seo's sitemap settings in Settings → SEO → Sitemap to control which Craft entry sections are included.


Open Graph and social sharing

ether/seo automatically outputs Open Graph tags from seoTitle and seoDescription. To add a custom og:image for a plugin page, use the head block:

{% block head %}
<meta property="og:image" content="{{ siteUrl('assets/social/store-share.jpg') }}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
{% endblock %}

For product pages, ether/seo handles Open Graph automatically if your product entries have an SEO field configured.


Quick reference

GoalApproach
Change title on a plugin pageOverride seoTitle variable in template
Change descriptionOverride seoDescription variable in template
Make a page noindexAdd <meta name="robots" content="noindex, follow"> in {% block head %}
Add og:imageAdd <meta property="og:image" ...> in {% block head %}
Override canonicalAdd <link rel="canonical" href="..."> in {% block head %}
Apply to all plugin pages via codeUse before-head-end hook in a module
Translate default titlesAdd strings to translations/{locale}/yui.php
Regenerate product sitemapphp craft yui/seo/update-sitemap