SEO · TECHNICAL · PERFORMANCE · 4 JUNE 2026 · 8 MIN READ
Crawl, render, index: what search engines do with a Shopify store
Three separate stages, three separate failure modes. Most Shopify SEO problems are one stage being blamed for another stage’s fault.
A search engine does three distinct things with your store: it discovers URLs and fetches them (crawl), it executes whatever JavaScript those pages need before it can see the content (render), and it decides which of the resulting pages deserve to be in the results (index). Shopify hands you a working sitemap and a maintained robots.txt, so discovery is rarely the problem. What goes wrong is almost always the third stage — a store publishing many near-identical URLs and letting the crawler pick between them.
IN SHORT
- Crawl, render and index are three stages with three different fixes; a page that is crawled is not necessarily rendered, and a page that is rendered is not necessarily indexed.
- Shopify generates `sitemap.xml` automatically and it links to separate child sitemaps for products, collections, blogs and pages — you do not need to build or submit anything else.
- A store in password-protected mode cannot be read by a sitemap reader, so a pre-launch store is invisible by design and stays that way until private mode is turned off.
- Liquid renders server-side, so the first stage of rendering costs a crawler nothing — the risk is content you moved into JavaScript, such as filtered grids fetched through the Section Rendering API.
- Shopify appends `?variant=` to product URLs in search results and filtered collections, which is a documented behaviour and a duplicate-URL source you have to canonicalise around.
- Shopify keeps the default `robots.txt` rules current, which is the single strongest argument against replacing the template with hand-written text.
Three stages, and why separating them matters
When someone says "Google is not picking up our new products", they have described a symptom that could sit in any of three places, and the fixes do not overlap. Crawling is discovery and fetching: does the crawler know the URL exists, is it allowed to request it, and did the request succeed. Rendering is turning the fetched response into a page with content in it, which for anything JavaScript-dependent means a second pass with a browser engine. Indexing is the editorial decision: given everything that was rendered, which URLs are worth storing and serving.
The reason this matters on Shopify specifically is that the platform is unusually good at the first stage and offers you unusually many ways to make a mess of the third. You will rarely fix a Shopify indexing problem by doing more of what helps crawling, and the common interventions — submitting the sitemap again, adding noindex to things — routinely target the wrong stage.
So the useful diagnostic question is not "is it indexed" but "which stage did it stop at". Search Console answers this directly if you read the coverage report rather than the summary number.
Crawl: Shopify already did most of this
Every Shopify store generates a sitemap automatically. The documentation describes it as containing "links to all your products, primary product image, pages, collections, and blog posts", and the file you submit is an index — Shopify's own words are that the generated sitemap files "link to separate sitemaps for your products, collections, blogs, and webpages", updated as the store changes. There is nothing to build, and no plausible reason to install an app that builds a second one.
Two caveats are worth knowing because both catch teams out. The first is private mode: Shopify is explicit that "a sitemap reader (such as Google) can't access it if your website is set to private mode", which means a password-protected store is invisible on purpose. If a site has been live for a fortnight and nothing is indexed, check the storefront password before anything else. The second is international domains — sitemaps for those are documented as available on the Basic, Shopify, Advanced and Plus plans, so a store selling across several domains on a lower tier is discovering less than it thinks.
robots.txt is the other half of discovery, and Shopify generates one by default. The documentation says the default "works for most shops, so this template isn't included in any themes by default", and that the default rules are "mirrored through the Liquid robots object", which robots.txt.liquid uses to output them. If you need your own rules, add the template and append — do not paste static text over it. Shopify's stated reason is worth quoting because it is the whole argument: "The default rules are updated regularly to ensure that SEO best practices are always applied." A hand-written robots.txt is a snapshot of one afternoon's thinking that nobody will revisit.
The practical crawl work left to you, then, is small: make sure the store is public, make sure your internal linking actually reaches deep pages rather than relying on the sitemap alone, and do not disallow anything you also want canonicalised. A blocked URL cannot tell a crawler where its canonical version lives.
Render: Liquid is free, your JavaScript is not
Liquid renders on Shopify's servers. The HTML that comes back from a product URL already contains the title, the description, the price and the structured data, which means the rendering stage costs a crawler almost nothing for a conventionally built theme. That is a genuine architectural advantage and it is the reason most Shopify stores never think about rendering at all.
The exposure is content your team moved out of the server-rendered response. The usual culprits:
- Filtered and sorted collection grids fetched through the Section Rendering API. The API returns rendered section HTML for an AJAX request — useful, and it means the grid a shopper sees after clicking a filter arrived by JavaScript rather than in the initial response.
- Infinite scroll on collections, where products past the first page exist only if something scrolls.
- Tabs on product pages — delivery, care, specification — populated client-side from an app rather than printed in the markup.
- Review content injected by a third-party script, which is the most common reason a product page's visible reviews and its structured data disagree.
Render, continued: the things worth knowing about that API
If your theme uses the Section Rendering API, three documented details shape how you should build around it. It renders up to five sections per request. It does not let you specify section setting values — existing or default values apply. And a failed section comes back as null inside an otherwise successful response, so a request can return HTTP 200 with nothing useful in it.
That last one is the interesting one for search. A section that silently fails renders as an empty region on a page that reports success; nothing in your monitoring notices, and a crawler that does render the page sees a collection with no products in it. Null-check the response and fail loudly.
The general rule is simpler than the mechanics: whatever you need indexed should be in the server-rendered response. Use the API to make a page feel fast to a shopper, not to deliver content that has to be read. The test takes a minute — request the page with JavaScript disabled, or fetch it with curl, and read what comes back. If the products are not in it, the crawler is doing extra work to find them, and sometimes it will not.
Index: where Shopify stores actually lose
This is the stage that matters, and the problem is nearly always the same one: the store publishes many URLs that are the same page. Shopify does not do this to spite you — each source is a feature somebody wanted.
The variant parameter. The Liquid documentation gives product.url as a relative URL and its own example includes a variant parameter: /products/gorgeous-wooden-computer?variant=1234567890. It also documents that when products appear in search results or filtered collections, the URL carries the variant parameter of the most relevant variant, and that product recommendations append tracking parameters instead. So a product with twelve variants has at least thirteen reachable URLs before anyone has filtered anything, and your internal links point at several of them.
Filter combinations. Storefront filtering multiplies rather than adds, and a collection with five multi-select filters reaches six figures of URLs on its own. That deserves its own treatment and has it.
Collection-scoped product paths, tag pages, and app parameters. Every one of these produces a URL that renders the same content with a different address.
The lever is the canonical tag. Liquid exposes canonical_url as a global object, documented simply as "the canonical URL for the current page", and your theme decides what it does with it. That vagueness is the point to take seriously: do not assume what your store emits, open a filtered collection URL and a ?variant= product URL in your browser and read the source. Whatever is in the tag is your actual baseline, regardless of what the theme's README claims.
And be clear about which tool does which job. noindex keeps a URL out of results but does not save a crawl, because the crawler has to fetch the page to read the directive. robots.txt saves the crawl but hides the canonical. Canonicals consolidate. Three tools, three jobs, and using the wrong one is why most faceted-navigation fixes change nothing.
The pages worth having, and the cost of producing them
Everything above is defensive. It stops you competing with yourself; it does not earn a position. What earns positions is pages that answer a query better than the alternatives, which on a store means real collection pages for the category phrases people actually search — with their own h1, their own opening paragraph, their own buying guidance and their own internal links.
The reason most teams have three of these rather than thirty is production cost, not strategy. If every landing page needs a developer, the eleventh one never gets built, and the backlog quietly becomes an argument about priorities. A [section library](/services/build/shopify-section-library) — composable blocks a merchandiser arranges without touching code — turns that from a sprint into an afternoon, which is the only intervention we have seen reliably change how many good pages a store has.
Put crudely: the crawl and render stages are hygiene, and hygiene has a ceiling. The index stage is where you decide what you are asking to be ranked, and that is a content decision with a tooling dependency.
What we would check, in order
An hour, and it will tell you which stage your problem is in before anybody argues about strategy.
- Is the storefront password-protected? If so, nothing downstream is worth debugging yet.
- Fetch
/robots.txtand read it. Then check whether your theme has arobots.txt.liquidand, if it does, whether somebody replaced therobotsobject with static rules. - Fetch
/sitemap.xml, follow the child sitemaps, and confirm the product and collection counts match what you expect to be published. - Request a collection page with JavaScript disabled. Are the products in the HTML, or does the grid arrive through the Section Rendering API?
- Open a product URL with
?variant=on it and read the canonical tag. Then do the same on a filtered collection URL. - In Search Console, read the page indexing report by reason — "Duplicate without user-selected canonical" and "Crawled – currently not indexed" point at completely different work.
- Only then decide whether the answer is a canonical fix, a rendering fix, or ten collection pages that do not exist yet.
Questions this raises
How do search engines crawl a Shopify store?
Shopify generates a `sitemap.xml` automatically, which acts as an index linking to separate child sitemaps for products, collections, blogs and pages, and it updates as the store changes. It also generates a `robots.txt` whose default rules are maintained by Shopify. Crawlers discover URLs from those files and from your internal links, then fetch them. Discovery is rarely where a Shopify store fails.
Does Shopify create a sitemap automatically?
Yes, on every store. Shopify documents it as containing links to your products and their primary product image, pages, collections and blog posts, split across child sitemaps. Sitemaps for international domains are documented as available on the Basic, Shopify, Advanced and Plus plans. There is no reason to generate a second one.
Why is my Shopify store not being indexed?
Check private mode first — Shopify states that a sitemap reader cannot access your sitemap if the site is password-protected, which makes a pre-launch store invisible by design. After that, the usual cause is not discovery but duplication: many near-identical URLs from variant parameters, filters and tag pages, with canonical tags that do not consolidate them.
Should I edit robots.txt on Shopify?
Only if you have a specific rule to add, and then by adding `robots.txt.liquid` and appending to the output of the `robots` Liquid object rather than replacing it with static text. Shopify updates the default rules regularly so that current SEO practice keeps applying; a hand-written file opts you out of those updates permanently and nobody will remember to revisit it.
Does JavaScript hurt SEO on a Shopify theme?
Liquid renders on the server, so a conventional theme puts everything a crawler needs in the initial HTML. The risk is content you moved into JavaScript — filtered grids fetched through the Section Rendering API, infinite scroll, client-side tabs, injected reviews. The test is to load the page with JavaScript disabled and read what remains.
What does the ?variant= parameter do to SEO?
It creates additional URLs for the same product. Shopify documents `product.url` as including the variant parameter of the most relevant variant when products appear in search results or filtered collections, and product recommendations append tracking parameters instead. None of that is a problem provided every one of those URLs canonicalises to the clean product URL — which is worth verifying in your own theme rather than assuming.
NEXT STEP
Free store audit
A senior Shopify engineer reviews your storefront, theme performance and checkout, then sends a prioritised list of fixes.
