SEO & analytics audit rules
Audit rules covering technical SEO, meta tags, structured data, and tracking reliability in a Front-Commerce project.
An e-commerce storefront lives or dies by its organic traffic and by the reliability of its conversion data. These rules check the technical SEO foundations (crawlability, canonical URLs, structured data) and the analytics setup, with emphasis on failure modes observed in real Front-Commerce projects: missing Open Graph tags, sitemaps left on the legacy backend, and homegrown tracking that bypasses the Front-Commerce analytics module.
AUDIT-SEO-01 — Serve environment-appropriate robots.txt
Severity: critical — Detection: runtime
Rule: The production robots.txt does not disallow the whole site, and
non-production environments (staging, preprod) do disallow all crawlers or are
protected by HTTP authentication.
Why: A global Disallow: / shipped to production deindexes the entire
catalog — a direct, major revenue loss that can take weeks to recover from. The
inverse mistake (an open staging environment) creates duplicate content that
competes with production pages.
How to check: Fetch the file on every deployed environment:
curl -s https://www.example.com/robots.txt
curl -s https://staging.example.com/robots.txt
A violation is Disallow: / (or an empty/404 response combined with an open
staging site) on production, or a staging environment that neither disallows all
user agents nor sits behind authentication. Also verify the robots.txt
references the sitemap URL (Sitemap: line) and that this URL responds (see
AUDIT-SEO-02). Statically, locate how the file is produced —
grep -rn "robots" app/ extensions/ public/ — and confirm the content is driven
by the environment rather than hardcoded.
AUDIT-SEO-02 — Serve the sitemap from the storefront or proxy it cleanly
Severity: important — Detection: runtime
Rule: https://<shop>/sitemap.xml responds with 200 and XML content listing
storefront URLs; if the sitemap is generated elsewhere (for example by Magento),
the storefront URL proxies it or redirects to it with a single 301.
Why: Crawlers discover deep catalog pages through the sitemap. A real audit found the sitemap still served only by the Magento backend on its own domain, with no redirection from the storefront: search engines crawling the declared location got a 404, and the sitemap URLs pointed at the wrong domain.
How to check:
curl -sI https://www.example.com/sitemap.xml
curl -s https://www.example.com/sitemap.xml | head -20
A violation is a 404, a redirect chain (more than one hop), or <loc> entries
pointing at a different host than the storefront. Statically, verify the project
uses the Front-Commerce sitemap service: look for getSitemapEntries or
sitemapFetcher usage in extensions
(grep -rn "getSitemapEntries\|sitemapFetcher" app/ extensions/) and confirm
that custom dynamic routes (CMS pages, landing pages) register a fetcher so they
appear in the sitemap.
AUDIT-SEO-03 — Keep canonical URLs and robots directives consistent
Severity: important — Detection: runtime
Rule: Every indexable page declares exactly one canonical URL pointing at
its preferred variant, and no indexable page carries a noindex directive (via
meta tag or x-robots-tag header).
Why: Product pages are typically reachable through several paths (category
path, search, direct URL) and with query parameters (filters, pagination,
tracking). Without a canonical, search engines split ranking signals across
duplicates. A stray x-robots-tag: noindex header — often a leftover from a
staging configuration — silently deindexes pages while the HTML looks correct.
How to check: For one URL per page type (home, category, product, CMS):
curl -sI https://www.example.com/some-product.html | grep -i "x-robots-tag"
curl -s https://www.example.com/some-product.html | grep -io '<link rel="canonical"[^>]*>'
A violation is a missing canonical on an indexable page, a canonical pointing at
a different page than the one served, contradictory signals (canonical +
noindex on the same page), or an x-robots-tag header on production pages
that should be indexed. Also fetch a filtered category URL
(?color=blue&page=2) and verify its canonical points at the unfiltered page or
that it is marked noindex, per the project's SEO strategy.
AUDIT-SEO-04 — Enforce one URL per resource with single-hop 301 redirects
Severity: important — Detection: runtime
Rule: Trailing slash handling is consistent (one variant serves 200, the other permanently redirects to it), legacy URLs redirect with a 301, and no redirect requires more than one hop.
Why: When both /category and /category/ serve 200, every page exists
twice for crawlers. Redirect chains (http → https → non-slash → final) waste
crawl budget and leak PageRank at each hop; 302 responses on permanent moves
prevent signal transfer entirely.
How to check:
curl -sIL -o /dev/null -w "%{http_code} %{url_effective}\n" https://www.example.com/some-category/
curl -sIL -o /dev/null -w "redirects: %{num_redirects}\n" http://example.com/some-category/
Run the pair for a category, a product, and a CMS page, testing both slash
variants. A violation is: both variants returning 200, any 302 on a permanent
move, or num_redirects greater than 1 from any commonly linked entry URL. If
the project migrated from another platform, sample a handful of old URLs from
the redirect mapping and confirm they return a single 301 to the new location.
Statically, review custom redirects registered in extensions
(grep -rn "redirect" extensions/ app/routes/ on loader code).
AUDIT-SEO-05 — Provide meta title, description, and Open Graph tags per page type
Severity: important — Detection: runtime
Rule: Every page type (home, category, product, CMS) renders a unique
<title>, a meta description, and Open Graph tags (og:title, og:type,
og:image, og:url) reflecting that page's content.
Why: Title and description drive click-through from search results. Open Graph tags control how shared links render on social networks and messaging apps; a real audit found a storefront with no OG tags at all, so every shared product link displayed as a bare URL with no image.
How to check: With the application running:
for url in "/" "/some-category" "/some-product.html" "/some-cms-page"; do
curl -s "https://www.example.com$url" | grep -io '<title>[^<]*\|<meta[^>]*\(description\|og:\)[^>]*>'
done
A violation is a missing or duplicated <title> across page types, a missing
description, or absent og: tags — product pages must at minimum carry
og:title, og:image (the product image), and og:url. Statically, verify
each custom route exports a meta function
(grep -rln "MetaFunction\|export const meta" app/routes/) and that overridden
page components did not drop the base theme's meta logic.
AUDIT-SEO-06 — Expose structured data as JSON-LD
Severity: important — Detection: runtime
Rule: Product pages emit valid Product JSON-LD (name, image, price,
availability), all pages with a breadcrumb emit BreadcrumbList, and the site
emits an Organization (or WebSite) block.
Why: Structured data powers rich results — price, availability, and review stars directly in search listings — which measurably raise click-through on product pages. Invalid or missing JSON-LD forfeits this space to competitors.
How to check:
curl -s https://www.example.com/some-product.html | grep -o '<script type="application/ld+json">[^<]*' | head -5
Parse each block and validate it with the
Rich Results Test. A violation is
a product page without a Product block, a Product block missing
offers.price or offers.availability, or JSON that fails to parse.
Statically, locate where structured data is produced
(grep -rn "ld+json\|application/ld" app/ extensions/) and check that
overridden product page components still render it.
AUDIT-SEO-07 — Render internal links with the Front-Commerce Link component
Severity: important — Detection: static
Rule: All internal navigation uses the Front-Commerce Link (or
TrackingLink) component; HTML content injected from a CMS is rendered through
the Wysiwyg pipeline so its <a> elements become client-side navigations.
Why: A raw <a href> to an internal URL triggers a full page reload: the
SPA state, the preloaded data, and the navigation performance are lost, and
analytics page-view tracking may double-fire. This is a real, recurring finding
with CMS-driven content: HTML from Strapi rendered with
dangerouslySetInnerHTML contained internal <a> links, and every click on
them reloaded the whole application.
How to check:
grep -rn "<a href" app/ extensions/ --include="*.tsx" --include="*.jsx" | grep -v "http\|mailto:\|tel:\|target="
grep -rn "dangerouslySetInnerHTML" app/ extensions/ --include="*.tsx"
A violation is a raw <a> pointing at an internal path, or CMS HTML injected
with dangerouslySetInnerHTML instead of the Front-Commerce Wysiwyg component
(whose transforms rewrite embedded links to client-side navigations). Confirm at
runtime by clicking a link inside CMS-managed content with the network panel
open: a full document reload on an internal link is a violation.
AUDIT-SEO-08 — Track and meet Core Web Vitals
Severity: important — Detection: runtime
Rule: LCP, CLS, and INP are within the "good" thresholds (LCP under 2.5 s, CLS under 0.1, INP under 200 ms) on the home, category, and product pages, and the team monitors them with field data.
Why: Core Web Vitals are a search ranking factor and correlate directly with conversion. A storefront that passes only in the lab regresses unnoticed without field monitoring.
How to check:
npx lighthouse https://www.example.com/some-product.html --only-categories=performance --output=json --quiet
Check field data through the PageSpeed Insights CrUX panel when the site has enough traffic. A violation is any of the three metrics outside "good" on a key page type, or the absence of any field monitoring (CrUX, RUM plugin, or equivalent). For remediation levers specific to Front-Commerce — priority images, font loading, one query per route — see Improve your Core Web Vitals.
AUDIT-SEO-09 — Implement Consent Mode V2 when using Google Analytics
Severity: critical — Detection: static
Rule: If the project uses Google Analytics or Google Tag Manager, the
consent configuration declares the four Consent Mode V2 signals (ad_storage,
ad_user_data, ad_personalization, analytics_storage) and the plugins are
gated behind needConsent: true.
Why: Since March 2024, Google requires Consent Mode V2 for measurement in the EEA; without it, conversion data degrades and the site processes personal data without a valid legal basis — a GDPR exposure, not just a data-quality problem.
How to check:
grep -rn "google-analytics\|google-tag-manager\|gtag\|gtm" app/config/analytics.ts app/ extensions/
grep -rn "ad_storage\|ad_user_data\|ad_personalization\|analytics_storage" app/config/
grep -rn "needConsent" app/config/analytics.ts
If Google plugins are present, a violation is: missing consentOptions with the
four V2 signals in app/config/cookiesServices.js (or .ts), a Google plugin
with needConsent: false, or a custom plugin lacking an updateConsent method
to propagate granular consent changes. Confirm at runtime that no Google request
fires before consent is given (network panel, fresh session).
AUDIT-SEO-10 — Enable server-side tracking with a running worker for order events
Severity: important — Detection: runtime
Rule: Server-side events are configured (app/config/serverEvents.ts with a
Redis config and at least one integration), the front-commerce worker process
runs in production, and the OrderPlaced event is dispatched on order
confirmation.
Why: Client-side order tracking loses 10–30% of conversions to ad blockers,
consent refusals, and users closing the confirmation page early. The server-side
OrderPlaced event is the only reliable source for revenue data — but it
silently does nothing if the worker process is not deployed alongside the web
process.
How to check: Statically, confirm the configuration exists:
cat app/config/serverEvents.ts
grep -rn "front-commerce worker" package.json Procfile* docker-compose* .platform* 2>/dev/null
A violation is a missing integration for the analytics destination, or no
deployment artifact starting the worker (front-commerce worker absent from
process definitions). At runtime, place a test order with the
ConsoleIntegration (or worker debug integration) enabled and verify the
OrderPlaced event is logged by the worker process. An event configured but
never consumed (worker not running, Redis unreachable) is a violation.
AUDIT-SEO-11 — Route all tracking through the Front-Commerce analytics module
Severity: important — Detection: static
Rule: All tracking services are registered as plugins in
app/config/analytics.ts; no tracking script is loaded through a hand-rolled
<script> tag, a custom hook, or a parallel tag manager setup outside the
analytics module.
Why: The Front-Commerce analytics module provides consent gating, e-commerce event mapping (product views, add-to-cart, checkout steps), and page-view tracking on client-side navigation. A real audit found a homegrown GTM implementation pasted into the document head: none of the Front-Commerce tracking features worked — no e-commerce events, no consent integration, and page views missed on every SPA navigation.
How to check:
cat app/config/analytics.ts
grep -rn "googletagmanager\|gtag(\|fbq(\|dataLayer" app/ extensions/ --include="*.tsx" --include="*.ts" | grep -v "config/analytics"
grep -rn "createElement(.script.)\|<script" app/root.tsx app/entry.client.tsx 2>/dev/null
A violation is any tracking snippet (GTM container, gtag bootstrap, Meta pixel)
injected outside the analytics plugin list, or an analytics.enable set to
false while tracking works "anyway" through a parallel implementation. The fix
is to move each service to a plugin with needConsent set appropriately, so
consent, e-commerce events, and SPA page views work uniformly.