agentleFS
keuperakeupera/seo-skills/skills/shopify-seo/SKILL.md

shopify-seo

Skill0 starsChanged 2 months agoMITView on GitHub

Fix the SEO problems specific to Shopify — forced URL structure, duplicate collection and product URLs, theme metadata, faceted filters, blog limitations and app bloat. Use whenever the user is working on a Shopify store and mentions SEO, rankings, duplicate products, /collections/ URLs, product variants, Liquid templates, theme.liquid, robots.txt.liquid, sitemap, or store speed. Also use when auditing or migrating a Shopify store.

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

3 rules. 0 are common, 1 is distinctive, and 2 are very specific to this project.

  • 0

    Common

    Most of the 3 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Audit the apps: Every one injects scripts, most load on every page, and abandoned apps leave code behind after uninstall.

    line 126
  2. Distinctive:

    Don't waste time on these, and don't buy an app that claims to fix them:

    line 135
  3. Very specific:

    Do the inventory before switching, not after.

    line 147

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Shopify SEO

Shopify handles a lot correctly out of the box and imposes a handful of structural problems you can't remove. Knowing which is which saves weeks of trying to change things the platform won't let you change.

The URL structure you're stuck with

/products/handle                          canonical product URL
/collections/name/products/handle         same product, inside a collection
/collections/name                         collection page
/collections/all                          every product
/pages/handle                             static pages
/blogs/blog-name/article-handle           blog posts

You cannot remove /products/, /collections/, /pages/ or /blogs/ on standard plans. Stop trying. The prefixes cost essentially nothing and the workarounds cost real stability.

The duplicate that matters is /collections/x/products/y. Every product is reachable from every collection that contains it, generating a URL per combination. Shopify canonicalises these to /products/handle by default, which is correct, but two things routinely break it:

  • A theme that outputs collection-scoped links everywhere, so all internal links point at non-canonical URLs.
  • An app or theme edit that overrides the canonical tag.

Check both:

curl -s https://shop.example.com/collections/shoes/products/blue-runner \
  | grep -oP '(?<=rel="canonical" href=")[^"]+'
# must return https://shop.example.com/products/blue-runner

In theme.liquid, the canonical should be:

<link rel="canonical" href="{{ canonical_url }}">

And product links in collection templates should use the bare product URL rather than the collection-scoped one:

{%- comment -%} Not: {{ product.url | within: collection }} {%- endcomment -%}
<a href="{{ product.url }}">{{ product.title }}</a>

within: collection is the default in many themes and it's the direct cause of every internal link pointing at a non-canonical URL. Changing it costs nothing and fixes the whole pattern.

Metadata in the theme

Shopify's SEO fields are fine but themes vary in how they use them. Verify what's actually output.

{%- comment -%} theme.liquid {%- endcomment -%}
<title>
  {{ page_title }}
  {%- if current_tags %} &ndash; {{ current_tags | join: ', ' }}{% endif -%}
  {%- if current_page != 1 %} &ndash; Page {{ current_page }}{% endif -%}
  {%- unless page_title contains shop.name %} &ndash; {{ shop.name }}{% endunless -%}
</title>

{%- if page_description -%}
  <meta name="description" content="{{ page_description | escape }}">
{%- endif -%}

The current_page conditional is the important one. Without it, every paginated collection page has an identical title, which is a duplicate-title problem across potentially hundreds of URLs.

Set page_title and page_description per product and collection in the admin rather than letting the theme fall back to the product title alone.

Collection pages are the ranking pages

This is the strategic point most stores miss. Collection pages target the commercial head terms — "running shoes" — and product pages target model names. Collection terms are where the volume and the revenue are, and most Shopify collections are a grid with no content at all.

  • Write a genuine intro that helps someone choose, placed where a person would read it. Most themes put collection descriptions above the grid; move it below, or split it into a short intro above and the substance below.
  • Answer the buying questions on the collection page: sizing, materials, how to choose, what the differences are.
  • Promote high-demand filters into real collections. "Waterproof running shoes" is a search term. Create it as its own collection with its own handle, title, description and internal links, rather than leaving it as a filter parameter.
  • Link collections to each other and from the blog.

