v2 scoring Estimated on the four-pillar score. A default Shopify install earns 25/35 for raw-HTML readability; schema, llms.txt and AI-crawler rules depend on your setup and start at 0. The steps below, or the Fix Kit, supply those three (up to 65 points).
The platform pitfall: you don't control the root
Liquid renders on Shopify’s servers, so product titles, descriptions and prices are in the raw HTML. Rendering is rarely the problem on Shopify. The files around the store are.
You cannot upload an arbitrary file to your domain root: files added in the admin are served from a CDN path, not from /llms.txt. robots.txt exists only as a theme template, robots.txt.liquid, and Shopify generates sitemap.xml itself.
The default robots rules do not block AI search bots, but they do not name any of them either. Every AI crawler falls back to the * group, so the file says nothing about which crawlers you want, and Crawlable’s crawler-governance pillar scores it 0 of 20. The blocking happens later, when a pasted "block AI bots" snippet lists OAI-SearchBot or PerplexityBot next to GPTBot and takes the store out of ChatGPT Search and Perplexity along with the training crawlers.
Since May 2026, Shopify serves /llms.txt, /llms-full.txt and /agents.md on every store. By default all three carry the same agent-commerce instructions about checkout endpoints, not a map of your catalog. Crawlable’s validator marks that /llms.txt as malformed, because it has no > summary and its links have no descriptions.
The older workaround, uploading llms.txt to Files and adding a URL redirect from /llms.txt, is no longer needed. It also never served a file at /llms.txt: Crawlable counts a /llms.txt that redirects elsewhere as missing.
STEP 1 OF 3
Allow retrieval bots and block bulk scrapers in robots.txt.liquid
In the admin, go to Online Store → Themes → ⋯ → Edit code, then Add a new template, choose robots, and Shopify creates templates/robots.txt.liquid. Keep Shopify’s default groups by leaving its Liquid loop at the top, and add your own groups below it as plain text.
{%- comment -%} templates/robots.txt.liquid {%- endcomment -%}
{% for group in robots.default_groups %}
{{- group.user_agent }}
{%- for rule in group.rules -%}
{{ rule }}
{%- endfor -%}
{%- if group.sitemap != blank -%}
{{ group.sitemap }}
{%- endif -%}
{% endfor %}
# Search and answer engines: allowed, so products can be retrieved and cited.
# A named group does not inherit the * rules above, so the private paths repeat.
User-agent: OAI-SearchBot
User-agent: ChatGPT-User
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: PerplexityBot
User-agent: Perplexity-User
Allow: /
Disallow: /admin
Disallow: /cart
Disallow: /checkout
Disallow: /checkouts/
Disallow: /orders
Disallow: /account
Disallow: /search
# Bulk training crawlers: a licensing decision. Change Disallow to Allow to permit them.
# Google-Extended also controls grounding in Gemini Apps and Vertex AI.
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: Google-Extended
User-agent: Applebot-Extended
User-agent: CCBot
User-agent: Bytespider
User-agent: meta-externalagent
Disallow: /- This file earns the full 20 crawler-governance points: retrieval bots named and allowed, training crawlers in a group of their own.
- Shopify’s docs advise saving a copy of your current /robots.txt first and comparing it with the rendered template before you publish.
- Shopify’s bot protection can still rate-limit any crawler on a large catalog. That shows up as fetch errors in an audit, not as robots blocks.
STEP 2 OF 3
Replace the default /llms.txt with templates/llms.txt.liquid
Shopify serves /llms.txt from templates/llms.txt.liquid when your theme has one. In the same code editor, add a new file named llms.txt.liquid to the Templates folder.
The template renders with a restricted Liquid context. Only the request and agents objects are available, so collections, pages and linklists render blank and the links have to be written out. agents.store_name and agents.store_url keep the name and domain in sync.
# {{ agents.store_name }}
> {{ agents.store_name }} sells handmade stoneware tableware: plates, bowls and mugs, glazed and fired in small batches. Ships to the US, UK and EU.
## Collections
- [Dinner plates]({{ agents.store_url }}/collections/dinner-plates): Stoneware plates in four glazes, 21 cm and 27 cm.
- [Bowls]({{ agents.store_url }}/collections/bowls): Serving, pasta and cereal bowls. Dishwasher safe.
- [Mugs]({{ agents.store_url }}/collections/mugs): 350 ml mugs, sold singly and in sets of four.
## Store information
- [Shipping]({{ agents.store_url }}/policies/shipping-policy): Delivery times and costs by country.
- [Returns]({{ agents.store_url }}/policies/refund-policy): 30-day returns on unused items.
- [About us]({{ agents.store_url }}/pages/about): Who makes the pieces, and where.
## For shopping agents
- [Agent instructions]({{ agents.store_url }}/agents.md): Shopify's catalog, cart and checkout endpoints for agents.- This is the shape Crawlable validates: one
#heading, a>summary,##sections, and absolute links with a description. A well-formed file earns 15 of the 20 llms.txt points; a present/llms-full.txtadds 5. - Your template replaces Shopify’s file instead of merging with it, so keep the link to
/agents.md. That URL goes on serving Shopify’s agent-commerce instructions. /llms-full.txtfalls back toagents.mduntil you addtemplates/llms-full.txt.liquidwith the full text of your key pages.- Leave out contact email addresses and phone numbers. Shopify recommends against putting private merchant data in these files, which are cached and served to every agent.
STEP 3 OF 3
Clean up duplicate Product and Offer schema
Most themes emit a Product block, and review, SEO and feed apps often add their own. A product page can end up with two or three Product entities that disagree about the price or the rating. Anything parsing the page then has two answers and has to pick one.
Count what the raw HTML actually contains. More than one Product means a duplicate; an Offer count that is double your variant count usually means the same thing.
curl -s https://your-store.com/products/your-product \
| grep -o '"@type": *"[A-Za-z]*"' | sort | uniq -c{%- comment -%}
sections/main-product.liquid: the ONE Product block for this page.
Shopify's structured_data filter builds a Product (or a ProductGroup with a
Product per variant) with offers, price and availability, and keeps it in
sync with the product as you edit it.
{%- endcomment -%}
<script type="application/ld+json">
{{ product | structured_data }}
</script>- Keep one source. Turn off the structured-data option in each app that has one, or remove the theme’s block if an app’s is more complete. Then run the count again.
- For Crawlable’s schema pillar, a Product counts as complete when it carries
offers. That earns the full 25 points. Thestructured_datafilter includes them. - Crawlable does not deduct for a duplicate; it checks that one complete entity exists. The count above is how you find duplicates.
Frequently asked questions
- Can I add an llms.txt file to my Shopify store?
- You cannot upload a file to the domain root, and since May 2026 you do not need to. Shopify serves /llms.txt on every store, and you replace its content by adding templates/llms.txt.liquid to your theme.
- Does Shopify's default robots.txt block ChatGPT or Perplexity?
- No. The default rules do not name any AI crawler, so they all follow the * group and can crawl products and collections. AI search bots get blocked by edits to robots.txt.liquid or by apps that add blocking rules, which is why naming them explicitly is worth doing.
- Why does my product page have two Product schemas?
- Your theme emits one, and an installed app, usually for reviews, SEO or a product feed, emits another. Keep the more complete source and switch the other off, so the page carries a single Product with one set of offers.
- Will blocking GPTBot hide my products from ChatGPT search?
- No. ChatGPT Search answers from the index built by OAI-SearchBot, and ChatGPT-User fetches pages people ask about. GPTBot collects training data, so blocking it is a licensing choice that leaves search visibility unchanged.
More Shopify gotchas
- You cannot edit robots.txt directly in older stores; newer ones allow it via robots.txt.liquid in the theme.
- Shopify's bot protection can rate-limit crawlers on large catalogues, which shows up as fetch failures rather than blocks.
- Duplicate content across /products/x and /collections/y/products/x dilutes which URL gets cited — set canonicals.
Last checked .
Further reading
- How to Make React Apps Crawlable for AI Search: SSR, Prerendering and Dynamic Rendering
Google can render React; ChatGPT, Claude and Perplexity crawlers can't. Code for Vite SSR, Next.js and Astro prerendering, dynamic rendering, and a curl check.
- What GPTBot Actually Sees When Your Site Relies on Client-Side JavaScript
AI crawlers like GPTBot and OAI-SearchBot fetch raw HTML without executing client-side JS. Here is what they actually extract from SPAs.
- Why AI Search Engines Can’t Read Client-Side Rendered (CSR) Sites
Most AI crawlers fetch raw HTML and never run your JavaScript. Here's what they actually see on a client-rendered site, how to test it, and how to fix it.
- What is Generative Engine Optimization (GEO)? The Complete 2026 Guide
How ChatGPT Search, Perplexity and Claude find, read and cite pages, why that differs from Googlebot, and what the research says actually improves AI visibility.