Magento 2 SEO Guide (2026): The Technical Blueprint for Higher Rankings
Magento 2 SEO for Magento Open Source and Adobe Commerce: admin settings to change, layered navigation fixes, Product JSON-LD, Core Web Vitals, Hyvä, AI search.
Magento 2 SEO trouble usually starts with numbers that don't add up. Search Console lists far more URLs than your store has products and categories, Googlebot spends its visits on filter and sort combinations, product pages take seconds to load, and the store slips out of Google results and AI answers. Magento 2 and Adobe Commerce let you control every URL, canonical tag, robots rule and sitemap. Few of those controls ship set the way a store needs them, and the platform creates extra URLs on its own.
Most Magento SEO fixes are admin settings and a few lines of robots.txt. The rest is theme work: complete Product JSON-LD, a lighter frontend, and HTML that crawlers can read without running JavaScript. Every admin path below is checked against Adobe's current documentation and linked next to the setting. Fixes that apply to every platform, such as out-of-stock products and variant URLs, are in ecommerce SEO and product page SEO.
TL;DR. Magento is SEO friendly once configured: canonical tags for products and categories ship turned off, "Use Categories Path for Product URLs" must stay at No, and /catalogsearch/ and the layered navigation toolbar parameters need robots.txt rules. Luma's microdata leaves out availability and brand and loads reviews with AJAX, so add one complete Product JSON-LD block with BreadcrumbList next to it. Run Varnish or Fastly as the page cache, and look at Hyvä, free and open source since November 10, 2025, when Luma's JavaScript keeps INP above 200 ms. PWA Studio and Edge Delivery storefronts render product data in the browser, so crawlers that don't run JavaScript need server-rendered or pre-rendered HTML. AI Overviews need no extra markup; ChatGPT, Claude and Perplexity need fast, complete HTML.
Is Magento SEO friendly?
Yes. Magento gives you more SEO control than most hosted platforms: editable URL keys, canonical tags, metadata per store view, URL rewrites and redirects, a robots.txt editor and an XML sitemap generator, all in the admin. With its default settings, a fresh Magento 2.4 store:
- outputs no canonical tags on product or category pages
- adds
.htmlto every product and category URL - tells crawlers
INDEX, FOLLOWon every page, internal search results included - creates a new URL for every layered navigation filter and every sort option
- marks up product pages with partial microdata
You can confirm the URL and canonical defaults in app/code/Magento/Catalog/etc/config.xml, where category_canonical_tag and product_canonical_tag are both 0.
Magento Open Source and Adobe Commerce share the same SEO core, so every setting below applies to both. Adobe Commerce adds content staging and B2B modules, and Adobe Commerce on cloud infrastructure uses Fastly as its page cache and CDN. Adobe Commerce as a Cloud Service works differently: Adobe marks the admin's metadata, sitemap and URL rewrite tools as "PaaS only" and points Cloud Service stores to the SEO guidelines for its Edge Delivery Services storefront.
The disadvantages of Magento for SEO come from scale and weight. Layered navigation multiplies URLs, the URL rewrite table grows with every catalog change, the Luma frontend ships a lot of JavaScript, and Adobe's newer storefronts render product data in the browser. Magento 1 reached end of life in June 2020. How Magento compares with Shopify, WooCommerce and BigCommerce on the same tests is in best ecommerce platform for SEO.
Magento 2 SEO settings to change first
The URL and canonical settings for Magento 2 SEO sit on one admin page. Go to Stores > Settings > Configuration, expand Catalog, choose Catalog, and open Search Engine Optimization. Clear the "Use system value" checkbox next to each field you change, then save.
| Setting | Default | Set it to | Why |
|---|---|---|---|
| Product URL Suffix | .html |
Leave it on a live store | Changing it changes every product URL at once |
| Category URL Suffix | .html |
Leave it on a live store | Same, for every category URL |
| Use Categories Path for Product URLs | No | No | Yes gives a product one URL per category it sits in |
| Use Canonical Link Meta Tag For Categories | No | Yes | Filtered and sorted category URLs point back to the plain category |
| Use Canonical Link Meta Tag For Products | No | Yes | Every route to a product points to /url-key.html |
| Create Permanent Redirect for URLs if URL Key Changed | Yes | Yes | Renamed products and categories 301 to the new URL |
| Generate "category/product" URL Rewrites | No from 2.4.6, Yes before | No, unless you use category paths | Yes writes rewrite rows for every product in a category on save, which Adobe warns can degrade performance |
| Page Title Separator | - |
Your choice | Separates category names in the browser title |
Adobe's canonical meta tag guidance describes the tag as the one that "tells search engines which page to index when multiple URLs have identical or similar content", and its recommendation is to turn it on for both categories and products.
The same settings have configuration paths, listed in Adobe's catalog configuration reference, so you can set them from the command line in a deploy script and keep them in config.php under version control:
bin/magento config:set catalog/seo/category_canonical_tag 1bin/magento config:set catalog/seo/product_canonical_tag 1bin/magento config:set catalog/seo/product_use_categories 0bin/magento config:set catalog/seo/save_rewrites_history 1bin/magento config:set catalog/seo/generate_category_product_rewrites 0bin/magento cache:flush
After saving, flush the page cache under System > Tools > Cache Management, open a product and a filtered category in a private window, and view the source. You should find one <link rel="canonical"> on each, pointing at the clean URL.
Each product and category also has its own Search Engine Optimization section on its edit page, with the URL Key, Meta Title, Meta Keywords and Meta Description fields. Those fields are covered under metadata below.
Best URL structure for Magento catalog pages
A product URL in Magento is its URL key with the suffix, at the root: /trail-runner-2.html. A category URL is the category path with the suffix: /men/shoes/trail.html. That is the structure to keep, and the settings that change it all sit in two admin sections.
Keep product URLs short and category URLs nested. The category path in a category URL tells Google where the page sits in the tree, and the breadcrumb markup below repeats it. The category path in a product URL only multiplies URLs, which is why "Use Categories Path for Product URLs" stays at No. A product that sits in three categories then has one URL, and the category pages link to it.
Leave the suffix alone on a live store. The .html suffix does nothing for ranking, and removing it on a store with indexed pages rewrites every product and category URL in one save. Magento creates the 301s if "Create Permanent Redirect for URLs if URL Key Changed" is on, but you still lose the old URLs' crawl history for a while. Decide the suffix before launch, and on a new store either value is fine.
Keep store codes out of URLs on a single-store install. Under Stores > Settings > Configuration > General > Web, the URL Options section has "Add Store Code to Urls". At Yes, every URL carries the store view code (/default/trail-runner-2.html). Leave it at No unless you run several store views on one domain and need the code to tell them apart.
Turn on web server rewrites. Under General > Web > Search Engine Optimization, "Use Web Server Rewrites" removes index.php from every URL. Adobe's URL rewrites page names this setting as the one that controls it. With it off, /index.php/trail-runner-2.html and /trail-runner-2.html both resolve, and Adobe's default robots.txt blocks /index.php/.
Redirect the base URL once. The same Web page has "Auto-redirect to Base URL" with the options No, Yes (302 Found) and Yes (301 Moved Permanently). Set it to the 301 option on a single-store install, so yourstore.com and www.yourstore.com resolve to the one base URL you chose. Adobe's note on the field: "Do not use auto-redirect to base URL for multi-store setups."
Check the 404 page returns a 404. Under General > Web > Default Pages, "Default No-route URL" is cms/noroute/index and "CMS No Route Page" is the 404 Not Found CMS page. Fetch a URL that does not exist with curl -I and confirm the status line says 404. A store that returns 200 for missing products fills the index with soft 404s.
URL keys. Adobe's product SEO settings say the URL key "should be all lowercase characters, with non-trailing hyphens between these characters", and that you should not add the suffix to the key, because the configuration adds it. By default Magento builds the key from the product name. For a product whose name is a model number, write the key by hand so it reads as the product.
Canonical tags across categories and products
With both canonical settings on, Magento writes one <link rel="canonical"> per page, and the rules for where it points are fixed.
Categories. The canonical on a category page is the plain category URL, https://yourstore.com/men/shoes/trail.html, whatever the query string. A filtered URL (?color=50), a sorted URL (?product_list_order=price) and a paginated URL (?p=3) all carry the same canonical. For filters and sorts that is what you want. For pagination it is a problem, covered in the robots and sitemap section below.
Products. The canonical on a product page is https://yourstore.com/url-key.html, the short form, even on a store with category paths on. Adobe's own example in the catalog configuration reference is a product reached at domain/category/product whose canonical is domain/product. So a shopper who reaches a product through /gear/bags/driven-backpack.html gets a page whose canonical is /driven-backpack.html, and Google consolidates the two.
Configurable products. Each simple product inside a configurable has its own URL key and its own canonical, pointing at itself. A blue size 9 Trail Runner 2 with its own page competes with the parent. Set simple products to Not Visible Individually when they have no search demand of their own, so only the parent has a page. The general rule for variant URLs across platforms is in technical SEO for ecommerce.
Store views. The canonical uses the base URL of the store view that served the page. On a multi-language store with one domain per store view, /fr/ pages point at /fr/ URLs. Magento does not add hreflang between them; that is extension or theme work.
Absolute URLs. Magento writes the full URL with scheme and host, which is what Google asks for: its duplicate URL guide says to "Use absolute paths rather than relative paths with the rel="canonical" link element." If your store runs behind a proxy or CDN that terminates TLS, confirm the canonical says https://, because a canonical that says http:// on an https:// page points Google at a redirect.
What the tag cannot do. Google treats the canonical as a signal it weighs with others; the same guide says Google "will identify which version of the URL is objectively the best version to show to users in Search". A canonical on a filtered URL still needs Google to crawl that URL to read it, and Google's guide also says "Don't use the robots.txt file for canonicalization purposes." So the canonical handles consolidation, robots.txt handles crawl volume, and they apply to different URL sets.
To check all of it at once, view the source of a product reached through a category path, a filtered category, a paginated category and a simple product inside a configurable. Each should carry exactly one canonical, and Search Console's Page indexing report should show the filtered URLs under "Alternate page with proper canonical tag" rather than as indexed pages.
Magento SEO and layered navigation
Layered navigation is Magento's name for faceted navigation, the filters on a category page. Each filter adds a query parameter with the attribute code and an option ID. The product list toolbar adds its own parameters for sorting, page size and view mode:
/women/tops.html?color=50/women/tops.html?color=50&size=167/women/tops.html?color=50&size=167&price=20-30/women/tops.html?color=50&product_list_order=price&product_list_dir=desc/women/tops.html?color=50&product_list_limit=36&product_list_mode=list
The count multiplies fast. With five colors, five sizes and four price ranges, one category has 180 filter states (6 × 6 × 5, counting "no filter" for each). Add the toolbar's three default sort fields, two directions, three grid page sizes (list mode has five) and two view modes, each of which can also be absent, and that one category exposes 25,920 URLs. Google's faceted navigation documentation says these filters "can generate infinite URL spaces", and that crawlers fetch a large share of them before deciding they're useless.
Which attributes become filters is set per attribute. Under Stores > Attributes > Product, each attribute's Storefront Properties has Use in Layered Navigation, with the options "Filterable (with results)" and "Filterable (no results)". The second shows every value, including values with no matching products, so a crawler following them lands on empty lists. Use "Filterable (with results)", and set the attribute to filterable only when shoppers filter by it. A category only shows filters when its Display Settings have Anchor set to Yes. The price step settings sit under Stores > Settings > Configuration > Catalog > Catalog > Layered Navigation, and the toolbar's sort fields, page sizes and list modes under the Storefront section of the same page.
Turning on canonical tags for categories points every one of those URLs at the plain category. That helps indexing, but Google still has to crawl a URL to read its canonical.
The crawl also hurts speed. Magento's Varnish configuration strips tracking parameters such as gclid, fbclid and utm_* before caching, but layered navigation and toolbar parameters stay in the URL Varnish caches by. A crawler working through filter combinations that no shopper has opened gets a cache miss on almost every request, so PHP builds each page from scratch.
Robots.txt rules for layered navigation
Block the toolbar parameters everywhere, and the filters you never want in search. Use your own attribute codes, and keep ?p= (pagination) crawlable so Google can reach products deep in a category:
User-agent: *# Internal searchDisallow: /catalogsearch/# Sorting, page size and view modeDisallow: /*?*product_list_order=Disallow: /*?*product_list_dir=Disallow: /*?*product_list_limit=Disallow: /*?*product_list_mode=# Filters you never want crawledDisallow: /*?*price=Disallow: /*?*size=# Account, cart and checkoutDisallow: /checkout/Disallow: /customer/Disallow: /wishlist/Sitemap: https://yourstore.com/sitemap.xml
If filter URLs are already indexed, don't add these rules yet. A common Magento setup has an SEO extension set NOINDEX, FOLLOW on filtered pages while robots.txt blocks the same parameters. Google's robots meta documentation is direct: "For the noindex rule to be effective, the page or resource must not be blocked by a robots.txt file". Google never sees the noindex, and the blocked URLs can stay in the index. Remove them with the noindex steps in faceted navigation SEO, then add the robots.txt rules.
Some filter pages are worth ranking, such as a brand or "red dresses". Give those a clean URL with its own title, H1, copy and sitemap entry. In Magento that's a subcategory, or an extension that rewrites chosen filters to static URLs. Which filters deserve a page, and how to read the result in Search Console, is in Magento layered navigation SEO, with the platform-independent method in faceted navigation SEO.
Some layered navigation extensions filter with AJAX and never change the URL. That keeps crawlers out of filter combinations, and it also means a filter page you want to rank has no URL to rank with.
Layered navigation bloat shows up in a crawl as one category with hundreds of URLs sharing one title and one meta description. A site audit crawls the store as Googlebot would, groups pages by shared title, body and canonical, and lists the parameters behind each cluster, so you can see which attribute codes to block before you touch robots.txt.
Common Magento SEO issues: duplicate URLs, search pages and the rewrite table
Category paths in product URLs
With "Use Categories Path for Product URLs" set to Yes, a product in Gear > Bags answers at /gear/bags/driven-backpack.html and at /driven-backpack.html, and once more for every other category it's in. Adobe's configuration reference warns that "Doing so can cause multiple URLs to point to the same page, which might impact search rank", and the product canonical stays on the short domain/url-key form either way. Set the option to No, keep product canonicals on, and check that internal links and the sitemap use the short URL. Category-path URLs that already exist in the rewrite table can keep resolving, so the canonical tag does the cleanup.
Legacy /catalog/product/view/id/ URLs
Every product also answers at Magento's raw route, /catalog/product/view/id/123, and every category at /catalog/category/view/id/45. Both return the page with a 200. Your store starts linking to them when a product has no row in the URL rewrite table: Magento's product URL code then falls back to /catalog/product/view/id/123/s/url-key/category/4/.
Finding these in Search Console or your server logs means rewrites are missing, usually after a catalog import. Re-saving a product regenerates its rewrites; for thousands, use a URL rewrite regeneration module. Keep product canonicals on, and 301 any raw URLs that picked up external links.
Internal search pages
Magento's search results live at /catalogsearch/result/?q=. The page sets no robots tag of its own, so it inherits your store default, which is INDEX, FOLLOW. Search URLs linked from other sites, or created by your own search box, can end up indexed. Disallow /catalogsearch/ in robots.txt. If some are already indexed, add a noindex to the search results template first and block them once they've dropped out.
The URL rewrite table
Every URL key, category-path variant and automatic redirect lives in the url_rewrite table, and it grows with every import, category move and renamed product. Count what's in it (add your table prefix if the store uses one):
SELECT entity_type, redirect_type, COUNT(*) AS urlsFROM url_rewriteGROUP BY entity_type, redirect_type;
A redirect_type of 0 is a live URL; 301 and 302 are redirects. A product count far above your catalog size points at category-path rows. A large 301 count is worth checking for chains, where an old URL redirects to another redirect. Review single rows under Marketing > SEO & Search > URL Rewrites, where each row has a Request Path, a Target Path and a Redirect field with the options No, Temporary (302) and Permanent (301). Adobe's URL rewrites overview confirms that "automatic URL redirects are enabled for your store" by default, so a renamed URL key gets its 301 without a manual row.
Store views and hreflang
Magento doesn't output hreflang tags for store views. Multi-language and multi-country stores need an extension or theme code that links each store view's version of a page, plus one sitemap per store view.
Robots.txt, pagination and the XML sitemap in the Magento admin
Magento serves robots.txt from the admin. Go to Content > Design > Configuration, edit the Global row (or a website row on a multi-site install), and expand Search Engine Robots:
- Default Robots sets the robots meta tag on every page. The four options are
INDEX, FOLLOW,NOINDEX, FOLLOW,INDEX, NOFOLLOWandNOINDEX, NOFOLLOW. Keep it atINDEX, FOLLOWon production, and check it after every launch: a staging value ofNOINDEX, NOFOLLOWleft in place drops the whole store from search. - Edit custom instruction of robots.txt File holds your rules.
- Reset to Default fills the box with Adobe's default rules. They include
Disallow: /*?, which blocks every URL with a query string (pagination included),Disallow: /catalog/, which stops Google from reading the canonical tags on raw/catalog/product/view/URLs, andDisallow: /review/, which blocks the URL Luma loads reviews from.
Adobe's own advice is to keep the admin path out of the file. On Adobe Commerce on cloud infrastructure, you don't write a robots.txt file: Adobe's cloud guide says Commerce "generates the robots.txt content on demand and stores it in the database". The same guide says the sitemap must be written under /media/, because the root is not writable on cloud, and gives a Fastly snippet that serves /sitemap.xml from /media/sitemap.xml. It also notes that indexing by search engines "can only be enabled in Production, but not in any of the lower environments", so robots.txt edits in staging change nothing.
Once the file is live at the root, run your domain through the robots.txt analyzer to see which rules Googlebot, GPTBot and ClaudeBot follow and whether any of them is blocked.
Pagination on category pages
Magento paginates a category with ?p=2, ?p=3 and so on, and the toolbar's page-size and list-mode choices add their own parameters next to it. Three things keep paginated pages useful to crawlers.
Keep ?p= out of robots.txt. Adobe's default Disallow: /*? blocks it along with every other query string, and a blocked page 2 means products on pages 2 through 40 are reachable only through the sitemap.
Give each page its own canonical. Google's pagination guide says "Don't use the first page of a paginated sequence as the canonical page." Magento's category canonical does exactly that, pointing ?p=3 at the plain category. Most SEO extensions can set the canonical of a paginated page to itself; without one, a small theme change does the same.
Link the pages in sequence with plain <a href> tags, which Luma's toolbar does. Google's guide notes that it "no longer uses" rel="next" and rel="prev", and that it "ignores fragment identifiers", so a theme that pages with #p=2 or with a JavaScript-only "Load more" button hides every product past the first page from crawlers that read the HTML.
Under Stores > Settings > Configuration > Catalog > Catalog > Storefront, "Remember Category Pagination" keeps a shopper's page-size choice as they move between categories. Adobe notes it uses more cache storage; it has no effect on crawlers, which never carry the session.
The XML sitemap
For the sitemap, go to Stores > Settings > Configuration > Catalog > XML Sitemap:
- Set Frequency and Priority under Categories Options, Products Options and CMS Pages Options.
- Set Add Images into Sitemap to Base Only or All.
- Under Generation Settings, set Enabled to Yes and pick a Start Time. Large catalogs can switch Generation Method to Batch, which Adobe's page says "is available starting with the 2.4.9 release".
- Under Sitemap File Limits, keep Maximum No of URLs Per File at or below 50,000, the limit the sitemap protocol sets per file.
- Under Search Engine Submission Settings, set Enable Submission to Robots.txt to Yes.
- Create the file itself under Marketing > SEO & Search > Site Map: click Add Site Map, enter the filename and path, and click Save & Generate.
Generation runs on cron. If cron stops, the sitemap goes stale without warning, so set an Error Email Recipient. Then spot-check a few entries: each URL should return a 200 and carry a canonical tag pointing to itself. Products set to Not Visible Individually and disabled products stay out of the file; category-path product URLs only appear if you turned that setting on.
Magento SEO best practices for metadata across the catalog
Magento sets metadata at three levels, and a title on a product page comes from whichever level set it last: the store default, the auto-generation mask, then the field on the product itself.
Store defaults. Under Content > Design > Configuration, the HTML Head section of each store view holds Default Page Title, Page Title Prefix, Page Title Suffix, Default Meta Description and Default Meta Keywords. The prefix and suffix wrap every page title in the store view, so a suffix of | Yourstore lands on every product, category and CMS page. Keep it short, because it eats into the characters Google shows. Leave Default Meta Description empty: a store-wide description copied onto thousands of pages is worse than none, since Google then writes its own from the page.
Auto-generation masks. Under Stores > Settings > Configuration > Catalog > Catalog > Product Fields Auto-Generation, Magento pre-fills new products with "Mask for Meta Title" ({{name}}) and "Mask for Meta Description" ({{name}} {{description}}). The masks only run when a product is created, and they only use product fields, so a mask cannot add the brand or category. Set the title mask to {{name}} and let the store suffix add the brand, and set the description mask to {{description}} on its own, since a description that starts with the product name repeats the title.
Per product and per category. Each product's Search Engine Optimization section and each category's Search Engine Optimization section have URL Key, Meta Title, Meta Keywords and Meta Description, all scoped to the store view. Adobe's guidance on both pages: a meta title "unique to the page and fewer than 70 characters in length", and a meta description with "An ideal length is between 150-160 characters in length, with a maximum of 255 characters."
Where to spend the hand-written effort. Sort products by revenue in Reports > Sales and write titles and descriptions by hand for the categories and the top products. Categories first: one category title reaches every search for that product type, and a category with only a product grid gives Google little text to rank, so write a short introduction in each category's Content section. A product title that reads "Trail Runner 2 Men's Trail Running Shoe | Yourstore" beats the mask's "Trail Runner 2 | Yourstore" for every search that names the type.
Templates for the long tail. For thousands of products nobody will hand-edit, a rule-based template per category, such as {{name}} {{brand}} {{category}} | Yourstore, needs an extension; Magento's masks cannot do it for existing products. That is one of the four cases in the decision table below.
Meta Keywords. Google ignores them. Leave the field empty.
Configurable products. Set the simple products that make up a configurable to "Not Visible Individually", so only the parent has a product page and a title.
Image alt text. Set Alt Text on each product image in the image detail panel, describing the product and its variant. Google's image guidance and the rest of the product page work are in product page SEO.
Product schema: Luma's microdata vs full Product JSON-LD
Luma marks up product pages with schema.org microdata. Magento's templates cover the product name, SKU, description and image, an Offer with price and currency, the rating summary, and individual reviews.
It leaves out availability, brand, gtin or mpn, itemCondition, shipping and return details, and variants for configurable products. Google lists availability, brand and the rating among the recommended properties for merchant listings.
Reviews have a second problem. The review list in the Reviews tab (#product-review-container) ships empty, and Magento's process-reviews.js fills it with AJAX from /review/product/listAjax/ when the tab opens, or at page load if the tab is already open. Googlebot doesn't click tabs, AI crawlers don't run the script at all, and Adobe's default robots.txt rules block /review/. The review text and its markup are missing from what every crawler reads.
Google's product structured data guide "recommends using JSON-LD for structured data if your site's setup allows it". Add one Product JSON-LD block to your product page template, rendered on the server, and remove Luma's microdata attributes from your theme so the page describes the product once:
<script type="application/ld+json">{"@context": "https://schema.org","@type": "Product","name": "Driven Backpack","sku": "24-WB03","gtin13": "0123456789012","brand": { "@type": "Brand", "name": "Your Brand" },"image": ["https://yourstore.com/media/catalog/product/d/r/driven-backpack.jpg"],"description": "Your product description.","offers": {"@type": "Offer","url": "https://yourstore.com/driven-backpack.html","price": "36.00","priceCurrency": "USD","availability": "https://schema.org/InStock","itemCondition": "https://schema.org/NewCondition"},"aggregateRating": {"@type": "AggregateRating","ratingValue": "92","bestRating": "100","reviewCount": "18"}}</script>
Magento stores ratings as a percentage, so either set bestRating to 100 as above or convert to a five-point scale. For configurable products, describe the parent as a ProductGroup with a hasVariant entry per child, following Google's product variants guide. The price, currency and availability in the block must match what the page shows and what your Merchant Center feed says; Google's AI features guide asks for "Making sure your structured data matches the visible text on the page."
BreadcrumbList on categories and products
Luma prints a breadcrumb trail on every category and product page, with no markup behind it. Add a BreadcrumbList block next to the Product block. Google's breadcrumb documentation says it "uses breadcrumb markup in the body of a web page to categorize the information from the page in search results", and the item URL may be left off the last entry, in which case Google uses the page's own URL:
<script type="application/ld+json">{"@context": "https://schema.org","@type": "BreadcrumbList","itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Gear", "item": "https://yourstore.com/gear.html" },{ "@type": "ListItem", "position": 2, "name": "Bags", "item": "https://yourstore.com/gear/bags.html" },{ "@type": "ListItem", "position": 3, "name": "Driven Backpack" }]}</script>
On a product reached through two categories, build the trail from the product's primary category, so the same product always reports the same path.
FAQ markup on product and category pages
Google removed FAQ rich results from Search. Its documentation changelog says "This feature will no longer appear in Google Search starting May 7, 2026", and the FAQ structured data reference was taken down in June 2026. A FAQPage block on a Magento product page no longer earns a rich result. What still helps is the visible question and answer text: sizing, shipping, returns and compatibility answers in the product description give Google and AI assistants text to quote. Write them into the page, and add the markup only if another consumer of your HTML reads it.
Hyvä's structured data
Hyvä ships its own product structured data, separate from Luma's templates. Hyvä's default theme changelog lists an entry in 1.4.4 (March 2026) that added "availability and priceValidUntil for product rich snippet", and a 1.5.3 fix (October 2026) for the Offer price on MSRP products. After a Luma to Hyvä migration, test a product page in the Rich Results Test before you trust the old markup is still there, and if you added a JSON-LD block to Luma's theme, move it into the Hyvä theme or the page describes the product twice.
Write the JSON-LD into the server-rendered template. Product markup added with JavaScript can make Google's Shopping crawls less frequent, and crawlers that don't run JavaScript never see it; JSON-LD injected by JavaScript has Google's warning and a check. Test a product with Google's Rich Results Test, then check the whole catalog: the site audit flags indexable pages with no JSON-LD and pages with invalid markup.
How to pass Core Web Vitals on Magento 2
Google's thresholds, measured at the 75th percentile of real page loads, are 2.5 seconds for Largest Contentful Paint, 200 milliseconds for Interaction to Next Paint and 0.1 for Cumulative Layout Shift. Interaction to Next Paint replaced First Input Delay as a Core Web Vital on March 12, 2024, per web.dev. On Magento, LCP is usually a cache problem, INP is a frontend problem, and CLS is an image and banner problem.
Full page cache. Go to Stores > Settings > Configuration > Advanced > System > Full Page Cache. Caching Application offers Built-in Application and Varnish Caching, and Adobe's reference labels the built-in one "Not recommended for the production environment." Adobe Commerce on cloud uses Fastly. Every deploy or full cache flush empties the cache, and the first crawler to reach each page waits for PHP, so warm the cache for your top categories and products after a flush. TTL for public content defaults to 120 seconds on that page; raise it for category and product pages, since Magento purges tagged pages when a product changes anyway.
Production mode. Run bin/magento deploy:mode:set production so static files are compiled and served as files.
The frontend. Luma is built on RequireJS, jQuery and Knockout, and product and category pages load a long list of scripts. The browser parses and runs them before it can respond to a tap on a swatch or the add-to-cart button, which is what INP measures. On Luma, the usual way under 200 ms is to defer or bundle the scripts and strip the modules you don't use; the full move is a frontend change.
Hyvä. Hyvä replaces Luma's frontend stack with Tailwind CSS and Alpine.js. Hyvä's announcement says that "Starting November 10, 2025, the Hyvä Theme will be freely available on GitHub and via free Packagist Composer keys", relicensed to OSL3 and AFL3; Hyvä Checkout, Enterprise and Commerce stay commercial. Your extensions need Hyvä compatibility modules, so check each one before you switch. Hyvä changes the frontend only; URLs, canonicals and layered navigation still follow the admin settings above, and the structured data changes as described in the schema section.
Images. The main product image is usually the LCP element, so load it right away with fetchpriority="high", give it fixed width and height attributes, and lazy-load only images below the fold. A product image without dimensions is the usual CLS cause on Luma, along with promo banners that load after the grid. Image formats, sizes and Google's "good" threshold for each Core Web Vital are in ecommerce SEO.
Extensions and scripts. Each module can add scripts and layout blocks to every page. Disable the ones you don't use (bin/magento module:disable), and audit tag manager containers for tracking scripts nobody reads. A chat widget or a review widget that loads on every page costs INP on every page.
Measure the right pages. Search Console's Core Web Vitals report uses field data from real Chrome users, grouped by URL pattern, so a failing category template shows as one group covering thousands of URLs. Run PageSpeed Insights on a product page and a filtered category too, since those templates carry most of the store's URLs. Pass or fail is per template, so fix the template, re-measure after 28 days of field data, and move to the next one. The template-level method is in technical SEO for ecommerce.
PWA Studio, Venia and headless Magento storefronts
Adobe's PWA Studio, with its Venia reference storefront, and the newer Edge Delivery Services storefront both move product rendering into the browser.
PWA Studio's content rendering documentation describes the first response as "a pre-built, server-side rendered HTML response that contains the PWA application shell" from the UPWARD server. After that, "a JavaScript bundle renders the rest of the page content on the client side". The same page notes that a search engine crawler "indexes the initial HTML response from the server." For Edge Delivery Services, Adobe's own prerender guide says: "By default, Adobe Commerce on Edge Delivery Services renders product information with client-side JavaScript". Adobe built AEM Commerce Prerender, an App Builder app that "runs in Adobe's cloud on a schedule, polling your product catalog and generating HTML for each product", for that storefront only.
Custom headless builds on Magento's GraphQL API, with Next.js or a similar framework, render the first view on the server. Sections fetched in the browser after that, such as reviews, stock, customer-group prices and recommendations, still miss crawlers that read only the first response. More on that in JavaScript SEO.
Googlebot renders these pages after a delay. GPTBot, ClaudeBot and PerplexityBot don't run JavaScript at all, so they read the shell: no product name, no price, no description. Do AI crawlers render JavaScript has the full crawler breakdown.
How to audit rendering on headless Magento
Fetch a product page the way each crawler does and search the response for what a shopper sees:
curl -s -A "GPTBot" https://yourstore.com/trail-runner-2.html \| grep -c -E 'Trail Runner 2|"price"|application/ld\+json'
A count of 0 means the first response holds none of the product name, the price or the JSON-LD, and every crawler that doesn't run JavaScript indexes an empty shell. Repeat with -A "Googlebot" to confirm the server sends the same shell to Google, then run the URL through Search Console's URL Inspection with a live test and open the rendered HTML; the gap between the two is what Google has to render and what AI crawlers never get. The crawler simulator does the same comparison across two dozen user agents, with the HTML each one received side by side. Run it on a product, a category, a filtered category and the home page, because a storefront can server-render the home page and still ship a shell for products.
Then check the second layer: reviews, stock and customer-group prices that a server-rendered storefront fetches after load. Search the first response for one line from a review. If it is missing, the review markup is missing with it. The theme-by-theme results, Hyvä against PWA Studio against Vue Storefront, and where schema breaks on each migration, are in headless Magento SEO.
With Encited, crawlers get a pre-rendered snapshot of each page with the product data already in the HTML, and AI crawlers that ask for Markdown get Markdown. Shoppers keep getting the PWA, and the store needs no server-side rendering rebuild. This approach is called dynamic rendering, and the pre-rendering setup is a DNS change or a Cloudflare Worker in front of the store, with no Magento module to install. For product pages that fill in late, set window.prerenderReady = false in the page's HTML shell and true once the product data is on the page. The renderer waits for the flag before it stores the snapshot.
How to get a Magento store cited in AI Overviews and ChatGPT
AI Overviews and AI Mode pick pages from Google's index, so the work above is the work. Google's AI features guide says "There are no additional requirements to appear in AI Overviews or AI Mode, nor other special optimizations necessary", and "You don't need to create new machine readable files, AI text files, or markup to appear in these features." A Magento product page gets cited when it is indexed under one canonical URL, carries Product markup that matches the visible price and availability, and answers the question in its own text: fit, materials, compatibility, shipping and returns.
ChatGPT, Perplexity and Claude work differently. Their crawlers fetch the page and read the HTML as sent. OAI-SearchBot is OpenAI's search crawler and GPTBot its training crawler; blocking GPTBot does not remove you from ChatGPT search, and blocking OAI-SearchBot does. Allow the search crawlers in robots.txt, and check your CDN or firewall bot rules, which can block them while robots.txt allows them:
User-agent: OAI-SearchBotAllow: /User-agent: PerplexityBotAllow: /User-agent: ClaudeBotAllow: /
None of these crawlers runs JavaScript, so a Luma page gives them the product without its reviews, and a PWA Studio page gives them the shell. The AI crawl checker shows which AI crawlers your robots.txt and your server let through, and what each one receives.
llms.txt and a machine-readable catalog
The llms.txt proposal adds "a /llms.txt markdown file to websites to provide LLM-friendly content": a file with an H1, a short summary in a blockquote, and H2 sections of links with a line of notes each. It also proposes a Markdown version of each page at the same URL with .md appended. Google's guide above says none of this is needed for AI Overviews, and no AI engine has published that it reads the file. The cost is low, so a store can publish one that lists the category pages and the buying guides, with one line per link saying what the page answers.
Two rules for a catalog store. Link only pages a crawler can already fetch, so the file never becomes a side door to pages robots.txt blocks. And keep customer data, prices by customer group and B2B catalogs out of it: the file is public, and a Markdown export of a logged-in price list is a leak. Encited serves AI crawlers a Markdown version of each pre-rendered page when they ask for it, built from the same public HTML shoppers see, so the catalog stays machine-readable without a second export.
Slow pages and 499s
AI fetchers skip pages that load slowly, such as a Magento page that misses the cache and waits on PHP, and Nginx logs each request they give up on as a 499, its status for a client that closed the connection before the response was sent. How each AI engine picks and drops its sources is in how to rank in LLMs. Slow responses also lower how much Googlebot crawls.
Check your own logs. On Nginx's default log format, this lists the URLs AI fetchers gave up on:
awk '$9 == 499' /var/log/nginx/access.log \| grep -iE 'Claude-User|ClaudeBot|ChatGPT-User|GPTBot|OAI-SearchBot|PerplexityBot|Perplexity-User' \| awk '{print $7}' | sort | uniq -c | sort -rn | head -20
If Varnish or a CDN sits in front of Nginx, the disconnect shows up in that layer's logs instead.
Pre-rendering fixes the wait for crawlers. With Encited, each snapshot is stored across 300+ locations and served from the one closest to the crawler, so a fetcher with a short timeout gets the full page. Your crawl log lists each bot visit with the status it got back and how long it waited. To see whether ChatGPT, Perplexity, Gemini, Claude and Google AI Overviews mention your store once they can read it, add the questions your buyers ask to the AI visibility tracker. It runs each prompt across the engines, records which brands each answer names and which pages it cites, so you know whether your category page or a retailer's roundup is the source.
Magento SEO extensions vs native settings
Native Magento covers the settings that decide most of a store's SEO. An extension earns its place for four jobs, and each row below says which.
| Task | Native Magento 2 | Needs an extension or theme code |
|---|---|---|
| Meta title and description | Per product, category and store view; masks for new products | Rule-based templates for existing products and categories |
| Canonical tags | Products and categories | Rules for filtered and paginated pages |
| Robots meta | One default per website or store view | Per page or per URL pattern |
| Filter URLs | Query parameters only | Static, readable filter URLs with their own titles |
| XML sitemap | Yes, on cron | HTML sitemap, extra URL types |
| Redirects | URL rewrites, automatic 301 when a URL key changes | Bulk import, 404 monitoring |
| Product structured data | Partial microdata | Complete Product JSON-LD |
| hreflang | No | Yes |
| HTML for crawlers on PWA Studio or Edge Delivery storefronts | No | No; needs server-side rendering or pre-rendering |
The decision depends on the store, so take it by store rather than by feature:
| Your store | Native settings are enough | An extension earns its place |
|---|---|---|
| One language, one store view | Yes | |
| Several store views in different languages | Yes: hreflang between store views | |
| Under a few thousand products, titles written by hand for the ones that sell | Yes | |
| Tens of thousands of products that nobody will hand-edit | Yes: rule-based title and description templates | |
| Filters that should rank (brand, color, material) | Yes: static filter URLs with their own titles and copy, or subcategories built by hand | |
| Paginated categories that should keep their own canonical | Yes, or a small theme change | |
| Catalog imports and migrations that leave 404s | Yes: 404 monitoring and bulk redirect import | |
| Product JSON-LD | Theme change | Yes, if nobody can edit the theme |
| Slow pages, PWA Studio shell, missing reviews in the HTML | Neither | Neither; this is cache, frontend or rendering work |
A store in the left column runs on native settings plus a Product JSON-LD block in the theme. A store with one Yes in the right column usually gets more from the one module that does that job than from a suite. The suites, Mageworx SEO Suite Ultimate, Amasty SEO Toolkit Pro, Mirasvit Advanced SEO Suite and Mageplaza SEO, overlap on meta templates, canonical and robots rules, rich snippets, hreflang and sitemaps; what each one does, what it costs and which support Hyvä is in Magento 2 SEO extensions. Whatever you pick, an extension edits the HTML Magento outputs. It can't make a slow page fast or put product data into a page that renders in the browser.
How to run a Magento SEO audit
- Compare counts. Put the indexed count from Search Console's Page indexing report next to your count of enabled, visible products and categories. A large gap either way is your first lead. Read the reasons under "Crawled - currently not indexed" and "Duplicate, Google chose different canonical than user"; the crawled, currently not indexed guide covers the first. For new products stuck in "Discovered - currently not indexed", Index Rush shows the index status of each URL, points at indexed pages that should link to it, and requests indexing in one click.
- Check the settings. Walk the Search Engine Optimization table above, the Search Engine Robots section, and the live
https://yourstore.com/robots.txt. - View the source of four pages: a product, a filtered category, a search results page and a CMS page. Look for one canonical tag, the robots meta tag, and the JSON-LD.
- Query the rewrite table with the SQL above.
- Crawl the store. The site audit crawls the store and groups what it finds: pages that share the same body, title or meta description, canonical problems, redirect chains, and missing or invalid structured data. Layered navigation bloat shows up as clusters of duplicate titles on one category.
- See where crawlers spend their visits. Search Console's Crawl stats report breaks requests down by response and file type. Your server logs, or the Encited crawl log if your store runs through Encited, show which URLs Googlebot actually requests. If most hits carry
product_list_or filter parameters, the robots.txt rules above are your first fix. The same log shows which AI bots got errors or waited too long. - Test rendering on PWA Studio and Edge Delivery storefronts with the crawler simulator, as an AI crawler and as Googlebot, following the headless audit steps above.
The same test catches a Luma problem: open a product page as GPTBot in the crawler simulator and search the HTML for a line from one review. Reviews that load when the tab opens won't be in it. The order of checks for any platform, with the pass condition for each, is in ecommerce SEO audit.
Magento SEO checklist
Admin settings
- Use Canonical Link Meta Tag For Categories: Yes.
- Use Canonical Link Meta Tag For Products: Yes.
- Use Categories Path for Product URLs: No.
- Create Permanent Redirect for URLs if URL Key Changed: Yes.
- Default Robots on production:
INDEX, FOLLOW. - Simple products inside configurables: Not Visible Individually.
- Use Web Server Rewrites: Yes. Add Store Code to Urls: No on a single store. Auto-redirect to Base URL: 301.
URLs and crawling
- robots.txt blocks
/catalogsearch/, the fourproduct_list_parameters and the filters you never want crawled. - No URL is both blocked in robots.txt and tagged noindex.
- Pagination (
?p=) stays crawlable, and each page carries its own canonical. - Filters with search demand have their own static URLs, titles and copy.
- No internal links point to
/catalog/product/view/id/URLs. - The admin path is not in robots.txt.
- Missing pages return a 404 status.
Sitemaps and indexing
- XML sitemap generation is enabled on cron, with an error email set.
- The sitemap lists canonical product, category and CMS URLs only.
- One sitemap and hreflang per store view on multi-language stores.
- The sitemap is submitted in Search Console.
Content and schema
- Hand-written titles and descriptions for top categories and products; a title suffix, no store-wide meta description.
- One Product JSON-LD block per product page with price, availability, brand and GTIN, matching the visible page.
- ProductGroup markup for configurable products, BreadcrumbList on products and categories.
- Reviews in the server-rendered HTML.
- Structured data re-tested after a Hyvä migration.
Speed and rendering
- Varnish or Fastly in front of the store, and the cache warmed after deploys.
- Production mode on, unused modules disabled.
- Core Web Vitals passing for product and category templates in Search Console.
- PWA Studio, Edge Delivery and headless pages serve product data in the first HTML response, through server-side rendering or pre-rendering.
- OAI-SearchBot, PerplexityBot and ClaudeBot allowed in robots.txt and at the CDN; AI fetchers get 200s, with no 499s in the logs.
Monitoring
- Page indexing report checked monthly against catalog size.
- Crawl stats and logs checked for parameter URLs.
- A site audit after every theme, extension or catalog structure change.
- Buyer prompts tracked across ChatGPT, Perplexity, Gemini, Claude and AI Overviews.
FAQ
Is Magento SEO friendly? Yes, once configured. Magento Open Source and Adobe Commerce give you control over URLs, canonical tags, robots rules, sitemaps and redirects. The defaults need work: canonical tags are off, search results are indexable, and layered navigation creates a URL for every filter combination.
Does Magento 2 need an SEO extension, or are native settings enough? Native settings plus a Product JSON-LD block in the theme cover a single-language store without filter landing pages. Multi-language stores need an extension for hreflang, and large catalogs usually want rule-based meta templates and static filter URLs. No extension makes a slow page fast or puts product data into a page that renders in the browser.
How do I fix index bloat from layered navigation in Magento?
Turn on canonical tags for categories, block the toolbar parameters and the filters you never want crawled in robots.txt, and keep /catalogsearch/ out of the index. If filter URLs are already indexed, noindex them first and add the robots.txt rules after they drop out. Give filters with search demand their own static pages.
Should I block layered navigation URLs in robots.txt or noindex them? Use one per URL. robots.txt stops crawling of URLs that were never indexed. Noindex removes URLs that are already indexed, and it only works while Google can still crawl them, so a URL that is both blocked and tagged noindex keeps its place in the index.
How do canonical tags work across Magento categories and products? With both canonical settings on, every filtered, sorted or paginated category URL points at the plain category URL, and every route to a product points at the product's own URL key, whatever category path the shopper came through. Simple products inside a configurable get their own canonical, so set them to Not Visible Individually when they have no demand of their own.
What is the best URL structure for Magento catalog pages?
Short product URLs without the category path, category URLs that mirror the category tree, one suffix kept as it is on a live store, no store code in the URL on a single-store install, web server rewrites on so index.php never appears, and a 301 from every old URL when a key changes.
How do I pass Core Web Vitals on Magento 2? Run Varnish or Fastly as the full page cache and warm it after every flush, run production mode, serve the main product image at a fixed size without lazy loading, cut unused modules and tag manager scripts, and move the frontend to Hyvä if Luma's JavaScript keeps INP above 200 ms. Measure product and category templates in Search Console's Core Web Vitals report.
Does Hyvä improve Magento SEO? It improves speed, which helps Core Web Vitals and crawling. Hyvä replaces Luma's RequireJS, jQuery and Knockout stack with Tailwind CSS and Alpine.js, and the theme has been free and open source since November 10, 2025. URLs, canonicals, robots and layered navigation settings work the same as on Luma, and Hyvä ships its own product structured data, so check the markup after a migration.
How do I audit rendering on headless Magento? Fetch a product page as GPTBot and as Googlebot without running JavaScript and search the response for the product name, price, description and the Product JSON-LD. On PWA Studio and Edge Delivery Services storefronts the first response is an application shell with none of those, and crawlers that do not run JavaScript read only that shell. Server-side rendering or pre-rendering puts the product data in the first response.
How do I get a Magento store cited in AI Overviews and ChatGPT? AI Overviews draw on Google's index, and Google says no extra markup or files are needed, so the same fixes apply: one canonical URL per product, complete Product JSON-LD that matches the visible page, and fast pages. ChatGPT, Claude and Perplexity fetch pages without running JavaScript and give up on slow ones, so serve them complete HTML quickly and allow OAI-SearchBot, ClaudeBot and PerplexityBot in robots.txt.