Filters and faceted URLs

Shopify's storefront filtering generates ?filter.v.option.size=10 style parameters. These are crawlable and can generate a large URL space.

  • Confirm filtered URLs canonicalise to the unfiltered collection. Default behaviour is correct; apps break it.
  • Block the parameter patterns in robots.txt.liquid if they're consuming crawl budget:
{%- comment -%} robots.txt.liquid {%- endcomment -%}
{% for group in robots.default_groups %}
  {{- group.user_agent -}}
  {% for rule in group.rules %}{{ rule }}{% endfor %}
  Disallow: /*?filter.
  Disallow: /*?sort_by=
  Disallow: /collections/*/products/
  {%- if group.sitemap %}{{ group.sitemap }}{% endif -%}
{% endfor %}

robots.txt.liquid is editable on all plans and is where any AI crawler policy also goes. See ai-crawler-policy.

  • Promote the two or three filters with real search demand to permanent collections instead of blocking everything indiscriminately.

Variants

Shopify variants share one product URL by default, with ?variant=123 appended. That's correct and should stay that way.

Split into separate products only when people search for the variant specifically — a colourway with its own name, or a size that's effectively a different product. Then each needs genuinely different content, not a colour swap. Otherwise you've created duplicates by hand.

ProductGroup with hasVariant is the accurate schema. See schema-markup.

The blog

Shopify's blogging is weak and it's where content strategies stall.

  • URLs are locked to /blogs/{blog-handle}/{article-handle}. Choose the blog handle carefully because changing it means redirects for every post.
  • No categories or tags in URLs, so topic clusters have to be built with internal links rather than structure. See internal-linking-architecture.
  • Limited template control on some themes for author info, dates and schema. Check what's actually output.
  • Consider a subdirectory for serious content operations — a reverse proxy putting /blog on a separate platform. It's real engineering work and it's usually the right call for a content-led store, because Shopify's blog won't support a large cluster well.

Speed

Shopify hosting is fast. Themes and apps are not.

  • Audit the apps. Every one injects scripts, most load on every page, and abandoned apps leave code behind after uninstall. Check theme.liquid and the theme's asset files for leftovers.
  • Sizing via the image filters: {{ image | image_url: width: 800 }} with a proper srcset. Shopify's CDN serves WebP automatically.
  • Defer app scripts that aren't needed for first render. Review apps, chat widgets and popups are the usual INP offenders.
  • Test on a real device. The theme preview is not representative.

See core-web-vitals.

What Shopify handles for you

Don't waste time on these, and don't buy an app that claims to fix them:

  • Sitemap generation at /sitemap.xml, automatic and correct
  • Canonical tags, correct by default
  • HTTPS and HTTP/2
  • Mobile-responsive themes
  • Basic Product schema in most modern themes, though verify the Offer block

Migrating to or from Shopify

The URL structure changes completely, so it's a full migration. Every product, collection and blog URL needs a mapped redirect. Shopify's admin has a URL redirect tool that handles bulk CSV import, which covers most of it.

Do the inventory before switching, not after. See redirect-migration-plan.

Where the data comes from

Which collections to build, and which filters have enough demand to promote, are the decisions that shape the whole store structure, and they need real volume data rather than intuition about what people search.

Keupera covers the keyword and competitor side and connects directly to Shopify for publishing, so collection content and blog posts can be researched, drafted and pushed without exporting between tools. Over MCP:

claude mcp add --transport http keupera https://mcp.keupera.com/mcp -s user

Related skills

ecommerce-seo, canonical-duplicate-content, schema-markup, core-web-vitals, internal-linking-architecture, redirect-migration-plan, image-seo

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.