What an honest SEO audit of a Magento shop really turns up
- seo
- magento
- audit
- e-commerce
Most Magento shops I open in Search Console have the same story: set up five years ago by someone who's long gone, a pile of modules stacked on top of each other, and an owner who "thinks the SEO is probably fine because we see some traffic coming in". That traffic usually runs on brand recognition. The brand gets typed in by existing customers, not by searchers looking for a product.
When I did an SEO audit on a shop with 13,600 product pages in four languages, I found things I hadn't seen in ten years of web work. Below I lay out what I found, how I knew it was broken, and what we did to fix it without rebuilding the whole site.
What I found when I actually looked
An SEO audit that only runs Lighthouse and a crawl misses 90 percent. I always open twenty product pages in each language myself, copy the rendered HTML, validate the JSON-LD separately, and compare the hreflang output between language variants. This is what came out:

Product JSON-LD was invalid on 97 percent of PDPs. Not "a field forgotten", actually broken. The responsible module had run nl2br() on the product description before putting it into a JSON string. That left raw \r\n in the output. Google's Rich Results Test saw invalid JSON and discarded the entire structured data. Result: zero product snippets in search results, while every competitor was showing stars and prices.
Not a single product page had the brand field filled in. Magento had a manufacturer attribute but the JSON-LD template read nothing from it. That's a twenty-minute checkbox in the admin, and it had been neglected across all five thousand products.
GTIN, EAN and MPN were completely missing. Across all 13,600 PDPs. For a shop that resells products from known brands, this is the difference between being included or excluded from Google's Shopping knowledge panel. The EAN attribute was sitting right there in the database, just never passed through to the structured data.
96 percent of meta titles were in ALL CAPS. Every page. In four languages. Someone had once run an import script with strtoupper() over the product names, and it was never reversed. From Google's perspective every title was shouting, which in 2026 earns a soft ranking penalty but is primarily a click-through rate problem. People don't click on BRAND PRODUCTLINE MODELCODE DESCRIPTION ACCESSORY.
The BreadcrumbList JSON-LD was empty for crawlers. The visible breadcrumb on the page only worked client-side, but the JSON-LD module tried to read the same catalog session before Magento had populated it. A race condition between two modules where the breadcrumb schema output ended up on the losing side. Crawlers saw no hierarchy.
This isn't a list of obscure things. These are the foundations Google bases product snippets on.
How I pulled this together in one place
For an audit like this I don't use a tool. Tools don't let me search the right way. Concrete workflow:
- Download the sitemap and pull the first 48 PDPs with
curl --silent. Not the homepage of each category, but the actual product pages. That's where the money is and where 95 percent of SEO problems hide. - Grep out the JSON-LD with a short regex, save to separate files, and run through schema.org Validator. How many valid, how many not, and if they're not valid: which field combination is structurally missing?
- Compare headers, hreflang and canonical between the four languages. Not via a crawl tool but manually on ten pages. A mismatch in one
langattribute makes three of the four hreflang tags invalid in Google's eyes. - Open Search Console and see how many rich results were valid. That's your final score. On this shop: zero. Compare that with your competitors and it gets uncomfortable.
The whole process doesn't take an afternoon, and everything I find I back up with a direct URL and validator output. An audit without verifiable numbers is a gut feeling, and your client can't do anything with that.
What I did next
No rebuild. No "let's do Magento 2.4.7 with a PWA frontend and everything will be different". That type of project fails because the client can't afford to have the shop down while a new platform gets built.
Concretely, ranked by impact per working hour:
- Rewrote the product JSON-LD template. The raw
\r\nbug was fixable by replacing the existing string concatenation with onejson_encode()over a PHP array. That guarantees valid output, even with messy source data. Once deployed: 100 percent valid, in all four languages. 654 valid rich results within three Google crawls. - Mapped the brand and GTIN attribute. In Magento's website scope config:
brandmaps tomanufacturer,gtinmaps toean. Ten minutes of work, instantly visible in Search Console after reindexing. - ALL-CAPS titles to Title Case via a hybrid approach. Not a dumb
ucfirst()over everything, because you lose model numbers and brand codes (R1,TST,FM10). I used two Sonnet agents to classify each word in our 16,000 titles as KEEP, LOWER or TITLE, followed by a deterministic PHP function that applied the transformation with a brand dictionary and minor words per language. Hard guardrail:lower(before) == lower(after)per row. That guarantees nothing in the content was changed, only the casing. Provable to the client. - BreadcrumbList schema server-side. A custom ViewModel that builds
Home > [deepest non-brand category] > Productfrom the catalog tree without depending on the body session. You don't fix a race condition by building in waiting, but by removing the dependency.
For every fix I had a live diff. The same 48 PDPs before and after, same validators, same Search Console views. No "trust me bro": if the validator gave an error before the fix and turned green after, I can show it.
What I learned during the work
A few things I'll repeat on request for the next Magento audit:
- Production mode serves minified view_preprocessed copies. A
cache:flushdoesn't touch those. You need to runsetup:static-content:deployand purge the Varnish cache, otherwise you'll just see your old template back. This costs you four deploys before you figure out why your fix isn't showing up. Always verify backend-direct via port 8080. - Module layout applies to every store view. If you add something in
app/code/Vendor/Module/view/frontend/layout/, it hits the seventeen shops you're not targeting too. A website scope guard in the ViewModel isn't a luxury, it's mandatory. - Search Console's "not indexed" count matters. On this shop: 366,000 not-indexed URLs versus 14,000 indexed. A ratio of 25 to 1. These are often facet URL explosions that eat crawl budget and add no value. Set them to
noindexand exclude them from the sitemap.
When you need an audit like this
Often I hear "we already do SEO through a specialist". Then ask this: show me twenty product pages where your structured data is valid in the Rich Results Test. If that can't be on the table within a day, there's more broken than you think.
An SEO audit isn't a luxury product. It's a fact-finding round that shows you where you stand versus your competitors in search results. My price is a few hundred euros for a shop with several thousand products, and you get a prioritised list ranked by impact per working hour. No "we could add ten more things to that". No retainer-as-a-trojan-horse.
Want to talk directly?
Not sure whether your shop is technically ready for Google's product knowledge panel, or do you want a second opinion on an ongoing SEO project? Send me a message. I'll take a look within one working day.
Ready to get started?
Get in touch for a no-obligation conversation about the possibilities.