Every BigCommerce fix we catalog
SEOLZ catalogs 182 fixes for BigCommerce across 6 areas — SEO, answer-engine readiness, accessibility, security and site-health. Each lists the exact steps for BigCommerce, with a link to the official docs.
SEO · 52 fixes
Catalog coverageModerate effort
Audit your XML sitemap and internal linking so that every product and category page is discoverable and crawlable by Google — not hidden behind JavaScript, pagination, or missing links.
On BigCommerce
- BigCommerce auto-generates a sitemap at yourstore.com/xmlsitemap.php. Submit this URL in Google Search Console › Indexing › Sitemaps.
- Admin › Storefront › Search Engine Optimization: confirm 'Enable XML Sitemap' is checked.
- Admin › Products › View: export your product list (Export button) and compare the count to what Google Search Console reports as indexed.
- Admin › Storefront › Navigation: ensure every category is linked in the navigation. Uncategorised products are still in the sitemap but may receive fewer internal links — assign them to categories.
- Check Admin › Products › Categories for any category set to 'Visible: No' — hidden categories and their products are not indexed.
- Use the URL Inspection tool in Google Search Console to test individual product URLs and confirm they are crawlable.
<!-- CORRECT: Standard crawlable link -->
<a href="/products/blue-running-shoes">Blue Running Shoes</a>
<!-- WRONG: JavaScript-only — Googlebot cannot follow this -->
<span onclick="navigate('/products/blue-running-shoes')">Blue Running Shoes</span>Standard crawlable product link — use plain <a href> tags, never JavaScript-only click handlers, for navigation links that Google must follow.
Cwv clsModerate effort
Eliminate unexpected layout shifts by reserving space for every image, video, embed, and dynamically injected element so nothing jumps when the page loads.
On BigCommerce
- Images: In Storefront → My Themes → Edit Theme Files, open templates/components/products/product-view.html (and card.html for listing pages). Add width and height attributes to every <img> tag. BigCommerce's Stencil framework provides {{getImageSrcset}} helpers; use {{image width=800 height=800}} to output sized images with explicit dimensions.
- Theme CSS: In assets/scss/settings/foundation/images/_settings.scss, ensure img { max-width: 100%; height: auto; } is present so explicit width/height attributes work correctly with responsive layouts.
- Banner / promo: In Marketing → Banners, avoid rotating hero banners injected via JavaScript without a reserved container. In your theme's homepage template (templates/pages/home.html), wrap the banner region in a container with a fixed aspect-ratio or min-height.
- Fonts: In assets/scss/settings/global/color-and-type/_settings.scss, locate @font-face declarations and add font-display: optional;.
- Apps: For review or chat apps installed from the BigCommerce App Marketplace, wrap their embed scripts in a sized container div in the relevant template file.
- Verify: Check PageSpeed Insights on your storefront URLs; CLS should be < 0.1 on both mobile and desktop.
<!-- CORRECT: explicit width and height prevent layout shift -->
<img
src="/images/product-red-sneaker.jpg"
alt="Red canvas sneaker, side view"
width="800"
height="800"
loading="lazy"
>Always declare width and height on every img element. The browser uses these to reserve space before the image file downloads.
Cwv inpLarger project
Reduce Interaction to Next Paint (INP) to under 200 ms by breaking up long JavaScript tasks, deferring non-critical third-party scripts, and lightening event handlers so the page feels fast and responsive after every tap or click.
On BigCommerce
- Go to Storefront → Script Manager. Review every installed script. For non-critical scripts (chat, affiliate pixels, review widgets), change their 'Load Method' to 'Defer' or move their 'Placement' to 'Footer'.
- In Storefront → My Themes → Advanced → Edit Theme Files, open templates/layout/base.html and find any hard-coded `<script>` tags. Add `defer` or `async` attributes to non-critical ones.
- Remove or disable BigCommerce apps that inject frontend JavaScript but are no longer actively used (Apps → My Apps).
- For custom JavaScript in assets/js/, refactor event handlers on cart, search, and navigation interactions to yield back to the browser using `setTimeout` or `scheduler.yield()` between heavy steps.
- Use BigCommerce's built-in Lighthouse integration (Storefront → Optimize) or PageSpeed Insights to measure INP before and after changes.
Cwv lcpModerate effort
Reduce Largest Contentful Paint (LCP) to under 2.5 seconds by serving the hero image in a next-gen format (WebP/AVIF), preloading it, and eliminating render-blocking resources.
On BigCommerce
- IDENTIFY LCP IMAGE: Run PageSpeed Insights on your storefront. The LCP is usually the hero carousel image configured under Storefront › Home Page Carousel or a theme banner.
- CONVERT TO WEBP: BigCommerce's Akamai Image Manager automatically serves WebP/AVIF to supported browsers when you upload standard images — no action needed if you are on a current plan. Confirm by inspecting the hero image URL for a format parameter.
- UPLOAD OPTIMISED SOURCE: Even with auto-conversion, upload the highest-quality but appropriately-sized source JPEG/PNG (max 1920px wide) via Storefront › Image Manager so the CDN has a good original to compress.
- PRELOAD: Go to Storefront › My Themes › Edit Theme Files (or use Stencil CLI). Open templates/layout/base.html. In <head>, add: <link rel='preload' as='image' href='{hero image CDN URL}' fetchpriority='high'>. For dynamic images use the Handlebars variable that outputs your carousel image.
- DEFER JS: In base.html, add 'defer' to non-essential third-party <script> tags. Move analytics and chat widgets to the bottom of <body> or wrap in a setTimeout.
- NO LAZY-LOAD: Find the carousel/hero img tag in templates/components/ and ensure it has loading='eager' fetchpriority='high'.
- VERIFY: Re-run PageSpeed Insights; monitor Core Web Vitals in Google Search Console.
<!-- Step 1: Preload the LCP hero image -->
<link
rel="preload"
as="image"
href="/images/hero-banner.webp"
imagesrcset="/images/hero-banner-400.webp 400w,
/images/hero-banner-800.webp 800w,
/images/hero-banner-1500.webp 1500w"
imagesizes="100vw"
fetchpriority="high"
>
<!-- Step 2: Hero <img> tag — eager, high priority, no lazy-load -->
<img
src="/images/hero-banner-1500.webp"
srcset="/images/hero-banner-400.webp 400w,
/images/hero-banner-800.webp 800w,
/images/hero-banner-1500.webp 1500w"
sizes="100vw"
alt="[Descriptive alt text for your hero image]"
width="1500"
height="600"
loading="eager"
fetchpriority="high"
>Add inside <head>, immediately after <meta charset>. Replace the href with your actual hero image CDN URL.
Duplicate meta descriptionModerate effort
Write a unique, page-specific meta description for every page on your store so Google can display a compelling, accurate snippet for each one in search results.
On BigCommerce
- For a product: go to Products → View, open the product, select the 'Other details' tab, find the 'Search Engine Optimization' panel, and enter a unique description in the 'Meta Description' field.
- For a category: go to Products → Product Categories, click 'Edit' on the category, scroll to the 'Search Engine Optimization' section, and fill in 'Meta Description'.
- For standard pages (e.g. About, FAQ): go to Storefront → Web Pages, open the page, scroll to the 'Search Engine Optimization' section, and update the Meta Description field.
- For the homepage: go to Storefront → Home Page Carousel or Content → Home Page, then edit the default meta description via Store Setup → Store Profile → 'Default meta description' field.
- For bulk product updates: export your product catalogue (Products → Export) to CSV, populate the 'meta_description' column, and re-import via Products → Import.
- After saving, verify with a browser or SEO tool that the new description appears in the page source, then request re-indexing in Google Search Console.
<head>
<meta charset="UTF-8">
<meta name="description" content="Shop women's running shoes at Acme Store — lightweight, cushioned designs for road and trail. Free shipping on orders over $50.">
<title>Women's Running Shoes | Acme Store</title>
</head>Place inside the <head> element of every page. Replace the content value with a unique 120–160 character description for that specific page.
Duplicate titleModerate effort
Give every page a unique, descriptive title tag that accurately reflects that page's specific content.
On BigCommerce
- For individual products: Catalog → Products → Edit a product → SEO & Sharing tab → edit 'Page Title'.
- For individual categories: Catalog → Categories → Edit → SEO & Sharing tab → 'Page Title'.
- For store-wide template defaults: Storefront → Script Manager is not the right place — instead open Storefront → My Themes → Edit Theme Files (Stencil) → find templates/layout/base.html and verify the <title> block uses {{head.title}}, which BigCommerce populates dynamically from the page's configured title.
- Use the BigCommerce V2/V3 REST API or a third-party SEO app (e.g. Yoast SEO for BigCommerce) to bulk-update page_title fields across large catalogs.
<head>
<title>Merino Wool Running Socks – Free UK Shipping | BrandName</title>
</head>Place inside <head>. Make the title unique per page — include the specific item name and brand.
Faceted url indexableModerate effort
Point the rel=canonical on every faceted/filter URL to its clean parent category URL (or add noindex), so Google treats filtered pages as a single authoritative page instead of thousands of duplicates.
On BigCommerce
- BigCommerce generates faceted filter URLs as query strings appended to category URLs (e.g., /womens-pants/?color=Navy&size=S). By default these may be self-canonical.
- Go to Storefront → Script Manager (or Edit Theme Files if on a Stencil theme) and open templates/layout/base.html (Stencil).
- Find the canonical tag output — typically <link rel='canonical' href='{{urls.canonical}}'>. The {{urls.canonical}} variable in Stencil usually strips known filter params, but verify by viewing source on a filtered category URL.
- If filter query strings appear in the canonical, you need to override it. Add custom logic in your Stencil theme's JavaScript or use a Page Builder script to detect filter params and rewrite the canonical to the clean category URL.
- Alternatively, use BigCommerce's built-in 'Faceted Search' settings: go to Storefront → Faceted Search and review which facets are enabled. Reducing enabled facets reduces the number of filterable URL combinations Google can discover.
- For a code-free approach, use a third-party SEO app from the BigCommerce App Marketplace (e.g., SEO King or similar) that offers canonical management for filter pages.
- Verify in Google Search Console URL Inspection.
<head>
<!-- Canonical points to the CLEAN category URL, not the filtered variant -->
<link rel="canonical" href="https://www.example.com/womens-pants">
</head>Place this in the <head> of every filtered/faceted page. The href must be the clean parent category URL — never the filtered URL itself.
Images missing altModerate effort
Add descriptive alt text to every product and content image so search engines and screen readers can understand what the image shows.
On BigCommerce
- Product images: Admin → Catalog → Products → [select product] → Images & Videos tab → hover over the image thumbnail and click the pencil (Edit) icon → fill in the 'Alt Text' field → Save.
- Banners and other content images: Admin → Storefront → Image Manager — locate the image → click the edit icon → update the alt text field.
- Page Builder widgets: Admin → Storefront → My Themes → Customize (Page Builder) → click an Image widget on the canvas → update the Alt Text field in the right sidebar → Publish.
<!-- BEFORE (missing alt — bad) -->
<img src="/images/red-leather-bag.jpg">
<!-- AFTER (descriptive alt — correct) -->
<img src="/images/red-leather-bag.jpg" alt="Red leather crossbody bag with gold buckle clasp">
<!-- Decorative image (intentionally empty alt — correct) -->
<img src="/images/divider-line.png" alt="">Place this wherever an <img> tag appears in your HTML. Replace the placeholder text with your real description.
Images missing alt bulkModerate effort
Add descriptive alt text to every product and content image at the template level so search engines and screen readers can understand all images on the page.
On BigCommerce
- Go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil-based).
- Open `templates/components/products/product-view.html` for product detail pages and `templates/components/products/card.html` for category/search grids.
- Locate `<img>` tags and update them to include `alt="{{product.main_image.alt}}"` with a Handlebars fallback: `alt="{{#if product.main_image.alt}}{{product.main_image.alt}}{{else}}{{product.title}}{{/if}}"`.
- To set alt text on individual images: go to Products → Edit a product → scroll to the Images & Videos section → click each image and fill in the 'Alt Text / Title Text' field.
- Commit and apply changes in the theme editor, then preview a product page to confirm.
{{!-- Product card image with alt text fallback (Stencil / Handlebars) --}}
<img
class="card-image"
src="{{getImageSrcset product.main_image use_default_sizes=true}}"
alt="{{#if product.main_image.alt}}{{product.main_image.alt}}{{else}}{{product.title}}{{/if}}"
title="{{product.title}}"
loading="lazy"
width="300"
height="300">Place in templates/components/products/card.html (Stencil theme). Uses Handlebars with a fallback.
Low performance scoreLarger project
Improve your Lighthouse/PageSpeed performance score by reducing page weight, eliminating render-blocking resources, optimising images, and addressing Core Web Vitals so Google ranks your store higher in search results.
On BigCommerce
- Use Cornerstone theme (BigCommerce's official reference theme): Storefront → Themes → select Cornerstone — it ships with lazy-loaded images and CDN-optimised assets.
- BigCommerce automatically serves all store assets via Akamai CDN and delivers images via its built-in Image Manager CDN — ensure you are not hot-linking external image URLs in product descriptions.
- Optimise product images before uploading: target ≤ 200 KB per image at actual display size; BigCommerce's Image Manager will serve them at the right dimensions.
- Reduce third-party script load: Storefront → Script Manager → review every script; delete or disable any that are unused. Set non-critical scripts to load in the Footer and mark them as 'Deferred'.
- Enable Cloudflare (free or paid) in front of your BigCommerce store via CNAME setup for additional edge caching and Brotli compression: Settings → Domains → follow the BigCommerce Cloudflare setup guide.
- Check App Marketplace for performance-focused image apps (e.g., Amasty Image Optimizer equivalent on BC App Store) if you have a large product catalogue.
- Re-test with PageSpeed Insights; monitor Core Web Vitals in Google Search Console → Experience → Core Web Vitals.
<!-- In <head>: preconnect to critical third-party origins to reduce connection latency -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Preload your Largest Contentful Paint image (hero/banner) so it loads earlier -->
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high">
<!-- Hero image: eager load, explicit dimensions to prevent CLS -->
<img
src="/images/hero.webp"
alt="Descriptive alt text for your hero image"
width="1200"
height="600"
fetchpriority="high"
decoding="async"
>
<!-- All other images: lazy load, explicit dimensions to prevent CLS -->
<img
src="/images/product-shot.webp"
alt="Descriptive product alt text"
width="800"
height="800"
loading="lazy"
decoding="async"
>
<!-- Defer non-critical third-party scripts (analytics, chat, pixels) -->
<script src="https://example-analytics.com/tracker.js" defer></script>
<!-- Load non-critical CSS asynchronously to unblock render -->
<link rel="preload" href="/css/non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/non-critical.css"></noscript>Paste these patterns into your <head> and image markup to address the most common Lighthouse failures.
Meta description too longQuick win
Shorten your meta description to 150–160 characters so Google displays it in full instead of cutting it off with "…" in search results.
On BigCommerce
- For product pages: go to Products → View → click the product → select the 'Other details' tab → find the 'Search Engine Optimization' section → edit the 'Meta Description' field.
- For category pages: go to Products → Product Categories → click the category → find the 'Search Engine Optimization' section.
- For content pages: go to Storefront → Web Pages → click the page → 'SEO & Sharing' tab → 'Meta Description'.
- Keep the description under 160 characters and click Save.
<meta name="description" content="Award-winning Bang & Olufsen headphones, speakers and TVs. Visit our Malaysia showroom at The Gardens Mall, Level 2. Free shipping on orders over RM500.">Place this inside the <head> element of every page. Replace the content value with your page-specific description (max 160 characters).
Meta description too shortModerate effort
Expand your meta description to 120–160 characters so Google displays a compelling, complete snippet in search results that drives more clicks to your store.
On BigCommerce
- For a product: Admin → Catalog → Products → select the product → click the 'Other details' tab → find the 'Search keywords / Meta description' field → enter your 120–160 character description → Save.
- For a category: Admin → Catalog → Product Categories → select the category → 'Other details' tab → Meta Description field → Save.
- For the homepage or static pages: Admin → Storefront → Web Pages → select the page → 'Advanced' tab → Meta Description field → Save.
- To update many products at once, use the bulk import: Admin → Catalog → Import Products, add a 'meta_description' column to your CSV.
<meta name="description" content="Shop the official Nike national team jerseys — advanced Dri-FIT heat tech meets bold heritage design. Free shipping on orders over $75. Explore the full collection now.">Place this inside the <head> element of your HTML page. Replace the content value with your 120–160 character description.
Missing canonicalModerate effort
Add a self-referencing canonical tag to every page so Google knows which URL is the definitive version of that content.
On BigCommerce
- BigCommerce outputs canonical tags automatically on product and category pages via its Stencil theme framework — verify your theme is up to date.
- In your BigCommerce Admin, go to Storefront → Themes → click 'Advanced' → Edit Theme Files (Stencil CLI or in-browser editor).
- Open `templates/layout/base.html` and confirm this line is present inside `<head>`: `{{#partial 'head'}}` area should include `<link rel='canonical' href='{{canonicalUrl}}'>`. If missing, add it.
- For custom pages or pages using a non-standard template, open the relevant template under `templates/pages/` and ensure they extend the base layout that includes the canonical.
- Save changes and use the Preview option to verify via page source.
<link rel="canonical" href="https://www.yourstore.com/your-page/" />Paste this inside the <head> element of every page. Replace the href value with the full, absolute preferred URL of that specific page.
Missing h1Quick win
Add a single, descriptive H1 tag to every page that currently lacks one, clearly stating the page's main topic.
On BigCommerce
- For product pages: Catalog → Products → open the product → the 'Product Name' field is output as the H1 by default in Cornerstone and most BigCommerce themes. Make sure it is filled in.
- For category pages: Catalog → Product Categories → edit the category → the 'Category Name' renders as the H1.
- For custom pages (e.g. About, Landing): Storefront → Web Pages → open the page → add an H1 heading at the top of the page content using the WYSIWYG editor (select text, click the Heading 1 style from the Format dropdown).
- If the theme template does not output the product/category name as an H1, go to Storefront → My Themes → click Advanced → Edit Theme Files → open templates/pages/product.html (or category.html) and wrap the name output with <h1> tags.
- Save and preview; verify with View Page Source.
<h1 class="productView-title">{{product.title}}</h1>In templates/pages/product.html (Stencil theme), ensure the product name is in an H1.
Missing meta descriptionModerate effort
Write and add a unique meta description (120–160 characters) to every page that is missing one, so Google can display an accurate, compelling snippet in search results.
On BigCommerce
- For a product: Admin → Catalog → Products → click the product → 'SEO' tab → fill in the 'Meta Description' field.
- For a category page: Admin → Catalog → Product Categories → click the category → 'SEO' tab → fill in 'Meta Description'.
- For the homepage: Admin → Storefront → My Themes → click 'Customize' → look for a 'SEO' panel, OR go to Admin → Store Setup → Store Profile → 'Meta Keywords / Description' field (theme-dependent).
- For content pages: Admin → Storefront → Web Pages → click the page → 'SEO & Sharing' section → 'Meta Description' field.
- For bulk updates, export products via Admin → Catalog → Import/Export → Products, fill in the 'meta_description' column in the CSV, then re-import.
<head>
<meta charset="UTF-8">
<meta name="description" content="Shop our full range of handmade leather wallets. Free shipping on orders over $50. Slim, durable & personalised — order yours today.">
<title>Handmade Leather Wallets | YourStoreName</title>
</head>Place this tag inside the <head> element of every HTML page. Keep the content between 120–160 characters.
Missing og descriptionModerate effort
Add an og:description meta tag to every page so that social media platforms display a compelling, accurate preview when your pages are shared.
On BigCommerce
- Go to Storefront → Script Manager and create a new script scoped to 'All Pages' and placed in the <head>.
- Alternatively, edit your Stencil theme locally: open templates/layout/base.html (or product.html for product pages) and add <meta property="og:description" content="{{model.description | strip_html | truncate: 160}}"> inside <head>.
- For the native Open Graph support built into Stencil, open config.json in your theme and verify 'open_graph' features are enabled; BigCommerce auto-generates some OG tags, but og:description may need explicit template output.
- Upload the updated theme via the BigCommerce Theme Editor or Stencil CLI (stencil push), then validate with Facebook Sharing Debugger.
<head>
<!-- Open Graph / Social Sharing -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.example.com/page-url/" />
<meta property="og:title" content="Page Title – Brand Name" />
<meta property="og:description" content="A concise, compelling summary of this page in 100–160 characters that encourages clicks." />
<meta property="og:image" content="https://www.example.com/images/social-preview.jpg" />
</head>Place all Open Graph tags inside the <head> element of every page.
Missing og imageModerate effort
Add an og:image meta tag to every page so that social media platforms and messaging apps display a rich, branded image preview whenever someone shares your store's link.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click 'Customize' on your active theme.
- Most Cornerstone-based themes output og:image automatically using the product's primary image. Confirm this by viewing your page source and searching for 'og:image'.
- To set a homepage og:image, go to Storefront → Home Page Carousel or use the Theme Editor's 'Open Graph' fields if your theme exposes them.
- For granular control over og:image on every page type, go to Storefront → Script Manager → Add a script that injects og:image meta tags, or edit your theme's template files directly via Stencil CLI (storefront/templates/layout/base.html is the main layout).
- Alternatively, install an SEO app from the BigCommerce App Marketplace (search 'SEO' or 'Open Graph') that provides a UI for setting og:image per product and category.
- Validate using Facebook's Sharing Debugger after publishing.
Missing og titleQuick win
Add an og:title meta tag to every page so your store's title appears correctly when shared on social media platforms like Facebook, LinkedIn, and Pinterest.
On BigCommerce
- Go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' on your active theme.
- In the theme file editor, open templates/layout/base.html (or the equivalent head template for your theme).
- Locate the <head> section and search for any existing og:title tag. If absent, add: <meta property="og:title" content="{{this.head.title}}"> just before </head>.
- BigCommerce's Stencil framework exposes {{this.head.title}} as the current page title — this variable works across all page types (product, category, home, etc.).
- For per-page titles: in the admin go to Products → Edit a product → scroll to the 'SEO & sharing' section → fill in the 'Page title' field. BigCommerce uses this as the title for og:title when the template variable is used.
- Download/preview your theme changes and verify using Facebook Sharing Debugger.
{{!-- Inside <head> in templates/layout/base.html --}}
<meta property="og:title" content="{{this.head.title}}" />
<meta property="og:type" content="website" />
<meta property="og:url" content="{{urls.current}}" />
<meta property="og:site_name" content="{{settings.store_name}}" />Add inside the <head> block in templates/layout/base.html in your Stencil theme. The {{this.head.title}} variable resolves to the current page's title across all page types.
Missing titleQuick win
Add a unique, descriptive title tag (30–60 characters) to every page that is missing one.
On BigCommerce
- For a product: go to Products → View → select the product → click the 'SEO' tab → fill in the 'Page Title' field.
- For a category: go to Products → Product Categories → select the category → click the 'SEO' tab → fill in 'Page Title'.
- For a standard page (e.g. About Us): go to Storefront → Web Pages → select the page → fill in the 'Page Title' field in the SEO section.
- For the homepage: go to Storefront → Home Page → SEO → fill in the 'Page Title'.
- Click Save and verify by viewing the page source.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Slim Bifold Leather Wallet | BrandName</title>
</head>
<body>
<!-- page content -->
</body>
</html>Place this inside the <head> element of every HTML page. Keep the text between 30–60 characters.
Multiple h1Moderate effort
Remove all but one H1 tag from each page so every page has exactly one clear, descriptive primary heading.
On BigCommerce
- Go to Storefront → My Themes → click Customize on your active theme, or click Advanced → Edit Theme Files.
- In the file editor, open templates/pages/product.html for product pages, templates/pages/category.html for category pages, and templates/pages/home.html for the homepage.
- Search each file for 'h1'. The product name ({{product.name}}), category name, or page title should be the sole H1.
- Open templates/components/products/card.html — product card titles in grid listings should use a span, H3, or H4, not H1.
- Save changes, preview the storefront, and use browser DevTools to confirm one H1 per page type.
{{!-- templates/pages/product.html (Stencil) --}}
{{!-- Correct: product name as sole H1 --}}
<h1 class="productView-title">
<span data-product-title>{{product.title}}</span>
</h1>
<h2 class="productView-section-heading">Product Details</h2>
<div class="productView-description">
{{product.description}}
</div>
<h2 class="productView-section-heading">Related Products</h2>
{{!-- In templates/components/products/card.html --}}
{{!-- Product card titles should be h3 or a link inside a div, NOT h1 --}}
<h3 class="card-title">
<a href="{{url}}" class="card-title-link">{{name}}</a>
</h3>Place in templates/pages/product.html — Stencil theme. Ensure the product name is the only H1; product cards in templates/components/products/card.html should use h3 or a span.
Noindex detectedQuick win
Remove or replace the noindex directive on any page you want to appear in Google search results.
On BigCommerce
- Global search engine indexing: Go to BigCommerce Admin → Store Setup → Store Settings → Miscellaneous tab. Ensure 'Search Engine Indexing' is enabled (set to 'Yes, index this store').
- Per-page (Storefront Pages): Go to Storefront → Web Pages, click the page, then click 'SEO & Sharing'. Check the 'Meta Robots' field — change 'noindex' to 'index, follow' or clear the field.
- Per-product/category: BigCommerce does not expose a per-product robots field natively; a noindex on product pages usually comes from a theme template or a Script Manager snippet.
- Theme file check: Go to Storefront → My Themes → Edit Theme Files (or download the theme). Open templates/layout/base.html (or equivalent) and search for 'noindex'. Remove or correct the tag.
- After fixing, submit affected URLs in Google Search Console → URL Inspection → Request Indexing.
<meta name="robots" content="index,follow">Place inside <head>. This is the CORRECT tag that allows indexing and link-following.
Non self canonicalQuick win
Audit every page whose canonical tag points to a different URL, then either correct it to self-reference or confirm the cross-reference is intentional and correct.
On BigCommerce
- BigCommerce generates self-canonical tags automatically via its Stencil theme framework.
- If a non-self-canonical exists, it is almost certainly introduced by a custom Stencil theme edit. In your BigCommerce admin go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files'.
- In the theme editor, search all template files (.html files under 'templates/') for 'canonical'. The standard output is {{canonicalUrl}} — if you see a hardcoded URL or a modified value, restore it to: <link rel="canonical" href="{{canonicalUrl}}">.
- If you use a third-party SEO app from the BigCommerce App Marketplace (e.g., WordStream, Yoast for BigCommerce integrations), check that app's canonical override settings for the affected page type.
- Save and push theme changes, then preview the storefront page and view-source to verify the canonical matches the page URL.
<link rel="canonical" href="{{canonicalUrl}}">In a Stencil theme template file (e.g., templates/pages/product.html or category.html), inside the <head> block or passed to the head partial.
Og url mismatchModerate effort
Set a unique, page-specific og:url meta tag on every page that exactly matches that page's canonical URL.
On BigCommerce
- In BigCommerce Admin, go to Storefront → My Themes → click 'Edit Theme Files' (Advanced mode) on your active theme.
- Open 'templates/layout/base.html' (Stencil themes) and search for 'og:url'.
- Replace any hardcoded or incorrect value with the Stencil context variable: content='{{og.url}}' — BigCommerce's Stencil framework populates this automatically with the canonical URL when used correctly.
- If 'og.url' is absent from your template, add <meta property='og:url' content='{{og.url}}'> inside the <head> block.
- Save and apply the theme, then verify by viewing source on a product page, a category page, and the homepage.
- If you use a third-party SEO app from the BigCommerce App Marketplace (e.g. SEO Manager), check that app's Open Graph settings and disable duplicate og:url output from the theme to avoid conflicts.
<meta property="og:url" content="{{og.url}}" />
<link rel="canonical" href="{{og.url}}" />In templates/layout/base.html of your Stencil theme, inside the <head> block.
Page not foundModerate effort
Fix broken internal links pointing to pages that return a 404 error by either removing those links or setting up a 301 redirect from the missing URL to the correct replacement page.
On BigCommerce
- In the BigCommerce control panel, go to Server Settings → 301 Redirects.
- Click 'Create a Redirect'. Choose 'Manual' redirect type, enter the old broken URL path (e.g. /old-category/old-product) and the new destination URL. Save.
- To fix internal links in page content, go to Storefront → Web Pages, open each page, and use the WYSIWYG editor to update or remove the broken link.
- For links in navigation menus, go to Storefront → Navigation and edit the affected menu items.
- For links inside theme template files (.html / Handlebars), go to Storefront → My Themes → Advanced → Edit Theme Files and update the hard-coded URLs.
- Verify the old URL now redirects correctly by visiting it in a browser or using an HTTP status checker.
<!-- BEFORE: broken internal link -->
<a href="/old-products/discontinued-item">Shop Now</a>
<!-- AFTER: updated to correct URL -->
<a href="/products/replacement-item">Shop Now</a>Update an internal anchor link to point to the correct URL instead of the broken one.
Page speed warningModerate effort
Reduce your page load time to under 1.5 seconds by optimizing images, eliminating render-blocking resources, and enabling caching and compression.
On BigCommerce
- Stencil theme: In your BigCommerce admin go to Storefront > My Themes and ensure you are on a Stencil-based theme (not Blueprint) — Stencil themes are optimized for Core Web Vitals and support modern asset pipelines.
- Images: In the BigCommerce admin go to Products and re-upload product images at their correct display resolution. BigCommerce automatically serves images via Akamai CDN; use the ?imbypass=on URL parameter to verify CDN delivery is active.
- Script manager: Go to Storefront > Script Manager and remove any third-party scripts (chat widgets, social pixels) you no longer need. For remaining scripts, set placement to 'Footer' and set load method to 'Defer' or 'Async'.
- Page Builder: Go to Storefront > Page Builder, edit your homepage, and remove unused content sections (large hero banners with unoptimized images are the #1 BigCommerce speed killer). Replace large background images with WebP versions uploaded via Marketing > Image Manager.
- Apps: Go to Apps > My Apps and uninstall apps you are not actively using — each app may inject storefront JavaScript.
- Speed app: Consider installing a performance app from the BigCommerce App Marketplace (search 'page speed') for automated lazy loading and script management.
Redirect chainModerate effort
Update every internal link that passes through a redirect chain to point directly at the final destination URL, eliminating all intermediate hops.
On BigCommerce
- Crawl your store with Screaming Frog or a similar tool and export the redirect-chain report, noting chained URLs and their final destinations.
- For links inside page content: go to Storefront → Web Pages, open each affected page, locate the linked text in the WYSIWYG editor, click the hyperlink icon, and update the URL to the final destination.
- For navigation/header/footer links: go to Storefront → My Themes → Edit Theme (Page Builder) or edit the theme files directly. In Page Builder, click the navigation or footer widget containing the link and update the URL. In theme files (Stencil CLI), edit the relevant Handlebars template.
- For product or category descriptions containing chained links: go to Products → View or Products → Product Categories, open the item, and edit the description field to update the link.
- Review any existing redirects under Storefront → 301 Redirects and correct any entry whose destination is itself a redirect rather than a final URL.
- Re-crawl and validate that all internal links now resolve directly to 200 OK pages.
<!-- BEFORE: link points to an intermediate URL that itself redirects -->
<a href="https://example.com/old-page">Our Story</a>
<!-- AFTER: link points directly to the final destination URL -->
<a href="https://example.com/about-us">Our Story</a>Replace every intermediate redirect URL in your anchor href with the final destination URL — the one that returns HTTP 200 with no further redirects.
Search results indexableModerate effort
Add a noindex robots meta tag to all internal search result pages and block the search URL path in robots.txt to prevent Google from crawling and indexing thin, duplicate search results.
On BigCommerce
- In BigCommerce Admin, go to Storefront → My Themes → click 'Edit Theme Files' on your active theme (or use the Stencil CLI locally).
- Open 'templates/pages/search.html' — this is the template for all search result pages.
- Inside the <head> block (or in the parent layout file 'templates/layout/base.html' with a conditional), add: {{#if page_type '===' 'searchresults'}}<meta name="robots" content="noindex,follow">{{/if}}
- Save and apply the theme.
- For robots.txt: go to Advanced Settings → robots.txt and add Disallow: /search.php under the [User-agent: *] section.
- Confirm with Google Search Console URL Inspection on a sample /search.php?search_query= URL.
<meta name="robots" content="noindex,follow">Place this tag inside the <head> element of every search results page template.
Seo category description missingModerate effort
Write a 100–200 word description for every category page explaining what products it contains and who they are for, so Google can rank it for category-level keywords.
On BigCommerce
- In your BigCommerce control panel, go to Products → Product Categories.
- Click Edit (pencil icon) next to the category you want to update.
- Scroll down to the 'Category Description' field — it uses a rich-text (WYSIWYG) editor. Write or paste your 100–200 word description here.
- Use the editor's formatting tools to bold your primary keyword or add a short bullet list of sub-categories if relevant.
- Click Save & Exit.
- The description is output in your Stencil theme via the {{category.description}} Handlebars helper, which most themes render above the product listing by default.
- If it doesn't display, open your Stencil theme files in Page Builder or the Theme Editor (Storefront → My Themes → Edit), locate templates/pages/category.html, and ensure {{category.description}} is present in the template.
{{#if category.description}}
<div class="category-description">
{{{category.description}}}
</div>
{{/if}}In your Stencil theme, open templates/pages/category.html and add this where you want the description block rendered.
Seo category description thinModerate effort
Expand your category page description to at least 100 words of genuinely helpful, keyword-rich content that explains what shoppers will find in that category.
On BigCommerce
- In your BigCommerce control panel, go to Products > Product Categories.
- Click the category name to edit it.
- Find the 'Category Description' WYSIWYG editor and write or paste your expanded 100+ word description.
- Use the editor toolbar to add headings, bullet points, and links to subcategories.
- Click 'Save'. The description appears on the storefront wherever your theme's category.html template outputs {{category.description}}.
- If the description is not visible on the live page, open Storefront > My Themes > Edit Theme Files > templates/pages/category.html and confirm {{category.description}} is present and not commented out.
{{#if category.description}}
<div class="category-description">
{{{category.description}}}
</div>
{{/if}}Confirm this output tag exists in your theme's templates/pages/category.html to render the category description.
Seo category emptyQuick win
Either populate the empty category with products, or add a noindex tag and remove it from your navigation so Google does not waste crawl budget on a page with no content.
On BigCommerce
- Go to Products → Product Categories in your BigCommerce control panel.
- Locate the empty category (you can sort or filter by product count).
- Option A — Add products: Open each relevant product under Products → View, edit it, and assign it to this category in the 'Categories' field.
- Option B — Noindex: Open the category editor, scroll to the 'Search Engine Optimization' section, find 'Custom URL and SEO settings', and in the custom template or footer scripts section inject: <meta name='robots' content='noindex, follow'>. Alternatively, use a script in Storefront → Script Manager targeting only that category page's URL.
- Option B (easier): Use the 'SEO Manager' or 'Amasty SEO Suite' BigCommerce app to set noindex on individual categories via a dashboard toggle.
- Option C — Delete & redirect: Delete the category via the category editor. Then go to Server Settings → 301 Redirects and add a redirect from the old URL to the parent category.
- Ensure the category is removed from any navigation menu under Storefront → Navigation.
<meta name="robots" content="noindex, follow">Place inside the <head> element of an empty category page to prevent Google from indexing it.
Seo category sparseModerate effort
Add more products to sparse category pages, or consolidate very thin categories into broader, related ones so every indexed category page delivers genuine value to shoppers and search engines.
On BigCommerce
- Go to Products → Product Categories in your BigCommerce admin.
- Click 'Edit' on a sparse category. In the 'Category Description' field, add substantive intro text to give the page content beyond the product grid.
- To add products: go to each product's Edit page → scroll to 'Categories' → tick the target category. Or use the bulk edit CSV import/export.
- To merge categories: move products to the surviving category, then in Store Setup → 301 Redirects, add a redirect from the old category URL (e.g., /category/old-name/) to /category/new-name/.
- To noindex: BigCommerce does not expose per-category noindex natively. Use a Script Manager snippet (Storefront → Script Manager) that injects <meta name="robots" content="noindex, follow"> only on the target category URL, or use a third-party SEO app from the BigCommerce App Marketplace.
<meta name="robots" content="noindex, follow">Add inside <head> of any sparse category page you want excluded from Google's index while still being followable by crawlers.
Seo facet url not canonicalizedModerate effort
Add a canonical tag to every filtered, sorted, and paginated collection/category URL pointing back to the clean (unfiltered) category URL, so Google consolidates duplicate pages and focuses crawl budget on your real content.
On BigCommerce
- BigCommerce automatically generates canonical tags for standard category pages, but filter/facet URLs (e.g. ?brand=Nike&color=Red) may output self-referencing canonicals rather than pointing to the clean category URL.
- Go to Storefront → Themes → Edit Theme Files (Stencil theme). Open templates/layout/base.html and find the existing canonical tag or the {{{head.canonical_link}}} Handlebars helper.
- To override the canonical for faceted URLs, you need to modify the Stencil template logic so that on category pages, the canonical is always set to the category's base URL without query parameters. Use: {{#if category}} <link rel="canonical" href="{{urls.self | remove_query_params}}"> {{/if}} — exact syntax depends on your theme helpers.
- Alternatively, use a third-party SEO app from the BigCommerce App Marketplace (e.g. Amasty SEO, StoreSEO) that provides canonical control for faceted navigation.
- For BigCommerce native faceted search: go to Products → Product Filtering in the admin and ensure 'SEO URL format' is set to the cleanest option — BigCommerce can generate SEO-friendly filter URLs instead of query strings, which are easier to canonicalize.
- Verify in Google Search Console URL Inspection after deployment.
<head>
<!-- All other head tags -->
<link rel="canonical" href="https://www.example.com/collections/hoops">
</head>Place this inside the <head> of every filtered/sorted/paginated category page. The href must be the full, absolute clean URL (no query parameters).
Seo product content client renderedLarger project
Server-render your product descriptions in the initial HTML so that all crawlers — including Google, AI search bots, and social media scrapers — can read your content without executing JavaScript.
On BigCommerce
- BigCommerce's Stencil themes use Handlebars.js server-side templating — product descriptions render server-side by default.
- In the BigCommerce Control Panel, go to Storefront → My Themes → Advanced → Edit Theme Files. Navigate to templates/pages/product.html.
- Find {{{product.description}}} — the triple-brace syntax outputs raw HTML server-side. If this is missing or replaced by a custom JS fetch, restore it.
- For Product JSON-LD, locate or create templates/components/schema/product.html. BigCommerce Stencil automatically outputs basic Product schema. Enhance it by editing that file directly to add the description field: add '"description": "{{product.description}}"' inside the JSON-LD object.
- If you are using a headless BigCommerce setup (React/Next.js storefront), you must implement SSR or SSG via Next.js getServerSideProps or getStaticProps to pre-render product data into the HTML.
- Preview changes with Stencil CLI locally, then apply to the live theme. Validate with Google Rich Results Test or the URL Inspection tool.
Seo product description minimalModerate effort
Expand your product descriptions to at least 300 words by adding specifications, use cases, and benefits so search engines have enough content to rank and shoppers have enough information to buy.
On BigCommerce
- Go to BigCommerce Admin → Catalog → Products.
- Click the product name to open the editor.
- Select the 'Description' tab.
- Use the built-in Page Builder / rich-text editor to write a structured 300+ word description including specs (use a table or bulleted list), use cases, and benefits.
- Click 'Save & Exit'. BigCommerce will automatically update the page; submit the URL for re-indexing via Google Search Console.
<section class="product-description">
<h2>About the [Product Name]</h2>
<p>
The [Product Name] is a [category] designed for [target audience]. Whether you need
[use case 1] or [use case 2], this [product] delivers [core benefit] without
[common pain point].
</p>
<h3>Key Features & Specifications</h3>
<ul>
<li><strong>Material:</strong> [e.g. 100% organic cotton, BPA-free polypropylene]</li>
<li><strong>Dimensions:</strong> [W × H × D] / Weight: [X kg / X lbs]</li>
<li><strong>Colour options:</strong> [Colour 1], [Colour 2], [Colour 3]</li>
<li><strong>Compatibility:</strong> [e.g. Works with iOS 14+ and Android 10+]</li>
<li><strong>Warranty:</strong> [X-year manufacturer warranty]</li>
</ul>
<h3>Why Shoppers Choose [Product Name]</h3>
<p>
Unlike [generic alternatives], the [Product Name] [specific differentiator]. This means
[tangible benefit for the shopper], saving you [time / money / effort].
</p>
<p>
Ideal for [persona / scenario], the [Product Name] has been tested to [standard or
certification] and ships ready to use — no assembly required.
</p>
<h3>How to Use</h3>
<p>
[Step-by-step or scenario-based usage instructions in 2–4 sentences. Include any
important setup, safety, or care notes here.]
</p>
<h3>In the Box</h3>
<ul>
<li>1 × [Product Name]</li>
<li>1 × [Accessory or manual]</li>
<li>1 × [Charging cable / carry bag / etc.]</li>
</ul>
</section>Structural template for a product description section — paste inside your product page's main content area.
Seo product description missingModerate effort
Write and publish a 200–400 word product description covering what the product is, its key specs, who it's for, and how to use it.
On BigCommerce
- In your BigCommerce control panel, navigate to Products → View.
- Click the product name to open the editor.
- Select the 'Description' tab. Use the rich-text editor to write or paste your 200–400 word description.
- Click the 'Other Details' or 'SEO & Sharing' tab to set a custom meta description (if you want text different from the auto-generated excerpt).
- Click 'Save & Exit' and preview the live product page to confirm the description is visible.
<section class="product-description">
<h2>About This Product</h2>
<p>
The <strong>Trailblazer 500 Waterproof Hiking Boot</strong> is a lightweight,
full-grain leather boot built for all-day comfort on rugged mountain trails.
Its Gore-Tex membrane keeps feet dry in rain and creek crossings while the
Vibram outsole delivers confident grip on wet rock and loose scree.
</p>
<p>
Designed for day hikers and weekend backpackers who want reliable protection
without the weight of a mountaineering boot, the Trailblazer 500 strikes the
ideal balance between support and agility. The padded collar and gusseted
tongue prevent trail debris from entering the boot, and the cushioned EVA
midsole absorbs impact mile after mile.
</p>
<h3>Key Specifications</h3>
<ul>
<li><strong>Upper:</strong> Full-grain leather with Gore-Tex waterproof lining</li>
<li><strong>Outsole:</strong> Vibram Megagrip rubber</li>
<li><strong>Weight:</strong> 680 g / pair (size UK 9)</li>
<li><strong>Shaft height:</strong> Mid (ankle) cut</li>
<li><strong>Available widths:</strong> Standard and Wide</li>
</ul>
<h3>How to Use</h3>
<p>
Lace firmly for ankle support on uneven terrain. Break the boot in over two
or three shorter walks before a full-day hike. Apply a water-repellent spray
to the leather upper every 20–30 hours of trail use to maintain waterproofing.
</p>
</section>Minimum viable product description markup — paste inside your product page's <main> or article element.
Seo product description thinModerate effort
Expand every product description to at least 300 words of unique, keyword-rich content that answers real shopper questions and gives Google enough text to understand and rank the page.
On BigCommerce
- Go to Admin → Catalog → Products → [select the product] → 'Description' tab.
- Use the built-in Page Builder rich-text / HTML editor to write your expanded description.
- For bulk updates, go to Admin → Catalog → Export, choose the 'Product descriptions' template, update the 'Description' column in the exported CSV, and re-import via Admin → Catalog → Import.
- Save the product and submit the URL for re-indexing in Google Search Console.
<section class="product-description" aria-label="Product description">
<h2>About This Product</h2>
<p>
Write your opening paragraph here (2–3 sentences introducing the product,
its primary benefit, and who it is for). Aim for a natural, engaging tone
that mirrors how your customers talk about this type of product.
</p>
<h3>Key Features</h3>
<ul>
<li><strong>Feature One:</strong> Explain the benefit, not just the spec.</li>
<li><strong>Feature Two:</strong> Include the detail a shopper needs to decide.</li>
<li><strong>Feature Three:</strong> Use the words your customers actually search for.</li>
<li><strong>Feature Four:</strong> Keep each bullet to one clear point.</li>
</ul>
<h3>Materials & Specifications</h3>
<p>
Describe materials, dimensions, weight, compatibility, or other technical
details relevant to your product category. Specificity builds trust and
captures long-tail searches (e.g. "100% organic cotton", "fits 13-inch laptops").
</p>
<h3>How to Use</h3>
<p>
Walk the customer through setup, application, or use in plain language.
Answer the most common pre-purchase questions here so shoppers feel confident.
</p>
<h3>Why Our Customers Love It</h3>
<p>
Reinforce with a sentence or two of social proof context or a unique selling
point that differentiates this product from generic alternatives.
</p>
</section>Ideal semantic structure for a product description section on any platform's product page template.
Seo product image alt filenameModerate effort
Replace auto-generated filename-based alt text on product images with short, descriptive phrases that accurately describe what the image shows.
On BigCommerce
- Go to Admin → Products → View and open a product.
- Click the 'Images & Videos' tab.
- Click a product image thumbnail; an 'Image Description' field appears below it.
- Enter your descriptive alt text in the 'Image Description' field (BigCommerce uses this as the alt attribute).
- Click Save. Repeat for every image and every product.
- For bulk updates, export your product catalog via Admin → Products → Export, edit the 'image_description' columns in the CSV, and re-import.
<!-- BAD: filename-based alt text -->
<img src="/images/IMG_4823_blue_v2.webp" alt="IMG_4823_blue_v2.webp">
<!-- BAD: empty alt text -->
<img src="/images/blue-sweater.webp" alt="">
<!-- GOOD: descriptive alt text -->
<img src="/images/blue-sweater.webp" alt="Blue cotton crew-neck sweater, front view">The correct pattern for a product image alt attribute — descriptive, specific, keyword-natural.
Seo product missing brandModerate effort
Add a `brand` property to your Product schema markup so search engines can match your listings to brand-specific queries.
On BigCommerce
- Go to BigCommerce Admin → Storefront → Script Manager, or open your theme in Page Builder → Edit Theme Files.
- Find `templates/pages/product.html` (Cornerstone theme) — search for the existing `application/ld+json` Product schema block.
- Add the brand property using Handlebars: `"brand": { "@type": "Brand", "name": "{{product.brand.name}}" }` — BigCommerce exposes brand via the `product.brand` object in its Stencil context.
- If using a third-party SEO app from the BigCommerce App Marketplace (e.g., 'SEO King'), check its structured data settings to enable/map the brand field there instead.
- Save and preview a branded product page, then validate with Google's Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "{{product.title}}",
"image": "{{product.main_image.data}}",
"description": "{{product.description}}",
"sku": "{{product.sku}}",
"brand": {
"@type": "Brand",
"name": "{{product.brand.name}}"
},
"offers": {
"@type": "Offer",
"url": "{{product.url}}",
"priceCurrency": "{{currency_selector.active_currency_code}}",
"price": "{{product.price.without_tax.value}}",
"availability": "https://schema.org/{{#if product.availability}}InStock{{else}}OutOfStock{{/if}}"
}
}
</script>Inside your Cornerstone theme's product.html template, locate the existing JSON-LD block and add the brand property using the Stencil Handlebars context variable.
Seo product missing gtinModerate effort
Add a GTIN (and/or MPN) field to your Product structured data so Google can match your listings to its product knowledge graph for rich results and Google Shopping.
On BigCommerce
- Go to Admin → Products → [select a product] → 'Other Details' tab.
- Fill in the 'UPC/EAN' field (this maps to GTIN) and the 'MPN' field — both are native BigCommerce fields.
- BigCommerce's Stencil themes automatically include these values in the Product JSON-LD rendered on the product page ('gtin' and 'mpn' properties).
- To confirm, view the page source of a product and search for '"gtin"'.
- For headless BigCommerce storefronts, query the GraphQL Catalog API for 'upc' and 'mpn' and inject them into your custom Product schema block.
Seo product missing stock statusModerate effort
Add a visible stock availability label and an `availability` property to your Product structured data so Google can display rich results and shoppers know immediately whether a product is in stock.
On BigCommerce
- BigCommerce injects Product structured data automatically via its Stencil theme engine. To ensure `availability` is included, go to Storefront → Themes → Edit Theme Files (Advanced Editor) and locate `templates/pages/product.html`.
- Search for the `<script type="application/ld+json">` block. If `availability` is absent, add it inside the JSON object: `"availability": "{{#if product.stock_level}}https://schema.org/InStock{{else}}https://schema.org/OutOfStock{{/if}}"`.
- For the visible label, edit the same product template to output stock text using Handlebars: `{{#if product.stock_level}}<span>In Stock</span>{{else}}<span>Out of Stock</span>{{/if}}`.
- Alternatively install the *SEO Doctor* or *JSON-LD for SEO* app from the BigCommerce App Marketplace, which handles availability mapping automatically.
- Validate with Rich Results Test after publishing.
<!-- Product structured data with availability -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Your Product Name",
"description": "A short description of your product.",
"sku": "YOUR-SKU-123",
"image": "https://www.example.com/images/product.jpg",
"brand": {
"@type": "Brand",
"name": "Your Brand Name"
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/products/your-product",
"priceCurrency": "USD",
"price": "29.99",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
</script>
<!-- Visible stock label near Add-to-Cart button -->
<p class="stock-status" style="font-weight:bold; color:#2a7a2a;">✓ In Stock</p>Paste the complete block into the <head> section of your product page HTML. Change availability value to OutOfStock or PreOrder as needed.
Seo product no imagesModerate effort
Add at least one high-quality image to every product page so shoppers can see what they're buying and Google can surface your products in Image Search.
On BigCommerce
- Log in to your BigCommerce control panel and navigate to Products → View.
- Click the product name that is missing images.
- Select the 'Images & Videos' tab on the product edit screen.
- Click 'Upload Images', select your files, and upload them.
- After uploading, click the thumbnail of each image, enter descriptive text in the 'Alt Text' field, and designate one image as the 'Thumbnail' (main image).
- Click 'Save' and preview the storefront product page to verify images are visible.
<figure class="product-gallery">
<img
src="/images/products/black-leather-wallet-front.jpg"
alt="Black leather wallet with RFID blocking, front view"
width="800"
height="800"
loading="eager"
/>
<img
src="/images/products/black-leather-wallet-open.jpg"
alt="Black leather wallet open showing card slots and cash pocket"
width="800"
height="800"
loading="lazy"
/>
</figure>Basic responsive product image with descriptive alt text — place inside your product page HTML where the gallery/main image appears.
Seo product no spec tableModerate effort
Add a structured specifications table or list to every product page so shoppers, search engines, and AI tools can instantly find and use key product details.
On BigCommerce
- Go to Products → (select product) → scroll to the 'Custom Fields' section at the bottom of the edit screen.
- Add each specification as a Custom Field: Name = attribute label (e.g. 'Material'), Value = attribute value (e.g. 'Stainless Steel'). BigCommerce exposes these via the {{product.custom_fields}} Handlebars variable.
- In your Stencil theme, open 'templates/components/products/product-view.html' and add a loop to render custom fields as a <table> or <dl>.
- Alternatively, use the Page Builder (Storefront → My Themes → Customize) to add an HTML widget in the product page template containing a static spec table for that product.
- For a no-code path, install a BigCommerce app from the App Marketplace such as 'Tabs & Accordion' or 'Product Specifications' to display custom fields as a formatted table without editing theme files.
- Preview on mobile (Page Builder has a mobile-view toggle) before publishing.
Seo product price not in htmlModerate effort
Render your product price in the server-generated HTML so Google and other crawlers can read it directly — without executing JavaScript.
On BigCommerce
- In BigCommerce Admin go to Storefront → My Themes → Edit Theme Files (Stencil themes).
- Open templates/components/products/price.html (Stencil). Prices are rendered via Handlebars server-side using {{product.price.without_tax.formatted}} or similar. Confirm these expressions are present and not commented out.
- If you have a headless BigCommerce storefront (e.g. Next.js), move price fetching from a client component to a Server Component or use getServerSideProps / generateMetadata to embed the price in the initial HTML.
- For JSON-LD structured data, BigCommerce Stencil themes include a schema partial at templates/components/schema.html — ensure the 'offers' → 'price' field is populated with the Handlebars price variable.
- Preview via 'View Page Source' and confirm the price string is present.
Seo product single imageModerate effort
Add at least 4 product images (multiple angles, detail shots, and lifestyle/in-use photos) to every product page to improve click-through rates, conversions, and Google Images visibility.
On BigCommerce
- Go to Admin → Products → View → [select your product] → Images & Videos tab.
- Click 'Upload Images' and select multiple files at once to add them to the gallery.
- Set a 'Thumbnail' checkbox on the image you want as the main display image.
- Click the pencil/edit icon on each image to open its settings and fill in the 'Alt Text' field.
- Drag images to reorder them, then click 'Save' at the bottom of the page.
<figure class="product-gallery">
<!-- Main hero image -->
<img
src="/images/red-leather-wallet-front.webp"
alt="Red leather bifold wallet — front view"
width="2000"
height="2000"
loading="eager"
fetchpriority="high"
/>
</figure>
<!-- Thumbnail strip -->
<ul class="product-thumbnails" role="list">
<li>
<img
src="/images/red-leather-wallet-front-thumb.webp"
alt="Red leather bifold wallet — front view"
width="200"
height="200"
loading="lazy"
/>
</li>
<li>
<img
src="/images/red-leather-wallet-back-thumb.webp"
alt="Red leather bifold wallet — back view"
width="200"
height="200"
loading="lazy"
/>
</li>
<li>
<img
src="/images/red-leather-wallet-interior-thumb.webp"
alt="Red leather bifold wallet — interior card slots"
width="200"
height="200"
loading="lazy"
/>
</li>
<li>
<img
src="/images/red-leather-wallet-lifestyle-thumb.webp"
alt="Red leather bifold wallet shown in a shirt pocket"
width="200"
height="200"
loading="lazy"
/>
</li>
</ul>Basic accessible product image gallery markup. Place inside your product detail page template.
Seo product title genericModerate effort
Rewrite every product page title tag to include the specific product name plus at least one differentiating attribute (variant, material, brand, or model) so Google and shoppers can instantly tell what the page is about.
On BigCommerce
- Go to Products → View in your BigCommerce control panel and click the product name.
- Select the 'Other Details' tab within the product editor.
- Find the 'Search Engine Optimization' section and fill in the 'Page Title' field with your descriptive title.
- Click Save & Exit.
- For bulk updates, export your product catalog via Products → Export, fill in the 'Page Title' column in the CSV, then re-import via Products → Import.
- To set a store-wide default title format, go to Storefront → My Themes → Advanced → Edit Theme Files and edit config.json or the relevant Handlebars template (e.g. templates/pages/product.html), updating the {{#if product.title}}...{{/if}} block.
{{!-- templates/pages/product.html --}}
{{#partial "head"}}
<title>
{{#if product.title}}
{{product.title}}
{{#if product.brand.name}} – {{product.brand.name}}{{/if}}
{{#if product.category}} – {{product.category.[0].name}}{{/if}}
– {{settings.store_name}}
{{else}}
{{settings.store_name}}
{{/if}}
</title>
{{/partial}}In Stencil theme: edit templates/pages/product.html. Locate the <title> block and update it to include category and brand. This is the Handlebars pattern.
Seo variant urls in sitemapModerate effort
Remove product variant URLs (e.g. ?variant= or ?sku= query strings) from your XML sitemap and keep only the canonical base product URL for each product.
On BigCommerce
- BigCommerce generates its sitemap automatically at yourdomain.com/xmlsitemap.php and normally excludes variant query strings.
- Go to Store Setup → Store Profile → Verify your store URL is correct so the sitemap root is accurate.
- If a third-party SEO app (e.g. 'SEO Doctor', 'Aheadworks SEO', 'Yotpo') is overriding the sitemap, open that app's settings and disable variant URL inclusion.
- For headless BigCommerce storefronts, see the Headless / Custom entry and filter out ?sku= or ?variant= parameters in your sitemap-generation script.
- Re-submit the sitemap in Google Search Console.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- CORRECT: canonical base product URL -->
<url>
<loc>https://www.example.com/products/blue-sneaker</loc>
<lastmod>2024-06-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<!-- WRONG — never include variant query strings:
<url>
<loc>https://www.example.com/products/blue-sneaker?variant=12345</loc>
</url>
<url>
<loc>https://www.example.com/products/blue-sneaker?sku=blue-large</loc>
</url>
-->
</urlset>Correct sitemap entry — clean base product URL only, no query parameters.
Seo variant urls not canonicalizedModerate effort
Add a canonical tag to every product variant URL pointing back to the base product page, so Google consolidates ranking signals on one URL instead of splitting them across hundreds of duplicates.
On BigCommerce
- BigCommerce automatically outputs a canonical tag on product pages using the base product URL. Go to Storefront → My Themes → your active theme → Edit Theme Files.
- Open templates/pages/product.html (or the equivalent Stencil template). Search for 'canonical'.
- The canonical is typically output via a Handlebars helper such as {{canonicalUrl}} or set globally by the platform. Verify it resolves to the base product URL (without option/variant parameters).
- If your theme or a custom script appends variant query parameters to the canonical, override it: set the canonical tag manually to {{urls.product}} which resolves to the base product URL.
- Confirm in BigCommerce's built-in SEO settings: go to Store Setup → Store Settings → Search Engine Optimization and ensure 'Canonical URL' options favour the base product path.
- Check your XML sitemap (Marketing → Sitemap) to confirm only base product URLs are listed, not variant URLs.
{{!-- In templates/layout/base.html or templates/pages/product.html --}}
{{!-- BigCommerce Stencil: use the built-in canonicalUrl context variable --}}
<head>
{{!-- This outputs the base product canonical URL, ignoring option query params --}}
<link rel="canonical" href="{{urls.product}}">
</head>In your Stencil theme, open templates/pages/product.html. Locate or add this block inside the <head> section (typically via the base template).
Server errorModerate effort
Identify and fix every page returning an HTTP 5xx server error so search engines can crawl and index those URLs again.
On BigCommerce
- Log in to your BigCommerce control panel and go to Server Settings > Logs (or use the Store Logs section) to view application-level errors.
- If a recently installed app is suspect, go to Apps > My Apps, click the app, and Uninstall or Disable it to test.
- For Stencil theme errors, use the Stencil CLI locally (stencil start) which surfaces Handlebars template errors in your terminal; fix the template, then push via stencil push.
- For pages built with Page Builder, go to Storefront > Pages, open the affected page, and check for broken widgets — remove or reconfigure them.
- Contact BigCommerce Support via the Help menu with the affected URL; they can pull infrastructure logs.
- After the fix, use Google Search Console > URL Inspection > Request Indexing to prompt re-crawling.
# Run this in your terminal to check the HTTP status code of any URL
curl -o /dev/null -s -w "HTTP Status: %{http_code}\n" https://www.example.com/your-page
# A healthy page returns:
# HTTP Status: 200
# A broken page returns (example):
# HTTP Status: 500This is the correct HTTP 200 response header your server should return for a healthy page. Use curl on the command line to verify any URL's status code before and after your fix.
Slow pageModerate effort
Reduce your page load time to under 3 seconds by compressing images, eliminating render-blocking scripts and styles, and improving server response speed.
On BigCommerce
- Go to Storefront → My Themes → Advanced → Edit Theme Files and review your theme's JavaScript files for bloat or synchronous loading patterns.
- Images: Use BigCommerce's built-in Akamai Image Manager (enabled by default on most plans) — ensure you are referencing images via the CDN URL and using the 'width' and 'format=auto' query parameters to serve correctly sized WebP images.
- In the theme's templates/layout/base.html, add defer or async to non-critical <script> tags.
- Apps/Scripts: Go to Channel Manager → Scripts (or Storefront → Script Manager) — review every installed script and remove those not in active use.
- Enable BigCommerce's built-in Akamai CDN (included on most plans) — confirm it is active under Store Setup → Store Profile.
- Use Google PageSpeed Insights on your storefront URL and address each flagged resource type individually in the theme editor.
<img
src="product-image.webp"
alt="Descriptive product alt text"
width="800"
height="600"
loading="lazy"
decoding="async"
>Add these attributes to every image below the fold to enable native lazy loading and prevent layout shift.
Thin contentModerate effort
Add meaningful, original written content to pages that contain fewer than 300 words so Google has enough substance to rank and display them confidently.
On BigCommerce
- Go to BigCommerce Admin → Catalog → Products → click the product to edit.
- Click the 'Description' tab. Use the rich-text editor (WYSIWYG) to write an expanded product description — cover specifications, benefits, use-cases, and FAQs.
- For category pages: Catalog → Product Categories → click 'Edit' on the category → add text in the 'Category Description' field. Ensure your theme's category template is set to display this description (check Storefront → Themes → Customize).
- For content pages: Storefront → Web Pages → click 'Edit' on the page → expand the content in the WYSIWYG editor.
- Save and use the 'Preview' button to confirm text renders on the storefront.
<section class="product-description">
<h2>About This Product</h2>
<p>
The Merino Wool Crew-Neck Sweater is crafted from 100% ethically sourced
Grade-A Merino wool, making it naturally temperature-regulating, moisture-
wicking, and soft enough to wear directly against the skin. Perfect for
layering in autumn and winter, or as a standalone piece during mild spring
evenings.
</p>
<h3>Key Features</h3>
<ul>
<li>100% Merino wool — no synthetic blends</li>
<li>Available in sizes XS–3XL with a relaxed, unisex fit</li>
<li>12 colours, each piece individually yarn-dyed for depth</li>
<li>Ribbed cuffs and hem for a tailored finish</li>
<li>Machine washable on a gentle 30°C wool cycle</li>
<li>Certified by the Responsible Wool Standard (RWS)</li>
</ul>
<h3>Sizing & Fit</h3>
<p>
This sweater is cut with a relaxed, slightly oversized silhouette. If you
prefer a closer fit, we recommend sizing down. See our full <a href="/size-guide">size guide</a>
for chest, waist, and sleeve measurements.
</p>
<h3>Care Instructions</h3>
<p>
Machine wash cold on a gentle/wool cycle. Lay flat to dry — do not tumble
dry, iron at high heat, or dry-clean. With proper care, Merino wool retains
its shape and softness for years.
</p>
<h3>Frequently Asked Questions</h3>
<dl>
<dt>Is Merino wool itchy?</dt>
<dd>
No. Merino fibres are finer than standard wool (under 19.5 microns),
which means they bend against the skin rather than prick it, making this
sweater comfortable even for people who normally find wool irritating.
</dd>
<dt>How does Merino wool compare to cashmere?</dt>
<dd>
Merino is more durable and easier to care for than cashmere, while still
offering exceptional softness. It's an ideal everyday choice for those
who want luxury without high maintenance.
</dd>
<dt>Can I return or exchange this item?</dt>
<dd>
Yes. We accept returns and exchanges within 30 days of delivery, provided
the item is unworn and in its original packaging. See our
<a href="/returns">returns policy</a> for full details.
</dd>
</dl>
</section>Example of a well-structured, content-rich product description section with FAQ — paste into any HTML page template.
Title too longQuick win
Shorten your page title tag to 60 characters or fewer so it displays fully — without truncation — in Google search results.
On BigCommerce
- For a product: go to Products → View, open the product, click the 'SEO' tab, and edit the 'Page Title' field.
- For a category: go to Products → Product Categories, open the category, and edit the 'Page Title' field in the 'SEO' section.
- For static pages: go to Storefront → Web Pages, open the page, and edit the 'Page Title' field.
- For the homepage: go to Storefront → My Theme → Edit Theme Files (or Store Setup → Store Settings → Display) and look for the homepage SEO title field in Storefront → SEO.
- Save changes and keep all titles ≤60 characters.
<head>
<meta charset="UTF-8">
<title>Running Shoes for Men | YourBrand</title>
</head>Place inside the <head> element of every HTML page. Keep the total character count at or under 60.
Title too shortQuick win
Expand your page title to between 30 and 60 characters so Google displays it fully in search results and shoppers can immediately understand what the page is about.
On BigCommerce
- For a product: go to Products → View → select the product → click the 'Other details' tab → find the 'Page Title' field under 'Search Engine Optimization' → update it.
- For a category: go to Products → Product Categories → select the category → scroll to the 'Search Engine Optimization' section → update 'Page Title'.
- For the homepage: go to Storefront → My Theme → click 'Customize' → or go to Store Setup → Store Profile — homepage meta is often set under Storefront → Pages → Home.
- For content pages: go to Storefront → Web Pages → select the page → update the 'Page Title' field in the SEO section.
- Save changes; BigCommerce renders the title tag directly from this field with no additional configuration needed.
<head>
<meta charset="UTF-8">
<title>Men's Merino Wool Beanies – BrandName</title>
</head>Place inside the <head> element of every page. Replace the example with your actual descriptive title (30–60 chars).
Answer Engine Optimization · 17 fixes
Aeo schema client renderedModerate effort
Move your JSON-LD structured data from client-side JavaScript injection to server-rendered HTML so that AI crawlers and search engines can read it in the raw page source.
On BigCommerce
- In your BigCommerce admin go to Storefront → My Themes → Advanced → Edit Theme Files (Stencil CLI is recommended for larger edits).
- Open templates/pages/product.html (or the relevant Handlebars template) and add the JSON-LD <script> block directly, using Handlebars expressions ({{product.name}}, {{product.price.without_tax.formatted}}, etc.) to inject dynamic values server-side.
- If you use the BigCommerce Page Builder or a third-party app for schema, verify in the page source that the schema appears without JavaScript execution — Page Builder widgets are typically client-rendered and are NOT suitable for schema injection.
- Remove or disable any GTM-based or JavaScript-based schema injection to avoid duplication.
- Push your theme changes and view the live page source to confirm the JSON-LD block appears in the raw HTML response.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Your Product Name",
"description": "A clear description of your product.",
"sku": "YOUR-SKU-123",
"brand": {
"@type": "Brand",
"name": "Your Brand Name"
},
"offers": {
"@type": "Offer",
"url": "https://www.example.com/products/your-product",
"priceCurrency": "USD",
"price": "49.99",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "128"
}
}
</script>Place this block inside <head> or <body> in the server-rendered HTML. All values must be populated by the server, not by JavaScript.
Article missing authorQuick win
Add a structured-data author field (schema.org Person) to every article or blog post so AI engines and Google can identify and trust who wrote the content.
On BigCommerce
- BigCommerce's built-in blog is limited in structured data support. Go to Storefront → Script Manager and create a new script scoped to 'Blog Post' pages.
- Use the Script Manager's Handlebars context to inject the JSON-LD block; use {{blog.author}} if exposed, otherwise hardcode or use a custom field approach.
- For richer control, edit the blog-post.html template in the Stencil theme (via Stencil CLI or WebDAV for legacy Blueprint themes) and add the JSON-LD block inside the <head> partial.
- Add a custom field in the blog post editor for 'Author URL' and 'Author SameAs URLs', then reference them in the template.
- Validate with the Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "How to Choose the Best Running Shoes",
"datePublished": "2024-03-10T09:00:00+00:00",
"dateModified": "2024-06-20T14:00:00+00:00",
"author": {
"@type": "Person",
"name": "Alex Johnson",
"url": "https://www.yourstore.com/about/alex-johnson",
"sameAs": [
"https://www.linkedin.com/in/alexjohnson",
"https://twitter.com/alexjohnson"
]
},
"publisher": {
"@type": "Organization",
"name": "Your Store Name",
"logo": {
"@type": "ImageObject",
"url": "https://www.yourstore.com/assets/logo.png",
"width": 300,
"height": 60
}
},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://www.yourstore.com/blog/how-to-choose-running-shoes"
}
}
</script>For any static site or custom CMS: paste inside the <head> of each article page and fill in real values.
Faq schema not visibleModerate effort
Render all FAQ answers in the server-delivered HTML so that both Google and your FAQ structured data can see every question and answer — not just the one currently open in a JavaScript accordion.
On BigCommerce
- Go to Storefront → Script Manager (or Storefront → My Themes → Edit Theme Files) in your BigCommerce Admin.
- Open the Handlebars template for your FAQ page (e.g. templates/pages/page.html or a custom template assigned to that page).
- Replace the JavaScript accordion markup with native <details>/<summary> HTML so all answers are in the server-rendered HTML.
- Inject the FAQPage JSON-LD script block into the page <head> using Script Manager (set location to 'Head', page target to the FAQ page URL) or hardcode it in the template file.
- Publish and validate with the Rich Results Test.
<section>
<details>
<summary>What is your return policy?</summary>
<p>We accept returns within 30 days of purchase. Items must be unused and in original packaging. Contact support@example.com to start a return.</p>
</details>
<details>
<summary>How long does shipping take?</summary>
<p>Standard shipping takes 3–5 business days. Express shipping (1–2 business days) is available at checkout.</p>
</details>
<details>
<summary>Do you ship internationally?</summary>
<p>Yes, we ship to over 40 countries. International orders typically arrive within 7–14 business days.</p>
</details>
<details>
<summary>Can I change or cancel my order?</summary>
<p>Orders can be changed or cancelled within 1 hour of placement. After that, please wait for delivery and use our return process.</p>
</details>
</section>Replace JS-only accordion with native <details>/<summary> elements — all answers stay in the HTML at all times, visible to crawlers regardless of open/closed state.
Invalid rating valueModerate effort
Fix the AggregateRating.ratingValue in your structured data so it is a valid number between 1 and 5 (or your declared scale's minimum and maximum).
On BigCommerce
- Go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil).
- Search for 'ratingValue' inside templates/pages/product.html or the theme's schema.json / structured data partial.
- Confirm the value references a Handlebars variable such as {{product.rating.average}} rather than a static 0. BigCommerce's native Stencil Handlebars context exposes product.rating.average and product.rating.count.
- Add a conditional to suppress the AggregateRating block when there are no reviews: {{#if product.rating.count}} … {{/if}}.
- If you use a third-party reviews app (PowerReviews, Yotpo, etc.), check whether that app injects its own structured data — disable any conflicting manual markup in the theme to avoid duplicate or zeroed-out blocks.
- Save and push the theme, then test a product URL in the Google Rich Results Test.
{{#if product.rating.count}}
{{#if product.rating.average}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "{{product.title}}",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{product.rating.average}}",
"bestRating": "5",
"worstRating": "1",
"reviewCount": "{{product.rating.count}}"
}
}
</script>
{{/if}}
{{/if}}Place in templates/pages/product.html inside your Stencil theme, within the <head> section or just before </body>. Uses Stencil Handlebars context variables.
Low answer first scoreModerate effort
Restructure page content to lead with a direct, concise answer, use question-format headings, and add FAQ structured data so search engines and AI assistants can surface your answers prominently.
On BigCommerce
- Storefront → My Themes → Edit Theme Files (or Customize → Advanced → Edit Theme Files).
- For product pages, open templates/pages/product.html and add the answer summary paragraph at the top of the product description output.
- For content/landing pages: Content → Web Pages → Edit the page; place the 160-character summary as the first paragraph in the WYSIWYG editor and rewrite any subheadings as questions.
- To add FAQPage JSON-LD, open templates/layout/base.html and paste the JSON-LD <script> block just before </body> on pages that contain FAQ content, OR add it conditionally to product/category templates.
- BigCommerce's built-in 'Custom HTML' widget (Page Builder → drag HTML widget) also lets you inject JSON-LD per-page without touching theme files.
<!-- Answer-first page structure template -->
<!-- 1. Direct-answer summary (≤160 characters) -->
<p class="answer-summary">
[Product Name] does [core benefit] by [key mechanism] — ideal for [target customer].
</p>
<!-- 2. Question-format H2 subheading -->
<h2>What does [Product Name] do?</h2>
<p>Direct 1–2 sentence answer here. Then expand with supporting detail below.</p>
<!-- 3. Another question-format heading -->
<h2>Who is [Product Name] designed for?</h2>
<p>Direct answer. Then elaborate.</p>
<!-- 4. FAQ section (visible on page — required for FAQPage schema) -->
<section id="faq">
<h2>Frequently Asked Questions</h2>
<h3>How long does shipping take?</h3>
<p>Standard shipping takes 3–5 business days. Express options are available at checkout.</p>
<h3>What is your return policy?</h3>
<p>We accept returns within 30 days of delivery on unused items in original packaging.</p>
<h3>Is [Product Name] compatible with [common concern]?</h3>
<p>Yes. [One-sentence direct answer with any important caveats.]</p>
</section>
<!-- 5. FAQPage JSON-LD (copy the JSON-LD snippet above and paste here or in <head>) -->Page content structure template — place this as the opening content block on any product, category, or landing page.
Low review countModerate effort
Collect at least 5 published reviews so Google will display star ratings in search results alongside your product listings.
On BigCommerce
- Go to Store Setup → Store Settings → Product Reviews tab and ensure product reviews are enabled.
- Install a review app from the BigCommerce App Marketplace — 'Yotpo', 'Judge.me', or 'Okendo' all support BigCommerce and automatically inject AggregateRating structured data.
- In the app settings, activate post-purchase review request emails with a 7–14 day delay after shipment.
- BigCommerce's default theme (Cornerstone) already outputs basic AggregateRating schema when native reviews exist — confirm by inspecting page source for 'aggregateRating' in a JSON-LD block.
- For custom or headless themes, add the JSON-LD snippet (see code examples) to your product page template.
<!-- Product structured data with AggregateRating -->
<!-- Note: Google will only show review stars when reviewCount >= 5 -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Your Product Name",
"image": [
"https://example.com/images/product-front.jpg",
"https://example.com/images/product-side.jpg"
],
"description": "A clear, accurate description of your product.",
"sku": "SKU-12345",
"mpn": "MPN-12345",
"brand": {
"@type": "Brand",
"name": "Your Brand"
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"reviewCount": "12",
"bestRating": "5",
"worstRating": "1"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/products/your-product",
"priceCurrency": "USD",
"price": "49.99",
"priceValidUntil": "2026-12-31",
"itemCondition": "https://schema.org/NewCondition",
"availability": "https://schema.org/InStock",
"seller": {
"@type": "Organization",
"name": "Your Store Name"
}
}
}
</script>Drop this complete block into the <head> section of any product page. Swap in your real values for name, image, SKU, price, ratingValue, and reviewCount.
Missing schema articleModerate effort
Add Article schema markup (JSON-LD) to every blog post and editorial page so Google can identify and rich-result-enhance your content in search.
On BigCommerce
- Go to Storefront → Script Manager → Create a Script.
- Set Location to 'Head', Pages to 'Store Pages' (or more precisely target blog pages), and paste the JSON-LD script block with static values as a test.
- For dynamic values, edit your Stencil theme files: open 'templates/pages/blog-post.html' and insert the JSON-LD block there, using Handlebars variables ({{blog.post.title}}, {{blog.post.author}}, {{blog.post.date.created_at}}) to populate fields.
- Upload the updated theme via Stencil CLI or the Theme Editor, then validate a blog post URL with the Rich Results Test.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>How to Choose the Right Running Shoes</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "How to Choose the Right Running Shoes",
"description": "A complete guide to selecting running shoes based on your gait, terrain, and training goals.",
"image": {
"@type": "ImageObject",
"url": "https://www.example.com/images/running-shoes-guide.jpg",
"width": 1200,
"height": 630
},
"author": {
"@type": "Person",
"name": "Jane Smith",
"url": "https://www.example.com/authors/jane-smith"
},
"publisher": {
"@type": "Organization",
"name": "Example Store",
"logo": {
"@type": "ImageObject",
"url": "https://www.example.com/logo.png",
"width": 250,
"height": 60
}
},
"datePublished": "2024-03-15",
"dateModified": "2024-06-01",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://www.example.com/blog/how-to-choose-running-shoes"
},
"url": "https://www.example.com/blog/how-to-choose-running-shoes"
}
</script>
</head>
<body>
<!-- page content -->
</body>
</html>Place this entire block inside the <head> element of any article or blog-post page. Fill in all values before publishing.
Missing schema breadcrumblistModerate effort
Add BreadcrumbList structured data (JSON-LD) to every page so Google can display your site's navigation path directly in search results.
On BigCommerce
- In your BigCommerce admin go to Storefront › My Themes › your active theme › Advanced › Edit Theme Files.
- Open templates/layout/base.html (or the Cornerstone equivalent: templates/pages/product.html, templates/pages/category.html).
- Insert the JSON-LD script block before </head> using Handlebars variables: {{product.title}}, {{category.name}}, {{urls.home}}, {{product.url}}, {{category.url}} to make values dynamic.
- Alternatively, install a structured data app from the BigCommerce App Marketplace (search 'schema' or 'structured data') that handles BreadcrumbList automatically.
- Save changes and validate with Google's Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://www.example.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Women's Clothing",
"item": "https://www.example.com/womens-clothing/"
},
{
"@type": "ListItem",
"position": 3,
"name": "Dresses",
"item": "https://www.example.com/womens-clothing/dresses/"
},
{
"@type": "ListItem",
"position": 4,
"name": "Blue Wrap Dress",
"item": "https://www.example.com/womens-clothing/dresses/blue-wrap-dress/"
}
]
}
</script>Place this <script> block inside <head> or anywhere in <body> on any page with a breadcrumb trail. Extend itemListElement with one ListItem per level.
Missing schema faqpageQuick win
Add FAQPage schema markup to any page that contains a Frequently Asked Questions section so Google can display your answers as rich results directly in search.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → Script Manager → click 'Create a Script'.
- Set 'Location on page' to Footer, 'Select pages where script will be added' to 'Specific pages', and choose the page containing your FAQ.
- Paste your complete JSON-LD <script type='application/ld+json'> block into the Script Content field and save.
- For theme-level edits: go to Storefront → Themes → click 'Advanced' → Edit Theme Files, open 'templates/pages/custom/page.html' (or the relevant page template), and insert the script block.
- Validate with Google's Rich Results Test using the live page URL.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is your return policy?",
"acceptedAnswer": {
"@type": "Answer",
"text": "We accept returns within 30 days of purchase. Items must be unused and in their original packaging. Start a return by contacting our support team."
}
},
{
"@type": "Question",
"name": "How long does shipping take?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Standard shipping takes 5–7 business days. Expedited shipping options are available at checkout."
}
},
{
"@type": "Question",
"name": "Do you offer free shipping?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, free standard shipping is available on orders over $50 within the contiguous US."
}
}
]
}
</script>Paste this into Storefront → Script Manager as a Footer script scoped to your FAQ page, or inside the relevant page template HTML file.
Missing schema howtoModerate effort
Add HowTo structured data (JSON-LD) to any page that walks customers through a multi-step process, so Google can display your instructions as rich results in search.
On BigCommerce
- Go to Storefront > Script Manager in your BigCommerce admin.
- Click 'Create a Script', set Location to 'Footer', select the specific Page type ('Web Pages' for static pages or 'All Pages' with a conditional), and paste your complete JSON-LD HowTo script block into the script body.
- For blog posts, edit the specific blog post (Content > Blog), switch to HTML source view, and paste the <script type='application/ld+json'> block at the end of the post HTML.
- Alternatively, edit the relevant Stencil template file (e.g. templates/pages/blog-post.html) via Stencil CLI and inject the JSON-LD block inside the <head> partial.
- Validate the live URL with Google's Rich Results Test.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>How to Complete Your Task | Your Store</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to Complete Your Task",
"description": "Follow these steps to complete your task easily.",
"totalTime": "PT10M",
"step": [
{
"@type": "HowToStep",
"position": 1,
"name": "Prepare your materials",
"text": "Gather everything you need before you start: list materials here."
},
{
"@type": "HowToStep",
"position": 2,
"name": "Complete the main action",
"text": "Describe exactly what the user should do in this core step."
},
{
"@type": "HowToStep",
"position": 3,
"name": "Verify the result",
"text": "Explain how the user confirms the task was completed successfully."
}
]
}
</script>
</head>
<body>
<!-- Your how-to page content -->
</body>
</html>Place this block inside the <head> element of any static HTML page that contains step-by-step instructions.
Missing schema localbusinessQuick win
Add LocalBusiness JSON-LD structured data to your store so search engines and AI answer engines can surface your business name, address, phone number, and hours in rich results and direct answers.
On BigCommerce
- From your BigCommerce admin, go to Storefront → My Themes.
- Click 'Advanced' → 'Edit Theme Files' on your active theme.
- Open 'templates/layout/base.html' (or your base template file).
- Paste your JSON-LD <script> block just before the closing </head> tag.
- Click 'Save & Apply'. For homepage-only placement, edit 'templates/pages/home.html' instead.
- Validate with Google's Rich Results Test.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Your Store</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Store",
"name": "Your Business Name",
"url": "https://www.yourdomain.com",
"logo": "https://www.yourdomain.com/logo.png",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main Street",
"addressLocality": "Springfield",
"addressRegion": "IL",
"postalCode": "62701",
"addressCountry": "US"
},
"telephone": "+1-217-555-0100",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "09:00",
"closes": "18:00"
}
]
}
</script>
</head>
<body>
<!-- page content -->
</body>
</html>Paste this block anywhere inside the <head> element of your HTML page. Replace all placeholder values before deploying.
Missing schema organizationQuick win
Add an Organization schema markup block to your store's homepage (and/or sitewide template) so search engines and AI assistants can definitively identify your brand.
On BigCommerce
- In your BigCommerce admin, go to Storefront → Script Manager → Create a Script.
- Set Location to 'Head', Page to 'All Pages', Script type to 'Script'.
- Paste your complete <script type='application/ld+json'>…</script> Organization block into the script body field.
- Click Save. The script is now injected into the <head> of every page.
- Verify at the Rich Results Test using your store URL.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Acme Store",
"url": "https://www.acmestore.com",
"logo": {
"@type": "ImageObject",
"url": "https://www.acmestore.com/images/logo.png",
"width": 250,
"height": 250
},
"sameAs": [
"https://www.facebook.com/acmestore",
"https://www.instagram.com/acmestore",
"https://twitter.com/acmestore",
"https://www.linkedin.com/company/acmestore",
"https://www.youtube.com/c/acmestore"
],
"contactPoint": {
"@type": "ContactPoint",
"contactType": "customer service",
"email": "hello@acmestore.com"
}
}
</script>Drop this complete block inside your <head>…</head> section on every page. Replace all placeholder values.
Missing schema productModerate effort
Add Product schema markup (JSON-LD) to every product page so search engines can display rich results — including price, availability, and ratings — directly in search.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme.
- Open 'templates/pages/product.html' in the Stencil theme editor.
- Paste the JSON-LD schema block at the bottom of the file, using Handlebars variables: {{product.title}}, {{product.price.without_tax.value}}, {{product.sku}}, {{product.main_image.data}}, and set availability based on {{product.stock_level}}.
- Save and push the theme, then validate a live product URL in Google's Rich Results Test.
Missing schema webpageModerate effort
Add WebPage schema markup to every page so search engines and AI answer engines can precisely understand and describe your content.
On BigCommerce
- In your BigCommerce admin, go to Storefront → Themes → click 'Advanced' → Edit Theme Files on your active theme.
- Open the 'templates/layout/base.html' file (the global layout template used by Stencil themes).
- Paste your WebPage JSON-LD <script> block inside the <head> section of base.html.
- Use Handlebars variables to make it dynamic: {{settings.store_name}} for name, {{page.description}} for description, and {{urls.canonical}} or {{canonicalUrl}} for the url property (variable names may vary slightly by theme version).
- Save and push the theme. Validate a representative set of pages with the Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "About Us | Acme Store",
"description": "Learn about Acme Store, our mission, and the team behind our products.",
"url": "https://www.example.com/about/",
"inLanguage": "en-US",
"datePublished": "2022-01-15",
"dateModified": "2024-06-01",
"isPartOf": {
"@type": "WebSite",
"name": "Acme Store",
"url": "https://www.example.com/"
},
"breadcrumb": {
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://www.example.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "About Us",
"item": "https://www.example.com/about/"
}
]
}
}
</script>Paste this inside the <head> element of any HTML page. Replace all placeholder values with real page data.
Non iso dateQuick win
Change every datePublished (and dateModified) value in your structured data from a human-readable string to a strict ISO-8601 date — formatted as YYYY-MM-DD or YYYY-MM-DDThh:mm:ss+hh:mm — so search engines can reliably parse your content's freshness.
On BigCommerce
- Go to Storefront → My Themes → click 'Edit Theme Files' (Advanced) on your active theme.
- Open the Stencil template file where schema is output — commonly templates/pages/blog-post.html or templates/components/schema.html.
- Locate the date field. Stencil exposes a published_date object; use its iso8601 property: {{ blog.published_date.iso8601 }} which outputs a valid ISO-8601 string.
- If that property is unavailable in your theme version, use the datetime attribute pattern: {{ blog.published_date.datetime }}.
- For dateModified, use the same approach with the updated date helper if available, or set it equal to datePublished as a minimum.
- Save, push the theme, and validate with Google's Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Your Article Headline",
"datePublished": "2025-03-12",
"dateModified": "2025-03-12",
"author": {
"@type": "Person",
"name": "Author Name"
}
}
</script>Minimum viable JSON-LD block to paste into any HTML <head> — replace values with your own.
Org missing sameasQuick win
Add a `sameAs` array to your Organization schema, linking to your verified social profiles, Wikipedia page, LinkedIn, and other authoritative sources so search engines can confidently identify your brand as a known entity.
On BigCommerce
- From BigCommerce Admin, go to Storefront → My Themes → click Customize on your active theme → then Edit Theme Files (Advanced mode required).
- Open templates/layout/base.html (or your theme's equivalent master layout file).
- Paste the Organization JSON-LD block with sameAs just before the closing </head> tag.
- Save and apply. Preview your storefront and use View Page Source to confirm the schema is present.
- Validate with Google's Rich Results Test.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Your Brand Name",
"url": "https://www.yourdomain.com",
"logo": "https://www.yourdomain.com/images/logo.png",
"sameAs": [
"https://www.linkedin.com/company/your-company",
"https://www.facebook.com/yourpage",
"https://twitter.com/yourhandle",
"https://www.instagram.com/yourhandle",
"https://www.youtube.com/@yourchannel",
"https://en.wikipedia.org/wiki/Your_Brand",
"https://www.wikidata.org/wiki/QXXXXXXX"
]
}
</script>Paste this directly before the closing </head> tag in your HTML template. Remove any sameAs entries for platforms your brand does not have a presence on.
Page unreachableModerate effort
Ensure every page that should appear in AI-powered answers and rich results is actually reachable by crawlers, then add structured data so search engines and AI systems can read and surface its content.
On BigCommerce
- In the BigCommerce control panel, go to Storefront → Web Pages (or Products / Categories) and confirm the page is set to visible/active.
- For broken URLs, go to Server Settings → 301 Redirects to create redirects from old broken paths to correct live pages.
- Check Storefront → robots.txt — BigCommerce allows editing robots.txt under Storefront → robots.txt in newer versions. Remove any Disallow rules blocking important pages.
- For structured data, BigCommerce themes (Cornerstone) include basic Product schema by default. To extend it or add FAQPage schema, edit the relevant Handlebars template files in Storefront → My Themes → Edit Theme Files (e.g., templates/pages/product.html) and add a JSON-LD script block.
- Alternatively, use a third-party SEO app from the BigCommerce App Marketplace (e.g., 'StoreSEO') to manage schema without code edits.
- Submit the fixed URL in Google Search Console and confirm with the Rich Results Test.
Accessibility (WCAG) · 66 fixes
Aria allowed attrModerate effort
Audit every element that uses ARIA attributes and ensure each attribute is permitted for that element's role — removing or correcting any mismatched aria-* attributes.
On BigCommerce
- Go to Storefront → My Themes → click 'Edit Theme Files' for your active theme to open the Stencil file editor.
- Search template files (templates/components/, templates/layout/, and assets/js/) for the flagged aria-* attribute using the editor's search function.
- Correct the attribute in the relevant Handlebars (.html) or JavaScript file.
- If the violation originates from a widget added via Page Builder (Marketing → Page Builder), click the widget in the visual editor and look for an ARIA/accessibility field to correct, or remove the widget and recreate it without the bad attribute.
- Publish the theme and re-run your accessibility audit to confirm the fix.
<!-- WRONG: aria-checked is not allowed on role="button" -->
<div role="button" aria-checked="true">Toggle</div>
<!-- CORRECT option A: use a role that supports aria-checked -->
<div role="checkbox" aria-checked="true" tabindex="0">Toggle</div>
<!-- CORRECT option B: remove the unsupported attribute and use a native element -->
<button type="button" aria-pressed="true">Toggle</button>
<!-- WRONG: aria-expanded is not allowed on a <li> with no interactive role -->
<li aria-expanded="true">Menu Item</li>
<!-- CORRECT: put aria-expanded on the button that controls the submenu -->
<li>
<button type="button" aria-expanded="true" aria-controls="submenu-1">Menu Item</button>
<ul id="submenu-1">
<li><a href="/page">Sub-page</a></li>
</ul>
</li>
<!-- WRONG: aria-required on a <div> with no form-field role -->
<div aria-required="true">Enter your email</div>
<!-- CORRECT: aria-required belongs on the actual input, or use the native required attribute -->
<label for="email">Email <span aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" required aria-required="true" />Examples of invalid vs. corrected ARIA attribute usage for common patterns.
Aria allowed roleQuick win
Remove or replace any ARIA `role` attribute that is not permitted on the HTML element it is applied to — in particular, do not add `role="textbox"` (or other interactive roles) to elements that already have a native semantic role which conflicts with it.
On BigCommerce
- In the BigCommerce Control Panel, go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Search for the offending `role` attribute value across your Stencil Handlebars templates (`.html` files under `templates/`).
- Open the relevant template file and apply the fix: remove the invalid `role`, assign a permitted role, or use the correct native HTML element.
- Save the file, preview in a test environment, and re-audit with axe DevTools.
<!-- ❌ WRONG: role="textbox" is not permitted on <select> -->
<select role="textbox" name="country">
<option value="us">United States</option>
</select>
<!-- ✅ FIX A: Remove the invalid role — <select> already has the correct native semantics -->
<select name="country">
<option value="us">United States</option>
</select>
<!-- ❌ WRONG: role="textbox" on a <div> with no keyboard/input handling -->
<div role="textbox" class="fake-input">Enter your name</div>
<!-- ✅ FIX B: Replace with a real <input> element -->
<label for="name">Your name</label>
<input type="text" id="name" name="name" placeholder="Enter your name">
<!-- ❌ WRONG: role="textbox" on a <p> element -->
<p role="textbox">Some editable text</p>
<!-- ✅ FIX C: If you need an editable region, use contenteditable + the permitted role -->
<!-- role="textbox" IS permitted on elements with contenteditable, like a <div> -->
<div role="textbox"
contenteditable="true"
aria-multiline="false"
aria-label="Your name">
</div>Common patterns: wrong role on the left, correct fix on the right (as comments).
Aria command nameModerate effort
Give every button, link, and menuitem a clear, accessible name so screen readers can announce what it does.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (or download and edit locally via Stencil CLI).
- Navigate to the relevant Handlebars template — typically `templates/components/header/navigation.html`, `templates/components/cart/preview.html`, or `templates/components/common/mobile-menu-toggle.html`.
- Locate the `<button>`, `<a>`, or role-attributed element with no accessible name.
- Add `aria-label="Descriptive action name"` to the element tag, or add a `<span class="is-srOnly">Label</span>` inside it — BigCommerce Cornerstone theme ships with an `.is-srOnly` utility class for exactly this purpose.
- Save and push your changes; use the Stencil CLI `stencil start` to preview locally before pushing to production.
- Re-test using the axe browser extension.
<!-- OPTION 1: aria-label on an icon-only button -->
<button type="button" aria-label="Open cart">
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/>
<line x1="3" y1="6" x2="21" y2="6"/>
<path d="M16 10a4 4 0 01-8 0"/>
</svg>
</button>
<!-- OPTION 2: visually-hidden span inside the button -->
<button type="button">
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/>
</svg>
<span class="sr-only">Open cart</span>
</button>
<!-- OPTION 3: aria-labelledby pointing to existing visible text -->
<h2 id="cart-heading">Your Cart</h2>
<button type="button" aria-labelledby="cart-heading">View</button>
<!-- OPTION 4: icon-only link with aria-label -->
<a href="/cart" aria-label="View shopping cart">
<img src="cart-icon.svg" alt="" role="presentation" />
</a>Apply one of these patterns to any button, link, or menuitem that contains only an icon or image.
Aria dialog nameModerate effort
Add a visible or programmatic accessible name to every dialog element so screen readers can announce what the dialog is about when it opens.
On BigCommerce
- Go to Storefront → Themes → click Customize on your active theme, then switch to the Edit Theme Files tab (available in Stencil themes via the Theme Editor or locally via Stencil CLI).
- Search template files (templates/components/ and templates/pages/) for role="dialog" — common locations are the cart preview modal, search overlay, and age-gate popups.
- Add a unique id to the heading inside each dialog and add aria-labelledby="that-id" to the role="dialog" element, or add aria-label="[Dialog purpose]" if there is no heading.
- Commit and push changes if using Stencil CLI (stencil push), or save directly in the Theme Editor.
- Preview changes and test with the axe DevTools browser extension.
<!-- Preferred: point to the dialog's own heading -->
<div role="dialog" aria-modal="true" aria-labelledby="cart-dialog-title">
<h2 id="cart-dialog-title">Shopping Cart</h2>
<p>You have 3 items in your cart.</p>
<button type="button">Close</button>
</div>
<!-- Alternative: use aria-label when there is no visible heading -->
<div role="dialog" aria-modal="true" aria-label="Shopping Cart">
<p>You have 3 items in your cart.</p>
<button type="button">Close</button>
</div>Preferred method: aria-labelledby points to the dialog's own heading. Use this whenever a visible title exists inside the dialog.
Aria hidden focusModerate effort
Remove `aria-hidden="true"` from any element that contains focusable children (links, buttons, inputs), or remove those focusable children from the keyboard tab order so they cannot receive focus while hidden from assistive technology.
On BigCommerce
- Log in to your BigCommerce control panel and go to Storefront → My Themes → click Customize on your active theme to open Stencil.
- In the theme editor, use the 'Edit Theme Files' option (or download your theme via the BigCommerce CLI for local editing) and search all template files (.html) and JavaScript files for 'aria-hidden'.
- Common offenders in BigCommerce Cornerstone themes: the mobile navigation drawer (templates/components/common/mobile-menu.html and assets/js/theme/global/mobile-menu-toggle.js) and the quick-view modal.
- In the relevant JavaScript file that toggles the drawer or modal open/closed, add logic so that when the panel closes: container gets aria-hidden='true' AND all focusable children get tabindex='-1'; when it opens: remove aria-hidden and remove tabindex='-1'.
- Upload the corrected theme files or push via CLI (stencil push), then test with axe DevTools on your storefront preview.
Aria input field nameModerate effort
Add a descriptive accessible name (aria-label, aria-labelledby, or a visible <label>) to every ARIA input field so assistive technologies can identify it.
On BigCommerce
- In BigCommerce Admin, go to Storefront → Themes → click Customize on your active theme → click Advanced → Edit Theme Files (opens Stencil theme editor) or download the theme via the Theme Marketplace for local editing.
- Common problem files: templates/components/cart/item-quantity.html (cart quantity inputs), templates/components/search/quick-search.html (search bar).
- In item-quantity.html, locate the <input type="number"> and add aria-label="Quantity for {{name}}" using the available Handlebars context variable for product name.
- In quick-search.html, ensure the search <input> has aria-label="Search our store" or is wrapped in a <label>.
- Upload/save the modified theme files, preview the change, then publish the theme.
- Verify with axe DevTools browser extension on the live storefront.
<label for="customer-email">Email address</label>
<input type="email" id="customer-email" name="email" autocomplete="email">Option 1 (preferred): Visible label associated via 'for' + 'id'. Use this whenever a visible label fits the design.
Aria meter nameQuick win
Add a descriptive accessible name (via aria-label, aria-labelledby, or a visible <label>) to every element with role="meter" so screen readers can announce what the meter represents.
On BigCommerce
- Log in to BigCommerce admin and go to Storefront → My Themes → Advanced → Edit Theme Files (Stencil theme).
- Locate the Handlebars template containing the meter — commonly templates/components/products/rating.html or a custom component.
- Add aria-label="[Descriptive label]" to the element with role="meter", or use aria-labelledby pointing to an existing text element's id.
- Confirm aria-valuenow, aria-valuemin, and aria-valuemax are populated with the correct dynamic values (e.g., {{product.rating.average}}).
- Save, push the theme update, and verify with the axe DevTools browser extension on a live product page.
<!-- Option A: aria-label directly on the element -->
<meter
role="meter"
aria-label="Average customer rating"
aria-valuenow="3.8"
aria-valuemin="0"
aria-valuemax="5"
value="3.8"
min="0"
max="5">
3.8 out of 5
</meter>
<!-- Option B: aria-labelledby pointing to an existing visible element -->
<h3 id="rating-heading">Average customer rating</h3>
<meter
role="meter"
aria-labelledby="rating-heading"
aria-valuenow="3.8"
aria-valuemin="0"
aria-valuemax="5"
value="3.8"
min="0"
max="5">
3.8 out of 5
</meter>
<!-- Option C: visually hidden label for div-based meters -->
<span id="stock-label" class="visually-hidden">Items remaining in stock</span>
<div
role="meter"
aria-labelledby="stock-label"
aria-valuenow="4"
aria-valuemin="0"
aria-valuemax="20">
</div>
<!-- CSS for visually-hidden helper class -->
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>Place this markup wherever a meter widget is rendered. Replace attribute values with real content.
Aria progressbar nameQuick win
Add an accessible name (aria-label or aria-labelledby) to every progress bar element so screen readers can announce its purpose.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Search the Stencil theme files for 'progressbar', '<progress', 'role="progressbar"' — common locations include templates/components/products/rating.html, templates/pages/cart.html, and templates/components/account/.
- Add aria-label='Descriptive label' to each progress bar element's opening tag.
- If the bar is in a Handlebars partial, add the label within that partial. Example: <meter class='rating-meter' aria-label='Average product rating' value='{{product.rating}}' min='0' max='5'>.
- For script-injected progress bars (e.g. from a BigCommerce widget or third-party app), add a small JavaScript block in Storefront → Script Manager that targets the element and sets the aria-label attribute.
- Save, preview, and verify with the axe DevTools extension.
<!-- Option 1: aria-label (no visible label on page) -->
<div
role="progressbar"
aria-label="Checkout step progress"
aria-valuenow="2"
aria-valuemin="1"
aria-valuemax="4"
style="width: 50%; height: 8px; background: #4caf50;"
></div>
<!-- Option 2: aria-labelledby (visible label already exists on page) -->
<h2 id="progress-heading">Order Progress</h2>
<div
role="progressbar"
aria-labelledby="progress-heading"
aria-valuenow="60"
aria-valuemin="0"
aria-valuemax="100"
style="width: 60%; height: 8px; background: #4caf50;"
></div>
<!-- Option 3: Native <progress> element with <label> -->
<label for="file-upload-progress">File upload progress</label>
<progress id="file-upload-progress" value="70" max="100">70%</progress>Use aria-label when there is no visible label text on the page.
Aria prohibited attrModerate effort
Remove or replace any ARIA attributes that are prohibited for the role assigned to each HTML element, so assistive technologies receive accurate, unambiguous information.
On BigCommerce
- In the BigCommerce Control Panel, go to Storefront → My Themes → click Customize on your active theme → click the Advanced tab → Edit Theme Files.
- Navigate to the relevant Handlebars (.html) template — e.g. templates/components/products/card.html or templates/layout/base.html.
- Search for the prohibited ARIA attribute and correct or remove it.
- Save the file; use Stencil CLI locally for a faster edit-test loop if you have developer access.
- Retest on the live storefront using the axe browser extension.
<!-- ❌ WRONG: aria-checked is prohibited on role='heading' -->
<div role="heading" aria-level="2" aria-checked="false">Product Title</div>
<!-- ✅ CORRECT: remove the prohibited aria-checked attribute -->
<div role="heading" aria-level="2">Product Title</div>
<!-- ❌ WRONG: aria-label is prohibited on role='none' / role='presentation' -->
<div role="none" aria-label="Decorative banner"></div>
<!-- ✅ CORRECT: role='none' means purely decorative — remove all ARIA attributes -->
<div role="none"></div>
<!-- ❌ WRONG: aria-expanded is prohibited on a static <p> (implicit role='paragraph') -->
<p aria-expanded="true">Read more about our returns policy.</p>
<!-- ✅ CORRECT: move aria-expanded to the interactive control that actually toggles content -->
<button aria-expanded="true" aria-controls="returns-detail">Read more about our returns policy</button>
<div id="returns-detail">Full returns policy text here.</div>
<!-- ❌ WRONG: aria-required is prohibited on a <div role='alert'> -->
<div role="alert" aria-required="true">Please fill in all fields.</div>
<!-- ✅ CORRECT: remove aria-required; it belongs only on form inputs -->
<div role="alert">Please fill in all fields.</div>Examples of prohibited-attribute violations and their correct fixes.
Aria required attrModerate effort
Add all required ARIA attributes (such as aria-expanded and aria-controls) to every interactive element that uses an ARIA role, so assistive technologies can communicate widget state to users.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Locate the Handlebars template responsible for the widget — typically templates/components/header/navigation.html for nav dropdowns or templates/components/search/quick-search.html for the search combobox.
- Add aria-expanded='false' and aria-controls='target-id' to the trigger element in the template markup.
- Open assets/js/theme/ and find the matching JavaScript module (e.g. header.js or search.js). In the toggle handler, add: this.$trigger.attr('aria-expanded', isOpen ? 'true' : 'false');
- Bundle and preview the theme changes, then verify with the axe browser extension.
<!-- Trigger button (e.g. accordion header or dropdown toggle) -->
<button
id="section1-toggle"
aria-expanded="false"
aria-controls="section1-panel"
>
Product Details
</button>
<!-- Controlled panel -->
<div
id="section1-panel"
role="region"
aria-labelledby="section1-toggle"
hidden
>
<p>Panel content goes here.</p>
</div>
<script>
const toggle = document.getElementById('section1-toggle');
const panel = document.getElementById('section1-panel');
toggle.addEventListener('click', function () {
const isExpanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', String(!isExpanded));
panel.hidden = isExpanded;
});
</script>Place on any trigger element that opens/closes a collapsible section. Update aria-expanded via JS on each toggle.
Aria required childrenModerate effort
Add the required child ARIA roles (e.g. `role="option"` inside `role="listbox"`, or `role="group"`/`role="option"` inside `role="combobox"`) so every composite ARIA widget contains the child roles the ARIA specification demands.
On BigCommerce
- In your BigCommerce Control Panel go to Storefront → Themes → click Customise on your active theme → Open in Editor (Stencil theme editor), or download the theme ZIP for local editing.
- Locate the Handlebars template responsible for the broken widget — common files: templates/components/products/product-view.hbs (variant pickers), templates/components/faceted-search/ (filters), templates/layout/base.hbs (navigation).
- Add the missing ARIA child roles directly to the Handlebars markup (e.g. role="option" on each <option>-equivalent child element).
- Upload the modified theme or push via Stencil CLI (stencil push), then activate it.
- Use the axe DevTools extension on your live or preview URL to verify the fix.
Aria required parentModerate effort
Wrap every ARIA role that requires a parent container (e.g. `menuitem`, `option`, `listitem`) inside the correct parent element carrying the matching ARIA role (e.g. `menu`/`menubar`, `listbox`, `list`).
On BigCommerce
- In your BigCommerce Control Panel, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' for your active theme.
- Locate the Handlebars template responsible for the affected component — typically 'templates/components/common/navigation.html' or a header partial.
- Wrap the child-role elements in the correct parent role element (e.g. add `<ul role='menu'>` around `<li role='menuitem'>` items).
- Save changes and use 'Preview' to test, then run the axe browser extension to verify the fix before publishing.
<!-- INCORRECT: menuitem with no required parent -->
<nav>
<a href="/shop" role="menuitem">Shop</a>
<a href="/about" role="menuitem">About</a>
<a href="/contact" role="menuitem">Contact</a>
</nav>
<!-- CORRECT: menuitem children wrapped in role="menubar" -->
<nav>
<ul role="menubar">
<li role="none"><a href="/shop" role="menuitem">Shop</a></li>
<li role="none"><a href="/about" role="menuitem">About</a></li>
<li role="none"><a href="/contact" role="menuitem">Contact</a></li>
</ul>
</nav>
<!-- CORRECT: option children wrapped in role="listbox" -->
<div role="listbox" aria-label="Select a size">
<div role="option" aria-selected="false">Small</div>
<div role="option" aria-selected="true">Medium</div>
<div role="option" aria-selected="false">Large</div>
</div>
<!-- CORRECT: tab children wrapped in role="tablist" -->
<div role="tablist" aria-label="Product details">
<button role="tab" aria-selected="true" aria-controls="panel-desc">Description</button>
<button role="tab" aria-selected="false" aria-controls="panel-reviews">Reviews</button>
</div>
<div id="panel-desc" role="tabpanel">Description content here.</div>
<div id="panel-reviews" role="tabpanel" hidden>Reviews content here.</div>Correct pattern: child roles (menuitem) wrapped in the required parent role (menu/menubar). Apply the same principle to other role pairs.
Aria rolesQuick win
Audit every element that has a `role` attribute and replace any invalid or misspelled role value with a valid WAI-ARIA role from the official specification.
On BigCommerce
- In BigCommerce Admin, go to Storefront → Themes → click Customize on your active theme, then Advanced → Edit Theme Files.
- Use the file browser to search template files (`.html` Handlebars templates) for `role=` — check `templates/layout/base.html`, `templates/components/`, and `templates/pages/`.
- Correct the invalid role value in the appropriate file and save.
- For Stencil CLI users: edit the same files locally in your theme directory, then run `stencil push` to deploy.
- If the issue is in a BigCommerce widget or app, update the widget HTML in Page Builder (Content → Page Builder) or contact the app vendor.
- Preview and re-run axe to confirm the fix.
<!-- INVALID: typo -->
<!-- <div role="buton">Add to Cart</div> -->
<!-- FIXED: correct spelling -->
<div role="button" tabindex="0">Add to Cart</div>
<!-- BETTER: use native HTML instead of ARIA role wherever possible -->
<button type="button">Add to Cart</button>
<!-- INVALID: invented role -->
<!-- <section role="product-card"> -->
<!-- FIXED: remove non-existent role; let native <section> semantics apply -->
<section aria-label="Product card">
<!-- INVALID: abstract/structural-only role used on a concrete element -->
<!-- <ul role="list widget"> -->
<!-- FIXED: 'list' is valid; 'widget' is abstract and not allowed -->
<ul role="list">
<!-- INVALID: deprecated presentational role used incorrectly -->
<!-- <img role="presentation" alt="Red sneaker"> -->
<!-- FIXED: use role="presentation" only for decorative images with empty alt -->
<img role="presentation" alt="">Replace invalid or misspelled role values with the correct WAI-ARIA role. Examples of common corrections:
Aria toggle field nameQuick win
Add a visible or programmatic accessible name to every toggle control (checkbox, switch, or button with role="switch") so screen readers can announce what the control does.
On BigCommerce
- Log in to your BigCommerce control panel, go to Storefront → My Themes, and click Advanced → Edit Theme Files on your active theme.
- In the Stencil theme file editor, search templates/components/ and templates/layout/ for checkbox inputs, role="switch", or custom toggle HTML.
- For standard checkboxes (e.g. product option checkboxes in templates/components/products/options/), add a <label for="INPUT_ID"> or wrap both elements in a <label>.
- For icon-only toggle buttons (e.g. mobile menu close, wishlist heart icon), open the relevant Handlebars (.html) partial and add aria-label="Description" to the <button> element.
- Save and apply the theme changes, then use BigCommerce's Preview mode to verify before pushing to live.
- Run the axe DevTools extension on a live preview URL to confirm all toggles now report an accessible name.
<!-- PATTERN 1: Wrap input + label text in a <label> element (simplest) -->
<label>
<input type="checkbox" name="newsletter"> Subscribe to newsletter
</label>
<!-- PATTERN 2: Link a separate <label> to an input via for/id -->
<input type="checkbox" id="dark-mode" name="dark-mode">
<label for="dark-mode">Enable dark mode</label>
<!-- PATTERN 3: Icon-only toggle button — use aria-label -->
<button type="button" aria-label="Enable dark mode" aria-pressed="false">
<!-- SVG or icon here; the button has no visible text -->
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</button>
<!-- PATTERN 4: Custom div/span switch with role="switch" -->
<div role="switch" tabindex="0" aria-checked="false" aria-label="Receive marketing emails">
<span class="switch-track"></span>
</div>Three correct patterns for labelling toggle controls in plain HTML.
Aria tooltip nameModerate effort
Give every tooltip element an accessible name so screen readers can announce its content to users who cannot see the screen.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Search Handlebars (.html) templates and any custom JS files for role="tooltip".
- Add descriptive inner text to the tooltip element, or add an aria-label attribute directly on the element with a plain-language description.
- If tooltips are injected by a third-party widget script (e.g., a review or chat app), contact the vendor or override the output via Storefront → Script Manager by appending a small JS snippet that sets element.setAttribute('aria-label', 'Your description') on DOMContentLoaded.
- Use BigCommerce's built-in Preview mode and run the axe browser extension to verify the fix.
(function () {
'use strict';
document.addEventListener('DOMContentLoaded', function () {
var tooltips = document.querySelectorAll('[role="tooltip"]');
tooltips.forEach(function (tip) {
// Only patch tooltips that have no accessible name
var hasLabel = tip.getAttribute('aria-label') ||
tip.getAttribute('aria-labelledby') ||
tip.textContent.trim();
if (!hasLabel) {
// Attempt to derive a name from a nearby data attribute set by your theme
var derivedLabel = tip.dataset.tooltipLabel || 'Additional information';
tip.setAttribute('aria-label', derivedLabel);
}
});
});
}());Add this script via Storefront > Script Manager (footer, all pages) as a stopgap while template fixes are in progress.
Aria valid attrQuick win
Find and replace every misspelled or non-existent ARIA attribute name (e.g. `aria-labeledby`) with the correct, spec-defined name (e.g. `aria-labelledby`) across your entire site's HTML and templates.
On BigCommerce
- In your BigCommerce admin, go to Storefront → Themes → (your active theme) → Advanced → Edit Theme Files.
- Use the search functionality or download the theme as a ZIP file and open it in a code editor (VS Code) to run a global search for the misspelled attribute (e.g. `aria-labeledby`).
- Locate the relevant template files (commonly in `templates/components/`, `templates/layout/`, or `templates/pages/`) and correct the attribute name.
- If using Stencil CLI locally, run a global find-and-replace, then `stencil push` to deploy the corrected theme.
- For issues inside a third-party widget or script injected via Script Manager (Storefront → Script Manager), edit the script directly in the Script Manager editor.
- After deploying, verify using the axe DevTools browser extension on a live storefront page.
<!-- WRONG: aria-labeledby is not a valid ARIA attribute (one 'l' is a typo) -->
<input type="search" aria-labeledby="search-heading">
<!-- CORRECT: aria-labelledby (double 'l') is the valid ARIA attribute -->
<input type="search" aria-labelledby="search-heading">
<h2 id="search-heading">Search our store</h2>
<!-- Other common invalid → valid corrections:
aria-role → role (not an ARIA attribute at all; 'role' is a plain HTML attribute)
aria-labeledby → aria-labelledby
aria-describeby → aria-describedby
aria-owns-id → aria-owns
-->Before/after comparison showing the most common misspelling corrected. Apply the same principle to any other invalid ARIA attribute name.
Aria valid attr valueModerate effort
Audit every ARIA attribute on your pages and correct any that have invalid or mismatched values so assistive technologies can interpret them correctly.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme.
- Locate the relevant Handlebars template (`.html` files under `templates/components/` or `templates/pages/`) that renders the flagged element.
- Search for the ARIA attribute name and correct its value.
- If the issue is inside a widget placed via Page Builder, go to the storefront Page Builder, select the widget, and edit its HTML/custom code field.
- Commit your changes and preview the storefront, then verify with the axe DevTools browser extension.
<!-- WRONG: aria-expanded with a number instead of boolean string -->
<button aria-expanded="1">Menu</button>
<!-- CORRECT: must be exactly the string "true" or "false" -->
<button aria-expanded="false">Menu</button>
<!-- WRONG: aria-describedby pointing to an ID that doesn't exist -->
<input type="email" aria-describedby="email-hint" />
<!-- (no element with id="email-hint" on the page) -->
<!-- CORRECT: the referenced element must exist in the DOM -->
<input type="email" aria-describedby="email-hint" />
<p id="email-hint">We'll never share your email with anyone.</p>
<!-- WRONG: aria-checked with a non-standard value -->
<div role="checkbox" aria-checked="yes">Subscribe</div>
<!-- CORRECT: aria-checked accepts "true", "false", or "mixed" -->
<div role="checkbox" aria-checked="false">Subscribe</div>
<!-- WRONG: aria-hidden with an invalid value -->
<span aria-hidden="hidden">decorative icon</span>
<!-- CORRECT: aria-hidden accepts only "true" or "false" -->
<span aria-hidden="true">decorative icon</span>Correct examples for the most commonly mis-valued ARIA attributes. Copy the pattern that matches your flagged element.
Autocomplete validModerate effort
Add valid `autocomplete` attribute values to every form field that collects personal information, using the exact tokens specified by the HTML standard.
On BigCommerce
- Go to Storefront → My Themes → Advanced → Edit Theme Files (Stencil theme editor).
- For the checkout, BigCommerce uses an optimised one-page checkout rendered by its platform; it already includes standard autocomplete tokens. For customised checkouts using the Checkout SDK, edit your custom checkout component files.
- For account and contact forms, open the relevant Handlebars template files such as `templates/pages/auth/login.html`, `templates/pages/auth/create-account.html`, or `templates/pages/account/edit.html`.
- Find each `<input>` element and add the correct `autocomplete` attribute.
- Download, edit, and re-upload the theme bundle, or use the Stencil CLI for live editing.
- Preview the theme and validate with an axe browser extension before publishing.
<!-- Name fields -->
<input type="text" name="fname" autocomplete="given-name" />
<input type="text" name="lname" autocomplete="family-name" />
<input type="text" name="fullname" autocomplete="name" />
<!-- Contact fields -->
<input type="email" name="email" autocomplete="email" />
<input type="tel" name="phone" autocomplete="tel" />
<!-- Address fields (shipping) -->
<input type="text" name="address1" autocomplete="shipping address-line1" />
<input type="text" name="address2" autocomplete="shipping address-line2" />
<input type="text" name="city" autocomplete="shipping address-level2" />
<input type="text" name="state" autocomplete="shipping address-level1" />
<input type="text" name="zip" autocomplete="shipping postal-code" />
<select name="country" autocomplete="shipping country"></select>
<!-- Address fields (billing) -->
<input type="text" name="billing_address1" autocomplete="billing address-line1" />
<input type="text" name="billing_zip" autocomplete="billing postal-code" />
<!-- Payment fields -->
<input type="text" name="ccname" autocomplete="cc-name" />
<input type="text" name="ccnumber" autocomplete="cc-number" />
<input type="text" name="ccexp" autocomplete="cc-exp" />
<input type="text" name="cvc" autocomplete="cc-csc" />
<!-- Account fields -->
<input type="email" name="login_email" autocomplete="email" />
<input type="password" name="current_pass" autocomplete="current-password" />
<input type="password" name="new_pass" autocomplete="new-password" />
<input type="text" name="otp" autocomplete="one-time-code" />Apply these autocomplete tokens to the matching input fields in any HTML form.
Avoid inline spacingModerate effort
Remove hard-coded text-spacing CSS values from inline `style` attributes so users can override them with their own stylesheets or browser settings.
On BigCommerce
- Go to Storefront → My Themes → click Customize on your active theme → click Advanced → Edit Theme Files (opens the Stencil file editor).
- Search template files (e.g. `templates/pages/product.html`, `templates/components/`) for `style=` attributes containing spacing properties.
- Open the theme's main SCSS/CSS file (typically `assets/scss/`) and define a new class with the spacing values.
- Replace the inline `style` attributes in the templates with the new class.
- Alternatively, use Storefront → My Themes → Customize → Page Builder and remove any inline spacing set in the visual editor's typography options, then define those values in the custom CSS field under Storefront → Script Manager or the theme's custom CSS section.
- Preview and run an axe scan to verify.
<!-- BEFORE (fails WCAG 1.4.12 — inline style blocks user overrides) -->
<p style="line-height: 1.6; letter-spacing: 0.05em; word-spacing: 0.1em;">
Product description text here.
</p>
<!-- AFTER (passes — spacing is in a stylesheet class) -->
<p class="product-description">
Product description text here.
</p>
<!-- In your <head> or external .css file -->
<style>
.product-description {
line-height: 1.6;
letter-spacing: 0.05em;
word-spacing: 0.1em;
}
</style>Before: inline style locks spacing. After: class-based style allows user overrides.
Button nameModerate effort
Add a descriptive, screen-reader-accessible name to every button on your site so assistive technology users know what each button does.
On BigCommerce
- In BigCommerce Admin, go to Storefront → My Themes → click Customize on your active theme → then Advanced → Edit Theme Files (opens the Stencil theme editor / WebDAV access).
- Locate the Handlebars template files containing offending buttons. Common locations: templates/components/common/header.html (nav/cart/search icons), templates/components/products/add-to-cart.html (product buttons), templates/components/carousel/ (slider arrows).
- Add aria-label attributes to icon-only <button> elements in these templates.
- If you use Page Builder widgets, edit the widget's HTML in Storefront → Page Builder, select the element containing the button, switch to HTML/Custom Code view, and add the aria-label there.
- Commit and push changes via Stencil CLI (stencil push) or save via the Theme Editor, then test with a screen reader.
- Re-run an accessibility scan (e.g. axe DevTools browser extension) to confirm the button-name violations are resolved.
<!-- PATTERN 1: Icon-only button — add aria-label directly on the button -->
<button type="button" aria-label="Open search">
<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24">
<path d="M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z"
stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
</button>
<!-- PATTERN 2: Button with an <img> icon — give the img a descriptive alt -->
<button type="button">
<img src="/icons/cart.svg" alt="View shopping cart" width="24" height="24">
</button>
<!-- PATTERN 3: Button labelled by visible text elsewhere on the page -->
<h2 id="newsletter-heading">Subscribe to our newsletter</h2>
<!-- ... form fields ... -->
<button type="submit" aria-labelledby="newsletter-heading">Subscribe</button>
<!-- PATTERN 4: Visible text button — just ensure the text is real HTML text -->
<button type="button">Add to Cart</button>
<!-- PATTERN 5: Quantity stepper buttons -->
<button type="button" aria-label="Decrease quantity">−</button>
<input type="number" value="1" aria-label="Product quantity">
<button type="button" aria-label="Increase quantity">+</button>Use one of these patterns depending on your button's content. Apply the correct pattern to every icon-only or ambiguous button on your site.
Color contrastQuick win
Increase the contrast ratio between your text color and its background color to meet the WCAG 4.5:1 minimum, so all users — including those with low vision — can read your content clearly.
On BigCommerce
- Go to Storefront → Themes → click Customize on your active theme.
- In the Style panel, find Typography or Colors. Look for 'Body text color' or 'Secondary text color' and update it to an accessible hex value.
- If the color is not exposed there, click Advanced → Edit Theme Files (or use the Stencil CLI locally).
- Open assets/scss/settings/ — look for _color.scss or a variables file. Search for the failing color and replace it.
- Commit/push changes (Stencil CLI) or Save in the file editor, then publish the theme.
/* BEFORE (fails WCAG 1.4.3 — ratio 4.47:1 on white) */
.secondary-text {
color: #777777;
}
/* AFTER (passes WCAG 1.4.3 — ratio ~7.0:1 on white) */
.secondary-text {
color: #595959;
}Replace the failing color with one that achieves 4.5:1+ contrast on white (#ffffff). #595959 achieves ~7.0:1 on white.
Definition listModerate effort
Ensure every `<dl>` (definition list) element contains only properly nested `<dt>` and `<dd>` children, with no stray text, divs, or other elements placed directly inside it.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click Customize on your active theme, then choose Edit Theme Files (or use the Stencil CLI for local development).
- Search your Handlebars templates (.html files under templates/components/ and templates/pages/) for `<dl`.
- Common locations: templates/components/products/product-view.html (product specs), templates/pages/order-confirmation.html.
- Edit the Handlebars template directly to correct the `<dl>` structure, then save and apply.
- Preview and validate with the axe browser extension.
<!-- ✅ CORRECT: only <dt> and <dd> as direct children -->
<dl>
<dt>Material</dt>
<dd>100% Organic Cotton</dd>
<dt>Weight</dt>
<dd>180 GSM</dd>
<dt>Care Instructions</dt>
<dd>Machine wash cold</dd>
<dd>Tumble dry low</dd>
</dl>
<!-- ✅ ALSO CORRECT: <div> wrappers for layout/styling -->
<dl>
<div>
<dt>Material</dt>
<dd>100% Organic Cotton</dd>
</div>
<div>
<dt>Weight</dt>
<dd>180 GSM</dd>
</div>
</dl>
<!-- ❌ WRONG: stray <p>, <span>, or plain text directly inside <dl> -->
<!-- <dl>
<p>Product Details</p>
<dt>Material</dt>
<dd>Cotton</dd>
</dl> -->Correct `<dl>` structure — use this pattern for all product specs, FAQs, and paired term/value content.
DlitemModerate effort
Wrap every `<dt>` (term) and `<dd>` (description) element inside a parent `<dl>` element so description list items have their required container.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil).
- Use the search functionality to look for `<dt` or `<dd` across all Handlebars (.html) template files, particularly in templates/components/products/ and templates/pages/.
- Identify any `<dt>` or `<dd>` not nested inside a `<dl>` and add the missing `<dl>` wrapper.
- Save changes and use BigCommerce's live preview to verify the rendered HTML structure using browser DevTools.
- If the issue is in a custom widget, go to Page Builder, find the widget, and edit its HTML template or custom HTML block directly.
<!-- CORRECT: dt and dd are direct children of dl -->
<dl>
<dt>Shipping time</dt>
<dd>3–5 business days</dd>
<dt>Return policy</dt>
<dd>30-day free returns</dd>
<dt>Material</dt>
<dd>100% organic cotton</dd>
</dl>
<!-- ALSO CORRECT: grouping pairs with div inside dl (HTML5 spec allows this) -->
<dl>
<div>
<dt>Shipping time</dt>
<dd>3–5 business days</dd>
</div>
<div>
<dt>Return policy</dt>
<dd>30-day free returns</dd>
</div>
</dl>
<!-- INCORRECT — do NOT do this: dt/dd outside a dl -->
<!-- <div>
<dt>Shipping time</dt>
<dd>3–5 business days</dd>
</div> -->The correct structure: every <dt> and <dd> must be a direct child of a <dl> element.
Document titleQuick win
Add a descriptive, non-empty `<title>` element to every page so browsers, screen readers, and search engines can identify it.
On BigCommerce
- For the homepage: Admin → Marketing → SEO & Analytics → 'Page title' under 'Home Page SEO'.
- For product pages: Catalog → Products → select a product → 'SEO' tab → 'Page title' field.
- For category pages: Catalog → Categories → select a category → 'SEO' tab → 'Page title'.
- For standard pages: Storefront → Web Pages → select page → 'SEO' tab → 'Page title'.
- To fix the title at the template level: Storefront → My Themes → Advanced → Edit Theme Files → open `templates/layout/base.html` → confirm `<title>{{head.title}}</title>` is inside `<head>`.
<title>{{head.title}}</title>In templates/layout/base.html inside <head>. The Handlebars variable {{head.title}} is populated by BigCommerce from each page's SEO title field.
Empty headingQuick win
Find every empty heading tag on your store and add visible, descriptive text (or remove the tag entirely) so screen readers and search engines can interpret your page structure.
On BigCommerce
- In your BigCommerce Control Panel, go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Use the file search to locate Handlebars template files (`.html` under `templates/`) containing empty heading tags.
- Add literal text or a template variable inside the tag, e.g. `<h2>{{category.name}}</h2>`.
- Wrap dynamic headings in a Handlebars conditional to avoid rendering an empty tag: `{{#if category.name}}<h2>{{category.name}}</h2>{{/if}}`.
- For Page Builder content (Storefront → Pages → Edit → Page Builder): click the Heading widget, type visible text in the Content field, or delete unused heading widgets.
- Save and preview; validate with the axe browser extension.
{{!-- Only render h2 when category.name is non-empty --}}
{{#if category.name}}
<h2 class="page-heading">{{category.name}}</h2>
{{/if}}Handlebars conditional in a Stencil template file (e.g. templates/pages/category.html) to skip the heading when the variable is empty.
Empty table headerQuick win
Add visible or screen-reader-accessible text to every empty `<th>` table header cell so assistive technology users can understand what each column or row represents.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → click Customize on your active theme, then open the Theme Editor. For code-level edits, click Advanced → Edit Theme Files.
- Browse to templates/components/ and templates/pages/ — look for files containing `<table>` markup (e.g., product-comparison.html, account-orders.html).
- Search for empty `<th>` elements and add descriptive text or `aria-label` attributes.
- If comparison or spec tables are rendered by a BigCommerce widget, go to Page Builder (Storefront → Page Builder) and edit the widget's HTML/Text block directly.
- Save changes and verify with the axe DevTools browser extension.
<!-- OPTION 1: Add visible text (best for most cases) -->
<table>
<thead>
<tr>
<th>Feature</th>
<th>Basic Plan</th>
<th>Pro Plan</th>
</tr>
</thead>
<tbody>
<tr>
<td>Storage</td>
<td>5 GB</td>
<td>50 GB</td>
</tr>
</tbody>
</table>
<!-- OPTION 2: Visually hidden text (for top-left corner cells) -->
<style>
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<table>
<thead>
<tr>
<th><span class="sr-only">Feature name</span></th>
<th>Basic Plan</th>
<th>Pro Plan</th>
</tr>
</thead>
</table>
<!-- OPTION 3: aria-label directly on the th element -->
<table>
<thead>
<tr>
<th aria-label="Feature name"></th>
<th>Basic Plan</th>
<th>Pro Plan</th>
</tr>
</thead>
</table>Option 1 — visible text in the header cell (preferred). Option 2 — visually hidden text via a span. Option 3 — aria-label on the th element.
Error not associatedModerate effort
Add `aria-invalid="true"` and a linked `aria-describedby` error message to every form field that fails validation, so screen reader users are told exactly what went wrong.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → click 'Edit Theme' (Stencil) or use the Theme Files editor.
- Locate the relevant Handlebars templates: templates/components/common/forms/ contains reusable form partials; checkout fields live in templates/pages/checkout/ or are handled by the Optimized One-Page Checkout.
- In each form partial, add id="FIELDNAME-error" error span elements adjacent to inputs, and add aria-describedby="FIELDNAME-error" to the input tags.
- In your theme's JavaScript (assets/js/theme/ directory), extend the validation logic (often in utils/form-utils.js or a page-specific file) to set aria-invalid and toggle the error span's hidden state.
- For the Optimized One-Page Checkout (which is a React app BigCommerce controls), use the Checkout SDK or Checkout Customization scripts injected via Script Manager (Storefront → Script Manager) to patch ARIA attributes after React renders the fields.
- Save, push your Stencil theme, and test with a screen reader.
<div class="field-wrapper">
<label for="user-email">Email address <span aria-hidden="true">*</span></label>
<input
type="email"
id="user-email"
name="email"
autocomplete="email"
aria-required="true"
aria-describedby="user-email-error"
/>
<span
id="user-email-error"
class="field-error"
role="alert"
hidden
></span>
</div>Place this markup in any HTML form. The error span is always in the DOM; JS toggles visibility and sets aria-invalid.
Focus not visibleQuick win
Add a clearly visible focus indicator to every interactive element so keyboard users can always see which element is currently selected.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → click Customize on the active theme → click Advanced → Edit Theme Files.
- Open assets/scss/components/base/_base.scss (Cornerstone theme) or the equivalent main CSS/SCSS file. Search for 'outline'.
- Delete or override any `outline: none` rules, then add the focus styles below.
- If you are not on the Stencil framework, go to Storefront → Script Manager and inject a small `<style>` tag with the focus CSS, or add it to the custom footer script.
- Save and preview the theme, then tab through the storefront to verify.
/* --- Visible focus indicator fix (WCAG 2.4.7) --- */
*:focus-visible {
outline: 3px solid #005FCC;
outline-offset: 2px;
border-radius: 2px;
}
*:focus {
outline: 3px solid #005FCC;
outline-offset: 2px;
}
*:focus:not(:focus-visible) {
outline: none;
}Add to assets/scss/components/base/_base.scss in the Stencil theme, or paste into Storefront → Script Manager as an inline <style> in the head.
Frame titleQuick win
Add a descriptive `title` attribute to every `<iframe>` and `<frame>` element on your store so screen-reader users know what each embedded frame contains before entering it.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click Customize on your active theme → choose Edit Theme Files (or Advanced → Edit Theme Files in older panels).
- Use the file search to locate '<iframe' across all .html and .js template files (templates/layout/, templates/pages/, templates/components/).
- Add title="…" to each iframe and save / push changes.
- For iframes injected by third-party BigCommerce apps, check each app's configuration in Apps → My Apps for an accessibility or title setting. If unavailable, add a JavaScript fix via Storefront → Script Manager — create a new script that runs on 'All Pages' and sets the iframe title attribute after the DOM loads.
<!-- Good: descriptive title -->
<iframe
src="https://www.google.com/maps/embed?pb=..."
title="Google Map showing our store location at 123 Main St"
width="600"
height="450"
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
></iframe>
<!-- Good: product video embed -->
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="Product demo video: how to use the XYZ Widget"
width="560"
height="315"
allowfullscreen
></iframe>
<!-- Good: decorative / empty frame — hide from assistive tech -->
<iframe
src="blank.html"
title=""
aria-hidden="true"
tabindex="-1"
></iframe>Add a descriptive title attribute directly to any iframe element.
Heading orderModerate effort
Restructure your page headings so they follow a logical, sequential order (H1 → H2 → H3) with no levels skipped.
On BigCommerce
- Go to Storefront → Themes → click 'Edit Theme Files' (Blueprint) or 'Advanced → Edit Theme Files' (Cornerstone) for your active theme.
- Open the relevant template file — for example, templates/pages/category.html for category pages or templates/pages/product.html for product pages — and locate heading tags.
- Change any out-of-order heading tags (e.g., an <h4> that should be an <h2>) to the correct semantic level, keeping CSS classes intact so visual styling is unchanged.
- For content blocks edited in the Page Builder (Marketing → Page Builder), click any Text or Banner widget that contains a heading and use the heading-level selector in the rich-text toolbar to assign the correct level.
- Use the HeadingsMap browser extension to verify the heading outline on each major page template after saving changes.
<!-- ONE H1 per page: the primary page title -->
<h1>Women's Running Shoes</h1>
<!-- H2 for major page sections -->
<h2>Filter by Category</h2>
<!-- H3 for sub-sections within an H2 -->
<h3>Shoe Type</h3>
<h3>Brand</h3>
<h2>Featured Products</h2>
<!-- H3 for individual product titles within the H2 section -->
<h3>UltraRun Pro 5</h3>
<h3>TrailBlaze X2</h3>
<h2>Customer Reviews</h2>
<h3>Top Rated This Month</h3>
<!-- H4 for sub-items within an H3 — only go deeper when content genuinely nests -->
<h4>Review by Sarah M.</h4>
<h4>Review by James T.</h4>Correct heading hierarchy pattern for a typical ecommerce product or category page.
Html has langQuick win
Add a valid `lang` attribute to the `<html>` element so browsers, screen readers, and search engines know what language your page is written in.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes.
- Click Customize on your active theme, then in the Theme Editor click Advanced → Edit Theme Files (or download the theme, edit locally, and re-upload).
- Open templates/layout/base.html (the path may vary slightly by theme — look for the file containing the `<html>` tag).
- Add or correct the `lang` attribute: `<html lang="en">` (replace `en` with your store's primary language code).
- Save and upload, then verify via View Source on your storefront.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{head.title}}</title>
{{{head.scripts}}}
</head>
<body>
{{{snippet.header}}}
{{{page.html}}}
{{{snippet.footer}}}
</body>
</html>Place this in templates/layout/base.html in your BigCommerce theme. Replace 'en' with your store's primary language code.
Html lang validQuick win
Add a valid BCP 47 language code to the `lang` attribute on your site's `<html>` element so browsers and assistive technologies know what language your content is written in.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes.
- Click 'Advanced' → 'Edit Theme Files' on your active theme (or download the theme to edit locally).
- Open 'templates/layout/base.html' (the main HTML layout file for Stencil themes).
- Locate the opening `<html` tag. Update it to include the correct `lang` attribute, e.g. `<html lang="en">`. For multilingual stores using a translation app, check the app's documentation for its dynamic language variable.
- Save and upload the updated theme, then publish it and verify via page source.
<!DOCTYPE html>
<html lang="en">
<head>
{{{head.title}}}
{{{stylesheet '/assets/css/theme.css'}}}
{{{head.scripts}}}
</head>
<body>
{{{snippet 'header'}}}
{{{page}}}
{{{snippet 'footer'}}}
</body>
</html>In templates/layout/base.html of your Stencil theme, update the <html> tag with a hardcoded or app-provided language code.
Image altModerate effort
Add descriptive alt text to every meaningful image, and mark purely decorative images with an empty alt attribute or role="presentation".
On BigCommerce
- Product images: Admin → Catalog → Products → [Product name] → Images & Videos tab → hover over an image thumbnail and click the pencil/edit icon → fill in the 'Alt Text' field → Save.
- Banner images (via Marketing → Banners): alt text for banners is set in the HTML source — click the HTML editor icon in the banner editor and add alt="..." to the <img> tag.
- Theme images: Storefront → Themes → Advanced → Edit Theme Files → locate the relevant template (.html) and add or correct the alt attribute on <img> tags.
- Page Builder widgets: When adding an image widget in the Page Builder (Storefront → My Themes → Customize), look for an 'Alt Text' field in the widget's right-hand panel.
<!-- Meaningful image: describe the content -->
<img src="red-leather-bag.jpg" alt="Red leather crossbody bag with gold clasp" width="600" height="400">
<!-- Image used as a link: describe the destination/action -->
<a href="/sale">
<img src="summer-sale-banner.jpg" alt="Shop our summer sale — up to 40% off">
</a>
<!-- Decorative image: empty alt, screen readers skip it -->
<img src="decorative-swoosh.svg" alt="" role="presentation">
<!-- WRONG — never omit alt entirely on an <img> -->
<!-- <img src="product.jpg"> -->
<!-- WRONG — never use filename or generic words -->
<!-- <img src="IMG_4821.jpg" alt="image"> -->Correct patterns for meaningful, linked, and decorative images.
Image redundant altQuick win
Remove or clear the alt text on images whose description is already provided by visible text immediately surrounding them, so screen readers don't read the same information twice.
On BigCommerce
- Go to Storefront → My Themes → click 'Edit Theme' (Stencil CLI) or use the Page Builder for supported blocks.
- For product card images, open templates/components/products/card.html in your Stencil theme via Stencil CLI or the built-in editor.
- Find the <img> tag inside the product card anchor. If the card also renders the product name as visible text in the same anchor or card, change the alt attribute to alt="" (an empty string).
- For the product detail page, open templates/pages/product.html and apply the same change to the main product image <img> tag if the product name h1 is in close proximity.
- Run stencil bundle and push the theme update, or save via the editor. Clear the CDN cache if applicable.
- Verify with axe DevTools browser extension on a live product and category page.
<!-- CORRECT: image inside a link that also has visible text -->
<a href="/products/red-sneakers">
<img src="red-sneakers.jpg" alt="" width="300" height="300">
<span>Red Sneakers</span>
</a>
<!-- INCORRECT: alt repeats the visible link text -->
<a href="/products/red-sneakers">
<img src="red-sneakers.jpg" alt="Red Sneakers" width="300" height="300">
<span>Red Sneakers</span>
</a>
<!-- INCORRECT: alt attribute missing entirely (screen reader reads filename) -->
<a href="/products/red-sneakers">
<img src="red-sneakers.jpg" width="300" height="300">
<span>Red Sneakers</span>
</a>Use alt="" (empty string) when the image is inside or adjacent to visible text that already describes it. Never omit the alt attribute entirely.
Input button nameQuick win
Add a visible label or accessible name to every input button so assistive technologies can announce what the button does.
On BigCommerce
- In your BigCommerce control panel go to Storefront → Themes → click Customize on your active theme, then click Advanced → Edit Theme Files (or use the Stencil CLI locally).
- Search Handlebars template files (`.html` under `templates/`) for `input type="submit"` or `input type="button"` with an empty value attribute.
- Common files: `templates/components/cart/cart.html`, `templates/components/common/header.html`, and `templates/pages/checkout.html`.
- Add a descriptive `value` attribute (e.g. `value="Proceed to Checkout"`) to every flagged element, or add `aria-label="..."` if the button must stay visually bare.
- Push the updated theme and preview on a staging URL before publishing.
<!-- CORRECT: Submit button with descriptive value -->
<input type="submit" value="Place Order">
<!-- CORRECT: Button with descriptive value -->
<input type="button" value="Add to Cart">
<!-- CORRECT: Reset button with descriptive value -->
<input type="reset" value="Clear Form">
<!-- CORRECT: Icon-only button — use aria-label when no visible text is possible -->
<input type="submit" value="" aria-label="Search products">
<!-- WRONG: Empty value — screen readers cannot announce purpose -->
<!-- <input type="submit" value=""> -->Use a descriptive value attribute on every input button type. Never leave value empty.
Input image altQuick win
Add a descriptive `alt` attribute to every `<input type="image">` element so screen readers can announce its purpose to visually impaired shoppers.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click Customize on your active theme → Edit Theme Files (Advanced).
- Search the Stencil template files (`.html` files under `templates/`) for `type="image"`.
- Add `alt="[descriptive action text]"` to each matching `<input>` tag and save.
- If the button is part of a payment widget injected via the Optimized One-Page Checkout, go to Store Setup → Payments and check if the provider's SDK supplies its own alt text; if not, contact BigCommerce support or the payment provider.
- Publish the theme change and test with the axe browser extension on your live storefront.
<!-- BEFORE (broken): -->
<input type="image" src="buy-now.png">
<!-- AFTER (fixed): -->
<input type="image" src="buy-now.png" alt="Buy now">
<!-- Search button example: -->
<input type="image" src="search-icon.png" alt="Search products">
<!-- Custom checkout submit example: -->
<input type="image" src="checkout-btn.png" alt="Proceed to checkout">Replace the `alt` value with a short, action-oriented description of what the button does.
LabelQuick win
Add a visible or programmatic label to every form input so assistive technologies can identify it for users.
On BigCommerce
- Go to Storefront → Themes → Advanced → Edit Theme Files (Stencil CLI is recommended for larger edits).
- Open the relevant Handlebars template — search form is in `templates/components/common/header.html` or `templates/components/search/...`; contact form in `templates/pages/contact-us.html`; newsletter in `templates/components/common/subscribe.html`.
- Add a `<label for='input-id'>Description</label>` before the target `<input>`, and add `id='input-id'` to the input. For icon-only inputs add `aria-label='...'` on the input itself.
- Push the changes via Stencil CLI (`stencil push`) or save via the online editor, then verify.
<!-- Method 1: Explicit label (recommended) -->
<label for="user-email">Email address</label>
<input type="email" id="user-email" name="email" autocomplete="email">
<!-- Method 2: Implicit (wrapped) label -->
<label>
Email address
<input type="email" name="email" autocomplete="email">
</label>
<!-- Method 3: aria-label (use when no visible label is desired, e.g. icon-only search) -->
<input type="search" name="q" aria-label="Search products">
<!-- Method 4: aria-labelledby (point to existing visible text on the page) -->
<h2 id="newsletter-heading">Subscribe to our newsletter</h2>
<input type="email" name="subscribe" aria-labelledby="newsletter-heading">
<!-- Visually hidden label (visible to screen readers, hidden on screen) -->
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<label for="search-input" class="visually-hidden">Search products</label>
<input type="search" id="search-input" name="q" placeholder="Search...">Preferred method: explicit label linked by for/id. Place immediately before the input.
Label title onlyModerate effort
Add a visible text label to every form field so it is not labeled only by a hidden tooltip (title attribute) or supplementary description (aria-describedby).
On BigCommerce
- Go to Storefront → Themes → Advanced → Edit Theme Files (in the Stencil theme editor, or download the theme for local editing via the BigCommerce CLI).
- Locate templates/components/search/search-form.html for the search box, and templates/components/cart/item-quantity.html for quantity inputs.
- Add a <label for='search_query'>Search</label> paired with id='search_query' on the input, or add aria-label='Search' to the input if the design requires no visible label.
- For checkout fields, BigCommerce's Optimized One-Page Checkout is hosted — open a support ticket or use the Checkout SDK / Checkout JS SDK customization to inject labels, or configure a third-party checkout that is WCAG-compliant.
- Re-upload / push the theme and verify in the storefront using axe DevTools.
<!-- CORRECT: Visible label paired to input -->
<div class="form-field">
<label for="customer-email">Email address</label>
<input
type="email"
id="customer-email"
name="email"
autocomplete="email"
/>
</div>
<!-- CORRECT: Visually-hidden label (readable by screen readers, invisible to sighted users) -->
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<div class="form-field">
<label for="site-search" class="visually-hidden">Search the store</label>
<input
type="search"
id="site-search"
name="q"
placeholder="Search..."
/>
</div>
<!-- CORRECT: aria-label as alternative when no <label> element is possible -->
<input
type="search"
name="q"
aria-label="Search the store"
placeholder="Search..."
/>
<!-- WRONG: title only — do NOT rely on this -->
<!-- <input type="search" name="q" title="Search the store" /> -->
<!-- WRONG: placeholder only — do NOT rely on this -->
<!-- <input type="email" name="email" placeholder="Email address" /> -->The correct pattern: a visible <label> paired to an input via matching for/id attributes.
Landmark banner is top levelModerate effort
Move your site's `<header>` element (or `role="banner"` landmark) so it is a direct child of `<body>`, not nested inside another landmark region.
On BigCommerce
- Go to Storefront → My Themes → click Customize on your active theme → select Edit Theme Files (Advanced).
- Open templates/layout/base.html (Stencil theme).
- Find the `<header>` element and confirm it is a direct child of `<body>`. It must appear before `<main id="main-content">`.
- If it is nested inside another landmark, cut and paste it to the correct position.
- Save and push the theme, then verify with axe DevTools.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Store</title>
</head>
<body>
<!-- CORRECT: <header> is a direct child of <body> -->
<header>
<a href="/"><img src="/logo.svg" alt="My Store home"></a>
<nav aria-label="Primary">
<ul>
<li><a href="/shop">Shop</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<!-- page content here -->
</main>
<footer>
<!-- footer content here -->
</footer>
</body>
</html>Correct top-level structure: <header> is a direct child of <body>, not nested in any landmark.
Landmark complementary is top levelModerate effort
Move your <aside> element (or role="complementary") to the top level of the page so it is not nested inside another landmark region.
On BigCommerce
- In your BigCommerce admin, go to Storefront → Themes → click 'Advanced' → Edit Theme Files (Stencil CLI recommended for safety).
- Locate the Handlebars template where the sidebar renders — commonly `templates/components/common/sidebar.html` or inside a page template like `templates/pages/product.html` or `templates/pages/category.html`.
- Find the `<aside>` block. If it is nested inside `{{{region name="main"}}}` or a `<main>` element, cut it out and paste it as a sibling of the `<main>` block in the same parent template.
- Ensure the parent wrapper `<div>` contains `<main>` and `<aside>` as siblings, then apply a two-column CSS layout (Flexbox/Grid) in `assets/scss/` to restore the visual appearance.
- Add `aria-label="Sidebar"` or a descriptive label to the `<aside>` tag.
- Bundle and upload the theme, preview on a staging URL, and validate with the axe browser extension.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Page Title</title>
</head>
<body>
<header>
<nav aria-label="Main navigation">
<!-- navigation links -->
</nav>
</header>
<!-- Correct: <main> and <aside> are siblings, both top-level landmarks -->
<div class="page-layout">
<main id="main-content">
<!-- primary page content -->
</main>
<aside aria-label="Related products">
<!-- complementary / sidebar content -->
</aside>
</div>
<footer>
<!-- footer content -->
</footer>
</body>
</html>Correct top-level landmark structure — <aside> is a sibling of <main>, both direct children of the page wrapper.
Landmark contentinfo is top levelQuick win
Move your site's footer element (or role="contentinfo") so it is a direct child of the page body, not nested inside another landmark region.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' for your active theme (Stencil).
- Open 'templates/layout/base.html' (the master layout file).
- Find the <footer> tag. Check whether it is inside a <main> element or any other landmark. In a correctly structured Stencil theme, <footer> should appear after </main>.
- If the <footer> is nested inside <main> or another landmark, cut the entire footer block and paste it after the </main> closing tag, as a direct child of <body>.
- Save and push the theme, then verify with the axe DevTools extension in your browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Store Page</title>
</head>
<body>
<header>
<!-- Site logo, main navigation -->
</header>
<nav aria-label="Main navigation">
<!-- Primary nav links -->
</nav>
<main>
<!-- All primary page content goes here -->
<h1>Page Title</h1>
<p>Page content...</p>
</main>
<!-- CORRECT: <footer> is a direct child of <body>, after </main> -->
<footer>
<p>© 2024 My Store. All rights reserved.</p>
<nav aria-label="Footer navigation">
<a href="/privacy">Privacy Policy</a>
<a href="/contact">Contact</a>
</nav>
</footer>
</body>
</html>Correct top-level landmark structure — <footer> is a direct child of <body>, not nested inside <main> or any other landmark.
Landmark main is top levelQuick win
Move the `<main>` element (or `role="main"`) so it is a direct child of `<body>`, not nested inside any other landmark element such as `<header>`, `<nav>`, `<aside>`, or `<footer>`.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → click 'Advanced' → Edit Theme Files (for Stencil themes).
- Open 'templates/layout/base.html' — this is the master HTML shell.
- Search for `<main` or `role="main"`.
- Check if it is wrapped by a `<header>` or other landmark-tagged element. If so, move the `<main>` opening tag to sit directly after the closing `</header>` tag at the top-level of `<body>`.
- Ensure the closing `</main>` tag appears before the opening `<footer>` tag.
- Push changes, clear the CDN cache, and validate with an axe browser extension.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Store</title>
</head>
<body>
<header>
<nav aria-label="Primary navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/shop">Shop</a></li>
</ul>
</nav>
</header>
<!-- CORRECT: <main> is a direct child of <body>, NOT inside <header> or any other landmark -->
<main id="main-content">
<h1>Welcome to My Store</h1>
<p>Browse our latest products below.</p>
</main>
<footer>
<p>© 2024 My Store</p>
</footer>
</body>
</html>Correct top-level landmark structure — <main> is a direct child of <body>, sibling to <header> and <footer>.
Landmark no duplicate bannerModerate effort
Ensure your page has only one banner landmark (one `<header>` or `role="banner"` element that is not nested inside another landmark), so screen reader users can navigate your site reliably.
On BigCommerce
- Go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil).
- Open 'templates/layout/base.html' (or 'templates/layout/default.html') — locate the top-level `<header>` element.
- Search all template files under 'templates/' for any additional `<header` or `role="banner"` occurrences.
- Secondary headers inside product or category content regions should use `<div>` instead of `<header>`.
- If a Widget or Page Builder block is adding a header element, edit the block's HTML in Page Builder (Storefront → Page Builder) and change the tag.
- Save and publish, then re-run your accessibility scan.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Store Page</title>
</head>
<body>
<!-- CORRECT: Single top-level <header> = one banner landmark -->
<header>
<a href="/"><img src="logo.svg" alt="Acme Store"></a>
<nav aria-label="Main navigation">
<ul>
<li><a href="/shop">Shop</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<article>
<!-- CORRECT: <header> nested inside <article> is NOT a banner landmark -->
<header>
<h1>Product Name</h1>
<p>Posted: <time datetime="2024-01-01">January 1, 2024</time></p>
</header>
<p>Product description goes here.</p>
</article>
<!-- CORRECT: promotional strip uses <div>, not <header> -->
<div class="promo-bar" role="region" aria-label="Promotional offer">
<p>Free shipping on orders over $50!</p>
</div>
</main>
<footer>
<p>© 2024 Acme Store</p>
</footer>
</body>
</html>Correct page structure: one top-level <header> as the banner, inner content sections use <div> or are wrapped in a sectioning element.
Landmark no duplicate contentinfoModerate effort
Ensure your page has only one footer/contentinfo landmark by removing or re-marking any duplicate `<footer>` elements or `role="contentinfo"` attributes.
On BigCommerce
- Go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil).
- Open templates/layout/base.html. Locate the single <footer> element near the bottom — this is your primary contentinfo landmark.
- Search the templates/ directory for any additional <footer> tags or role="contentinfo" attributes using the theme editor search or by downloading the theme ZIP and searching locally.
- Change any secondary <footer> elements to <div role="complementary" aria-label="[descriptive name]"> or simply <div>.
- For third-party scripts injecting a duplicate footer, go to Storefront → Script Manager, locate the relevant script, and edit it to remove or replace the <footer> or role="contentinfo" in its HTML output.
- Upload the corrected theme and run axe DevTools to confirm the fix.
<!-- CORRECT: One site-wide footer landmark -->
<body>
<header><!-- site header --></header>
<main><!-- page content --></main>
<!-- Secondary informational section — NOT a footer landmark -->
<div class="promo-bar" aria-label="Promotional offers">
<p>Free shipping on orders over $50!</p>
</div>
<!-- The ONE true contentinfo landmark -->
<footer>
<nav aria-label="Footer navigation">
<ul>
<li><a href="/privacy">Privacy Policy</a></li>
<li><a href="/terms">Terms of Service</a></li>
<li><a href="/contact">Contact Us</a></li>
</ul>
</nav>
<p>© 2024 My Store. All rights reserved.</p>
</footer>
</body>Correct pattern: exactly one top-level <footer> per page. Any secondary footer-like section uses <div> with a descriptive aria-label.
Landmark no duplicate mainQuick win
Find and remove every duplicate `<main>` element or `role="main"` attribute so that exactly one main landmark exists on each page.
On BigCommerce
- Go to Storefront → Themes → Advanced → Edit Theme Files (Stencil CLI) or use the in-browser editor for Blueprint themes.
- In Stencil themes open templates/layout/base.html and search for '<main' and 'role="main"'. Only one should exist, wrapping '{{> region name="main"}}'.
- Check templates/components/common/header.html and footer.html for stray '<main>' tags or 'role="main"' attributes; replace with '<div>' where needed.
- Re-bundle and push the theme (stencil push) then verify with DevTools or the axe extension on the live storefront.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Page Title</title>
</head>
<body>
<header>
<nav aria-label="Primary navigation">
<!-- site-wide navigation -->
</nav>
</header>
<!-- ✅ Only ONE <main> element per page -->
<main id="main-content">
<h1>Page Heading</h1>
<!-- primary page content goes here -->
</main>
<footer>
<!-- footer content -->
</footer>
</body>
</html>Correct page structure: exactly one <main> element wrapping the primary content, with header and footer outside it.
Landmark one mainQuick win
Add a single `<main>` landmark element (or `role="main"`) to every page so assistive technologies can identify and navigate directly to the primary content.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → click Advance → Edit Theme Files (or download your theme for local editing).
- Open `templates/layout/base.html` — this is the master template equivalent.
- Find the wrapper around `{{content}}` (often `<div class="container">` or `<div id="page-wrapper">`). Change the opening tag to `<main id="page-content">` and the closing to `</main>`.
- Ensure any 'Skip to content' link in the header targets `#page-content`.
- Upload/save the file, then publish the theme and verify with the axe extension.
<!-- Skip link at the very top of <body> -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<header><!-- site header / nav here --></header>
<main id="main-content">
<!-- ALL primary page content goes here:
product details, blog post, category grid, etc. -->
</main>
<footer><!-- site footer here --></footer>Place this landmark element around all unique page content, after the <header> and <nav> and before the <footer>. Use exactly one per page.
Landmark uniqueModerate effort
Add a unique aria-label (or aria-labelledby) to every repeated landmark role on the page so screen-reader users can tell them apart.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → Themes → (your active theme) → Advanced → Edit Theme Files (or use the Stencil CLI locally).
- Navigate to templates/layout/base.html for the global wrapper, and templates/components/ for reusable partials such as header.html, footer.html, and navigation.html.
- Find every <nav>, <aside>, <section>, and <header> tag that appears more than once across the rendered page.
- Add a unique aria-label to each, e.g. <nav aria-label='Main navigation'>, <nav aria-label='Breadcrumb'>, <nav aria-label='Footer links'>.
- Save (or push via Stencil CLI: stencil push), then publish the updated theme and verify with the axe browser extension.
<!-- BEFORE: two <nav> elements with no label — screen readers can't tell them apart -->
<nav>
<ul><!-- main menu items --></ul>
</nav>
<nav>
<ul><!-- footer links --></ul>
</nav>
<!-- AFTER: each <nav> has a unique aria-label -->
<nav aria-label="Main navigation">
<ul><!-- main menu items --></ul>
</nav>
<nav aria-label="Footer navigation">
<ul><!-- footer links --></ul>
</nav>
<!-- Alternative: use aria-labelledby when a visible heading already exists -->
<section aria-labelledby="filters-heading">
<h2 id="filters-heading">Product Filters</h2>
<!-- filter controls -->
</section>
<section aria-labelledby="recommendations-heading">
<h2 id="recommendations-heading">You May Also Like</h2>
<!-- recommended products -->
</section>Apply unique aria-label attributes to every repeated landmark element. Use aria-labelledby when a visible heading already labels the region.
Link in text blockQuick win
Increase the color contrast between inline links and their surrounding body text to at least 3:1, or add a non-color visual distinction (such as underline) so links are identifiable without relying on color alone.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → click Customize on your active theme.
- Open Style Editor: look for a 'Links' or 'Typography' section and update the link color swatch to a compliant color.
- For direct CSS control, click Advanced → Edit Theme Files (requires developer/partner access) and open assets/scss/components/_links.scss or assets/css/theme.css.
- Add or update: a { color: #YOUR_NEW_COLOR; text-decoration: underline; }
- Save and push the theme, then verify visually on a product description or blog post page.
/* Option A: Change link color to one with ≥3:1 contrast against body text
AND ≥4.5:1 contrast against the page background.
Example: body text #3f3f3f on white background — #0057d8 passes both thresholds. */
a {
color: #0057d8;
}
/* Option B: Keep your existing link color but add a non-color visual cue.
An underline satisfies WCAG 1.4.1 without requiring the 3:1 color contrast. */
a {
text-decoration: underline;
}
/* Best practice: combine both for maximum clarity */
a {
color: #0057d8;
text-decoration: underline;
}
/* If you want to scope this to body/content areas only: */
.content a,
.entry-content a,
article a,
p a {
color: #0057d8;
text-decoration: underline;
}Add to your global stylesheet. Option A changes link color; Option B restores underline. Use both for strongest compliance.
Link nameQuick win
Add a descriptive, screen-reader-accessible text label to every link on your store so assistive technology can announce its purpose.
On BigCommerce
- Go to BigCommerce Admin → Storefront → My Themes → click 'Edit Theme Files' (or download the theme via 'Download' and edit locally, then re-upload).
- Common files: templates/components/common/header.html (cart/search icon links), templates/components/common/footer.html (social links), templates/components/products/card.html (product card links).
- For icon links, add aria-label to the anchor: <a href='{{urls.cart}}' aria-label='View shopping cart'>.
- For product card image links, add aria-label='View {{product.name}}' to the wrapping <a> around the product image.
- Save and publish the theme, then test using the WAVE browser extension on your live storefront preview.
ListModerate effort
Fix all HTML lists so that only valid child elements appear directly inside `<ul>` and `<ol>` tags, and only `<ul>` or `<ol>` elements wrap `<li>` items.
On BigCommerce
- In BigCommerce Admin, go to Storefront → My Themes → click Customize on your active theme → select Edit Theme Files (Advanced).
- Open templates/components/header.html and templates/components/navigation/ — locate the nav `<ul>` blocks and ensure only `<li>` elements are direct children.
- Open templates/components/footer.html and repeat the check for footer link lists.
- For category/product pages, check templates/pages/category.html and templates/pages/product.html for any custom list markup.
- Stencil CLI users: make changes locally in the appropriate Handlebars template files, then run `stencil push` to deploy.
- Re-test with axe after pushing the theme update.
<!-- CORRECT: <ul> or <ol> with only <li> children -->
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item
<!-- CORRECT: nested list lives INSIDE an <li> -->
<ul>
<li>Nested item A</li>
<li>Nested item B</li>
</ul>
</li>
</ul>
<!-- WRONG: <div> as a direct child of <ul> -->
<!-- <ul>
<div>This breaks the list</div>
<li>Item</li>
</ul> -->
<!-- WRONG: <li> with no list parent -->
<!-- <li>Orphaned item</li> -->Correct list structure — all platforms. Use this as a reference for what valid markup looks like.
ListitemModerate effort
Ensure every `<li>` element is a direct child of a `<ul>` or `<ol>` element (or an element explicitly given `role="list"`), so that screen readers can correctly announce list structure to users.
On BigCommerce
- In your BigCommerce admin go to Storefront → My Themes → click Customize on your active theme → Edit Theme Files (or download the theme and edit locally).
- Locate the Handlebars (.html) template file responsible for the broken list — common files are `templates/layout/base.html`, `templates/components/header.html`, `templates/components/footer.html`, or a product/category partial.
- Find the `<li>` element. If its parent is a `<div>` or other non-list element, wrap all sibling `<li>` tags in `<ul>...</ul>` (or `<ol>` if ordered).
- If navigation is generated by the Stencil framework's `{{navigation}}` helper, override the navigation component in your theme's components directory and correct the HTML structure there.
- Upload/save the theme, then use the BigCommerce preview URL to verify. Run axe DevTools in the browser to confirm the fix.
<!-- CORRECT: unordered list -->
<ul>
<li>Free shipping on orders over $50</li>
<li>30-day returns</li>
<li>2-year warranty</li>
</ul>
<!-- CORRECT: ordered list (e.g. steps) -->
<ol>
<li>Add item to cart</li>
<li>Enter shipping address</li>
<li>Complete payment</li>
</ol>
<!-- CORRECT: list inside a <nav> (navigation pattern) -->
<nav aria-label="Main navigation">
<ul>
<li><a href="/shop">Shop</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
<!-- WRONG: <li> inside a <div> — do NOT do this -->
<!--
<div>
<li>Item one</li>
<li>Item two</li>
</div>
-->
<!-- LAST RESORT only: if the parent HTML tag truly cannot be changed,
add role="list" to the parent element -->
<div role="list">
<div role="listitem">Item one</div>
<div role="listitem">Item two</div>
</div>Correct structure: every <li> must be a direct child of <ul> or <ol>.
Meta refreshQuick win
Remove or disable the `<meta http-equiv="refresh">` tag that forces an automatic page reload, or replace any redirect use-case with a server-side redirect instead.
On BigCommerce
- Go to Storefront → My Themes → click Customize on your active theme → then Edit Theme Files (requires the Stencil CLI or the in-browser editor).
- Open `templates/layout/base.html` (Stencil themes) and search for `http-equiv`. Remove the matching `<meta>` tag.
- If the tag is not in the layout file, search all template and partial files for `refresh`.
- For redirects, use BigCommerce's built-in redirect manager: Server Settings → 301 Redirects (or via the API) — never use meta-refresh for redirects.
- Save, publish the theme, and re-scan the affected page.
<!-- REMOVE — self-refresh every 30 seconds (WCAG fail) -->
<!-- <meta http-equiv="refresh" content="30"> -->
<!-- REMOVE — redirect to another URL after 5 seconds (WCAG fail) -->
<!-- <meta http-equiv="refresh" content="5; url=https://example.com/new-page"> -->
<!-- ALLOWED — 0-second instant redirect (no time limit imposed on user) -->
<!-- Only use this as a fallback alongside a server-side redirect -->
<meta http-equiv="refresh" content="0; url=https://example.com/new-page">REMOVE this tag from your page's <head>. Both forms below are problematic (self-refresh and timed redirect).
Meta viewportQuick win
Remove `user-scalable=no` (and any `maximum-scale` below 5) from your site's `<meta name="viewport">` tag so visitors can pinch-to-zoom on mobile devices.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes.
- Click Customize on your active theme, then select Edit Theme Files (Advanced).
- In the file tree, open templates/layout/base.html (the path may vary by theme — look for the file containing <head>).
- Search for 'viewport' and remove `user-scalable=no` / fix `maximum-scale`.
- Click Save & Apply to push the change live.
<meta name="viewport" content="width=device-width, initial-scale=1">Place this in the <head> of every HTML page. This is the correct, accessibility-compliant viewport tag.
Meta viewport largeQuick win
Remove or raise the `maximum-scale` value in your meta viewport tag so users can pinch-zoom on mobile devices.
On BigCommerce
- In your BigCommerce Control Panel, go to Storefront → My Themes.
- Click 'Advanced' → 'Edit Theme Files' on your active theme, OR download the theme, edit locally, and re-upload.
- Open 'templates/layout/base.html' (the path may vary slightly by theme).
- Search for 'viewport' and update the <meta name="viewport"> tag to remove zoom restrictions.
- Save or re-upload the theme and apply it.
<meta name="viewport" content="width=device-width, initial-scale=1">Replace any existing <meta name="viewport"> tag in your <head> with this. Omitting maximum-scale and user-scalable entirely is the safest, most accessible choice.
Nested interactiveModerate effort
Remove or restructure nested interactive elements so that no focusable control (button, link, input, etc.) is placed inside another interactive control, and never rely on tabindex="-1" or aria-hidden="true" to hide an inner interactive element from assistive technologies.
On BigCommerce
- In your BigCommerce admin, go to Storefront → Themes → your active theme → Advanced → Edit Theme Files (Stencil CLI or Page Builder).
- Open the Handlebars template file for the affected component — common files: templates/components/products/card.html, templates/components/cart/item.html, templates/layout/base.html.
- Search for nested interactive patterns and refactor: replace the inner or outer interactive tag with a non-interactive `<span>` or `<div>`, keeping only one focusable control per action.
- Save and push the updated theme. Preview the storefront and test with Tab-key navigation to confirm only one interactive element is focused per action.
<!-- ❌ WRONG: button nested inside a link (invalid HTML, unpredictable in screen readers) -->
<a href="/products/widget">
<button type="button">View Product</button>
</a>
<!-- ✅ CORRECT: single interactive element styled as a button -->
<a href="/products/widget" class="btn btn-primary">View Product</a>
<!-- ❌ WRONG: link nested inside a button -->
<button type="button">
<a href="/cart">Add to Cart</a>
</button>
<!-- ✅ CORRECT: use only the element that matches the action -->
<!-- If it navigates → use <a>; if it performs an action on the page → use <button> -->
<a href="/cart" class="btn btn-primary">Add to Cart</a>
<!-- ❌ WRONG: relying on tabindex or aria-hidden to suppress inner element -->
<a href="/products/widget">
<button type="button" tabindex="-1" aria-hidden="true">View Product</button>
</a>
<!-- ✅ CORRECT: icons and decorative content inside interactive elements must be non-interactive -->
<button type="button">
<svg aria-hidden="true" focusable="false" width="20" height="20">
<use href="#icon-cart"></use>
</svg>
<span>Add to Cart</span>
</button>The WRONG pattern and the correct fix side by side.
Object altQuick win
Add a meaningful text alternative (via `title` attribute or `aria-label`) to every `<object>` element so screen readers can describe its content to users who cannot see it.
On BigCommerce
- In the BigCommerce Control Panel, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' for your active theme.
- Browse to the relevant template file (e.g., templates/pages/product.html or a custom partial) and locate the <object> element.
- Add `title='Descriptive label here'` to the opening <object> tag.
- If the <object> appears in a page built with the Page Builder (Content → Web Pages), edit that page, find the HTML widget containing the <object>, and add the `title` attribute in the HTML source view.
- Save and publish, then verify using the axe DevTools browser extension on the live or preview URL.
<!-- BEFORE (fails accessibility check) -->
<object data="product-catalog.pdf" type="application/pdf" width="600" height="400">
<p>Your browser does not support PDFs.</p>
</object>
<!-- AFTER: Option 1 — title attribute (preferred for <object>) -->
<object
data="product-catalog.pdf"
type="application/pdf"
width="600"
height="400"
title="Winter 2024 Product Catalog (PDF)">
<p>Your browser does not support PDFs.
<a href="product-catalog.pdf">Download the catalog</a>.
</p>
</object>
<!-- AFTER: Option 2 — aria-label (acceptable alternative) -->
<object
data="product-catalog.pdf"
type="application/pdf"
width="600"
height="400"
aria-label="Winter 2024 Product Catalog (PDF)">
<p>Your browser does not support PDFs.
<a href="product-catalog.pdf">Download the catalog</a>.
</p>
</object>
<!-- AFTER: Option 3 — purely decorative, hide from AT -->
<object
data="decorative-animation.svg"
type="image/svg+xml"
width="200"
height="200"
aria-hidden="true">
</object>Add a `title` attribute to any <object> element — this is the primary fix. Use aria-label as an alternative if ARIA is already in use on the element.
Page has heading oneQuick win
Add a single, descriptive `<h1>` heading to every page so assistive technologies and search engines can identify the page's main topic.
On BigCommerce
- Go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' for your active theme.
- For product pages: open templates/pages/product.html and locate the product name output — ensure it is wrapped in <h1 class='productView-title'>{{product.title}}</h1>.
- For standard content pages (About, Contact): go to Storefront → Web Pages, open the page, and in the rich-text editor highlight the page title and select 'Heading 1' from the format dropdown.
- For the homepage: edit templates/pages/home.html or the relevant carousel/banner widget via Page Builder (Storefront → My Theme → Customize) — change text widgets that represent the main heading to use the H1 element.
- Save and preview each page, then confirm with the axe browser extension.
<main>
<h1>Women's Running Shoes</h1>
<!-- rest of page content -->
</main>Place this after your site navigation, as the first element inside <main>. Style it with CSS as needed — the visual size is independent of the semantic tag.
Presentation role conflictModerate effort
Remove conflicting ARIA attributes (global ARIA properties and tabindex) from any element that has been marked as purely presentational with role="presentation" or role="none".
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click Customize on your active theme → Advanced → Edit Theme Files.
- Search for role="presentation" or role="none" across your Handlebars (.html) and JavaScript files using the editor's search.
- Open each flagged template (e.g. templates/layout/base.html, templates/components/*.html) and remove conflicting ARIA attributes or tabindex from the offending element.
- Save changes and use the Preview function to test. Run axe DevTools in Chrome against the preview URL to confirm the fix.
- Publish the theme update from the theme editor when satisfied.
<!-- CORRECT: Decorative image — use empty alt, no role needed -->
<img src="decorative-swoosh.png" alt="" />
<!-- CORRECT: If role="none" is used on a layout table, remove all ARIA -->
<table role="none">
<tr><td>Layout cell</td></tr>
</table>
<!-- CORRECT: Meaningful element — remove role="presentation" and use proper semantics -->
<img src="product-badge.png" alt="New arrival" />
<!-- BROKEN (do not do this): role="none" conflicts with aria-label -->
<!-- <img src="decorative-swoosh.png" role="none" aria-label="decorative swirl" /> -->
<!-- BROKEN (do not do this): role="presentation" conflicts with tabindex -->
<!-- <div role="presentation" tabindex="0">layout wrapper</div> -->Decision examples: decorative image (correct), meaningful image (correct), broken pattern (what to avoid).
RegionModerate effort
Wrap all visible page content inside HTML landmark regions (e.g. `<header>`, `<main>`, `<nav>`, `<footer>`) so screen-reader users can navigate the page by section.
On BigCommerce
- In your BigCommerce admin go to Storefront → My Themes → (active theme) → Advanced → Edit Theme Files.
- Open 'templates/layout/base.html' (Cornerstone theme) — this is the global shell.
- Ensure the site header markup is inside `<header role='banner'>`, the main page content area is inside `<main id='main-content'>`, and the footer is inside `<footer role='contentinfo'>`.
- Open 'templates/components/common/header.html' and 'templates/components/common/navigation.html' — confirm navigation is wrapped in `<nav aria-label='Main navigation'>`.
- Check 'templates/pages/' for individual page templates (category.html, product.html, etc.) to ensure content does not render outside the `<main>` block.
- Use the axe browser extension to test your live storefront and iterate until all content is inside landmarks.
Role img altModerate effort
Add a meaningful aria-label (or aria-labelledby) to every element with role="img" so screen readers can announce what the image represents.
On BigCommerce
- In BigCommerce Admin, go to Storefront → My Themes → click 'Advanced' → 'Edit Theme Files' on your active theme.
- Use the file search to find role="img" across your Stencil theme's .html and .handlebars template files.
- Add aria-label="[description]" to each element, following the same pattern as the generic HTML steps.
- For SVG sprites (common in Stencil), locate the SVG sprite file (often templates/layout/base.html or assets/img/ SVG files), add <title id="unique-id">[Description]</title> as the first child of each <symbol>, and reference it with aria-labelledby on the <svg role="img"> usage site.
- Push changes and validate with a screen reader or the axe browser extension.
<!-- Pattern 1: Inline element (icon font, emoji, span) -->
<span role="img" aria-label="Free shipping available">🚚</span>
<!-- Pattern 2: SVG element — use <title> + aria-labelledby (most robust) -->
<svg role="img" aria-labelledby="icon-free-shipping" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
<title id="icon-free-shipping">Free shipping available</title>
<use href="#icon-truck"></use>
</svg>
<!-- Pattern 3: SVG with aria-label only (simpler, slightly less support) -->
<svg role="img" aria-label="4.5 out of 5 stars" width="120" height="24" xmlns="http://www.w3.org/2000/svg">
<!-- star paths here -->
</svg>
<!-- Pattern 4: div/section used as a decorative image — HIDE from screen readers -->
<div role="presentation" aria-hidden="true" class="decorative-banner"></div>
<!-- Pattern 5: referencing an existing visible caption -->
<figure>
<div role="img" aria-labelledby="badge-caption" class="trust-badge"></div>
<figcaption id="badge-caption">Verified Secure Checkout</figcaption>
</figure>Apply to any HTML element using role="img" — choose the pattern that matches your element type.
Scrollable region focusableQuick win
Make every scrollable region on your site reachable by keyboard by adding tabindex="0" (or placing focusable content inside it) so keyboard and assistive-technology users can scroll it.
On BigCommerce
- In your BigCommerce Admin, go to Storefront → My Themes → click Customize on your active theme → click Edit Theme Files (or use Theme Editor → Edit Code for Stencil themes).
- Locate the Handlebars template file containing the scrollable element (e.g. templates/components/products/description.html or a custom partial).
- Add tabindex="0" aria-label="Product description" to the scrollable wrapper element.
- Add a :focus CSS rule in assets/scss/ or assets/css/ for that element class.
- Push/save the change, then preview and test keyboard navigation on the storefront.
<!-- BEFORE (inaccessible): -->
<div class="product-description" style="height: 200px; overflow-y: auto;">
<p>This is a long product description that requires scrolling to read in full...</p>
</div>
<!-- AFTER (keyboard-accessible): -->
<div
class="product-description"
style="height: 200px; overflow-y: auto;"
tabindex="0"
aria-label="Product description"
role="region"
>
<p>This is a long product description that requires scrolling to read in full...</p>
</div>Add tabindex="0" and aria-label to any scrollable container that holds only non-interactive content.
Select nameQuick win
Add a visible or programmatic label to every `<select>` dropdown so assistive technologies can announce its purpose to users.
On BigCommerce
- In your BigCommerce admin go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' for your active theme (Stencil-based).
- Product option selects live in `templates/components/products/options/swatch.html`, `set-select.html`, or `set-rectangle.html`. Open the relevant file and locate the `<select>` tag.
- Add a matching `<label>` before the `<select>`: `<label for="attribute_{{ product.options[i].id }}">{{ product.options[i].display_name }}</label>` and add the corresponding `id="attribute_{{ product.options[i].id }}"` to the `<select>` tag.
- For the sort-by dropdown on collection pages, open `templates/components/category/shop-by.html` or `templates/pages/category.html` and add `<label for="sort" class="u-hidden-visually">Sort by</label>` and `id="sort"` on the select.
- Commit your changes in the theme editor. BigCommerce Stencil themes include a `.u-hidden-visually` utility class for visually-hidden labels.
- Preview the storefront and verify labels are announced using a screen reader or the axe browser extension.
<!-- Method 1: Visible label (preferred) -->
<label for="sort-order">Sort by</label>
<select id="sort-order" name="sort">
<option value="price-asc">Price: Low to High</option>
<option value="price-desc">Price: High to Low</option>
<option value="newest">Newest</option>
</select>
<!-- Method 2: Visually hidden label (when visible label breaks design) -->
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<label for="sort-order" class="visually-hidden">Sort by</label>
<select id="sort-order" name="sort">
<option value="price-asc">Price: Low to High</option>
<option value="price-desc">Price: High to Low</option>
<option value="newest">Newest</option>
</select>
<!-- Method 3: aria-label (last resort, no visible label possible) -->
<select aria-label="Sort by" name="sort">
<option value="price-asc">Price: Low to High</option>
<option value="price-desc">Price: High to Low</option>
<option value="newest">Newest</option>
</select>
<!-- Method 4: Wrapping label (implicit association — no for/id needed) -->
<label>
Sort by
<select name="sort">
<option value="price-asc">Price: Low to High</option>
<option value="price-desc">Price: High to Low</option>
<option value="newest">Newest</option>
</select>
</label>The gold-standard approach: a visible <label> linked to the <select> via matching for/id attributes.
Skip linkQuick win
Add a valid, focusable target element (with a matching `id`) for every "Skip to main content" link so keyboard and assistive-technology users can bypass repeated navigation.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes → click Customize on the active theme → click Edit Theme Files (Advanced).
- Open `templates/layout/base.html` (Cornerstone theme) — this is the root template wrapping all pages.
- Immediately after `<body ...>`, add: `<a class="skip-link" href="#main-content">Skip to main content</a>`.
- Find the `<main>` element (search for `<main`) and add `id="main-content" tabindex="-1"` to it.
- Open `assets/scss/components/foundation/skip-link.scss` (or your theme's main SCSS/CSS) and add the visually-hidden-until-focused CSS (see snippet below).
- Click Save & Apply, then test with keyboard Tab navigation on your storefront.
Svg img altModerate effort
Add a meaningful text alternative to every SVG image so screen readers can describe it to visually impaired shoppers.
On BigCommerce
- Go to Storefront > My Themes > (active theme) > Advanced > Edit Theme Files (or Download to edit locally).
- SVGs typically appear in templates/layout/base.html, templates/components/, and assets/img/ directories. Search for '<svg' across template files.
- For inline SVGs in .html template files: locate the `<svg>` tag and add `role="img"` and `aria-label="Descriptive text here"` to the opening tag.
- For SVG files referenced as assets, download the SVG, open it in a text editor, add `<title id="t1">Descriptive text</title>` as the first child of the root `<svg>` element, add `role="img" aria-labelledby="t1"` to the `<svg>` tag, then re-upload to assets/img/.
- For decorative SVGs, add `aria-hidden="true"` to the `<svg>` tag.
- Save/upload changes and use the Preview option to verify; run axe DevTools in your browser to confirm the violation is resolved.
<!-- MEANINGFUL SVG — use title + aria-labelledby -->
<svg role="img" aria-labelledby="svg-logo-title" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<title id="svg-logo-title">Acme Co. logo — home</title>
<!-- SVG path data here -->
<circle cx="50" cy="50" r="50" fill="#e63946"/>
</svg>
<!-- MEANINGFUL SVG — simpler aria-label alternative -->
<svg role="img" aria-label="Free shipping badge" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<!-- SVG path data here -->
<path d="M1 3h15v13H1z" fill="#2a9d8f"/>
</svg>
<!-- DECORATIVE SVG — hide from assistive technology -->
<svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 10">
<!-- decorative divider path -->
<rect width="200" height="10" fill="#f0f0f0"/>
</svg>Preferred pattern for a meaningful inline SVG: <title> as first child + aria-labelledby on the root element.
TabindexModerate effort
Remove or replace all positive tabindex values (tabindex="1" or higher) on your page elements, using tabindex="0" for focusable elements and tabindex="-1" only when programmatic focus is needed.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → Themes → click Customize next to your active theme, then open the theme's Edit Theme Files option (available in the Advanced section of the Customize panel, or via the Stencil CLI for developer access).
- Search your template files (templates/layout/, templates/components/, templates/pages/) for 'tabindex'.
- Edit the relevant .html template files and change any tabindex value greater than 0 to '0', or remove it from standard interactive elements.
- If using the Cornerstone theme or a derivative, also check assets/js/ for any JavaScript that dynamically sets tabindex via setAttribute.
- Push your changes via the Stencil CLI ('stencil push') or save directly in the control panel file editor.
- Clear the CDN cache under Server Settings → Cache Settings if available.
<!-- ❌ WRONG: positive tabindex breaks natural tab order -->
<button tabindex="3">Submit</button>
<a href="/shop" tabindex="1">Shop Now</a>
<div tabindex="2">Custom widget</div>
<!-- ✅ CORRECT: native elements use no tabindex (natural order) -->
<button>Submit</button>
<a href="/shop">Shop Now</a>
<!-- ✅ CORRECT: non-native element made focusable in natural order -->
<div tabindex="0" role="button" aria-label="Custom widget">Custom widget</div>
<!-- ✅ CORRECT: element only focused by JavaScript (e.g., modal), not in tab flow -->
<div tabindex="-1" id="modal-container" role="dialog" aria-modal="true">...</div>Replace any positive tabindex value with 0 (or remove the attribute). Use -1 only for programmatic focus.
Valid langQuick win
Add or correct the `lang` attribute on every HTML element that contains content in a different language, using a valid BCP 47 language code.
On BigCommerce
- Go to Storefront → My Themes → click Customize on your active theme, then Advanced → Edit Theme Files.
- Open templates/layout/base.html (or the equivalent layout file for your theme, e.g. Cornerstone uses templates/layout/base.html).
- Find the <html> tag and set it to <html lang="{{locale_name}}"> — BigCommerce's Handlebars context exposes locale_name as a valid BCP 47 code.
- Click Save & Apply.
- For inline foreign-language text in product descriptions, use the HTML source editor in the product description field (Products → Edit Product → Description → click the <> HTML button) and add a lang attribute to the relevant tag.
<!DOCTYPE html>
<html lang="{{locale_name}}">
<head>
<meta charset="utf-8">
{{{head.title}}}
{{> components/common/head}}
</head>
<body>
{{{snippet 'htmlhead'}}}
{{{page_content}}}
</body>
</html>In templates/layout/base.html (Cornerstone or custom theme) — locale_name is provided by BigCommerce's Handlebars context as a valid BCP 47 code.
Security (OWASP) · 26 fixes
Dmarc policy noneModerate effort
Strengthen your DMARC policy from p=none (monitor-only) to p=quarantine, then p=reject, so that emails fraudulently sent from your domain are blocked rather than silently allowed through.
On BigCommerce
- In BigCommerce Admin → Settings → Email, configure a custom sender domain and complete the SPF and DKIM DNS records BigCommerce instructs you to add.
- If you use a third-party ESP (Klaviyo, Mailchimp, etc.) via a BigCommerce app, complete that app's DKIM/SPF setup at your DNS provider as well.
- Go to your DNS provider and locate the _dmarc.yourdomain.com TXT record. Change p=none to p=quarantine.
- After monitoring rua reports and confirming all legitimate mail passes, change p=quarantine to p=reject.
v=DMARC1; p=quarantine; sp=quarantine; pct=100; rua=mailto:dmarc-reports@yourdomain.com; ruf=mailto:dmarc-failures@yourdomain.com; ri=86400; aspf=r; adkim=r; fo=1;This is the DNS TXT record value for _dmarc.yourdomain.com — paste this as the record content at your DNS provider. Replace the rua/ruf addresses with your own reporting inbox or DMARC reporting service address.
Hsts disabledQuick win
Set a valid HTTP Strict-Transport-Security (HSTS) header with a max-age of at least 31536000 (one year) and includeSubDomains to force browsers to always use HTTPS for your store.
On BigCommerce
- BigCommerce manages HSTS at the platform infrastructure level for all storefronts — the header is set automatically and you cannot configure it manually from the admin.
- If your BigCommerce store is fronted by Cloudflare or another CDN/proxy that you control, ensure that proxy is not stripping or overriding the HSTS header.
- To check: go to your storefront URL in a browser, open DevTools (F12) → Network tab → click the top-level document request → Response Headers, and confirm Strict-Transport-Security is present.
- For headless BigCommerce setups (Next.js, Nuxt, custom front-end), set the HSTS header in your front-end server or CDN configuration — see the Headless/Custom entry below.
Strict-Transport-Security: max-age=31536000; includeSubDomainsThis is an HTTP response header — it cannot be set in HTML meta tags. It must be set by your server, CDN, or platform. Shown here for reference only.
Hsts max age too shortQuick win
Increase your HSTS max-age directive to at least 31536000 seconds (1 year) so browsers enforce HTTPS connections for a meaningful period.
On BigCommerce
- BigCommerce manages HTTPS and core security headers at the platform level for standard storefronts — direct server-header editing is not available in the admin UI.
- If the scanner reports a short max-age on a BigCommerce storefront, check whether a third-party script injection or a custom header app is overriding the header.
- For BigCommerce headless storefronts (e.g. Next.js + BigCommerce GraphQL API), set the header in your Next.js next.config.js headers() function or at your CDN/hosting layer (Vercel, Netlify, Cloudflare).
- Raise a support ticket with BigCommerce if you believe the platform itself is serving max-age=86400 — they control the CDN configuration for managed storefronts.
- Contact your BigCommerce account manager (for Enterprise) to request a compliant HSTS header be applied at the edge.
Strict-Transport-Security: max-age=31536000; includeSubDomainsThis is an HTTP response header — it must be sent by your server, NOT as an HTML meta tag. The meta tag is not supported for HSTS.
Https not availableQuick win
Enable HTTPS by installing a valid SSL/TLS certificate and redirecting all HTTP traffic to the secure HTTPS version of your store.
On BigCommerce
- BigCommerce provides a free SSL certificate for all storefronts automatically.
- In your BigCommerce Control Panel, go to Store Setup → Store Profile and confirm your Store URL begins with https://.
- To force HTTPS, go to Store Setup → Store Settings → Miscellaneous and enable 'Force Secure Checkout' if available, or verify that server-side HTTPS redirect is active (it is on by default for all BigCommerce-hosted storefronts).
- For a custom domain, go to Store Setup → Domains and ensure your domain is correctly pointed and the SSL certificate is listed as active.
- If using a custom SSL certificate (enterprise plans), upload it via the BigCommerce support request process or through your account manager.
Info disclosure serverQuick win
Remove or suppress the HTTP `Server` response header so your web server no longer advertises its software name and version number to the public internet.
On BigCommerce
- BigCommerce SaaS storefronts run on infrastructure fully managed by BigCommerce — you cannot modify the `Server` header from the store admin.
- Log in to your BigCommerce control panel, go to *Server Settings* — there is no native `Server` header control for SaaS plans.
- The most effective solution for BigCommerce merchants is to route traffic through *Cloudflare* (free or paid): update your domain's nameservers to Cloudflare, enable the proxy (orange cloud), then create a *Transform Rule* under Rules > Transform Rules > Modify Response Header to Remove the `Server` header.
- For enterprise/dedicated BigCommerce plans, contact BigCommerce Enterprise support to request banner suppression at the infrastructure level and obtain documentation for compliance audits.
<!-- The Server header cannot be controlled from HTML.
Apply the fix at your web server, CDN, or hosting control panel
using one of the platform-specific configurations shown below. -->There is no HTML tag to set or suppress the Server header — it is purely a server/CDN-level configuration. Use the server-specific snippets below.
Info disclosure x powered byQuick win
Remove or suppress the X-Powered-By HTTP response header so your server stops advertising which technology stack, hosting platform, or software version powers your store.
On BigCommerce
- BigCommerce is a fully hosted SaaS platform; server-level response headers are managed by BigCommerce infrastructure and are not directly editable by store owners.
- BigCommerce does not emit a meaningful X-Powered-By header by default on standard storefronts.
- If you are running a headless BigCommerce storefront (e.g. on Next.js/Vercel or a custom Node server), open your server middleware and add: res.removeHeader('X-Powered-By'); in your Express/Next.js config (see code snippets below).
- For Next.js specifically, add the header removal in next.config.js using the headers() function.
- Contact BigCommerce support if a non-headless storefront is emitting this header unexpectedly.
<!-- X-Powered-By is an HTTP response header set by the server, not in HTML markup.
Use the server-side code snippets below for your specific platform. -->There is no HTML tag for this — it is a server-side HTTP response header. Use the server/framework snippets below.
Insecure cookieModerate effort
Set the HttpOnly, Secure, and SameSite flags on all session and authentication cookies to prevent them from being stolen or misused by attackers.
On BigCommerce
- BigCommerce manages core session cookies (SHOP_SESSION_TOKEN, etc.) at the platform level — contact BigCommerce support if the scanner flags their own cookies, as these are set server-side by the platform.
- For cookies set by your custom Stencil theme JavaScript, move cookie creation to a server-side API route (BigCommerce App or serverless function) and set flags there.
- For a custom BigCommerce headless/Next.js storefront, set cookies in your API routes using response.setHeader('Set-Cookie', 'name=value; HttpOnly; Secure; SameSite=Strict').
- Navigate to BigCommerce Admin → Storefront → Script Manager and review any third-party scripts that might set cookies; contact those vendors to enable secure flags.
- Verify in browser DevTools → Application → Cookies.
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=StrictCorrect Set-Cookie HTTP response header — all three flags present. Your server must emit this header, not JavaScript.
Missing content security policyModerate effort
Add a Content-Security-Policy (CSP) HTTP response header to every page to block unauthorized scripts, styles, and resources from loading in your visitors' browsers.
On BigCommerce
- BigCommerce does not expose arbitrary HTTP response header settings in the merchant admin.
- The recommended approach is to place BigCommerce behind Cloudflare (free or paid) and configure the CSP as a Cloudflare HTTP Response Headers Transform Rule: Cloudflare Dashboard → your domain → Rules → Transform Rules → Modify Response Headers → Add header → Name: Content-Security-Policy → Value: your policy string.
- For headless BigCommerce storefronts (Next.js, Gatsby, etc.), set the header in next.config.js (headers() function) or your server middleware.
- As a partial fallback, add a <meta http-equiv='Content-Security-Policy' content='...'> tag inside your Stencil theme's base.html template (Storefront → My Themes → Edit Theme Files → templates/layout/base.html), understanding that this is weaker than an HTTP header.
Missing dmarcQuick win
Add a DMARC DNS TXT record at _dmarc.yourdomain.com to tell receiving mail servers how to handle emails that fail authentication checks for your domain.
On BigCommerce
- BigCommerce does not manage DNS. Go to the DNS provider where your domain is registered or delegated (e.g. Cloudflare, GoDaddy).
- Add a TXT record: Host/Name = _dmarc, Value = v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com, TTL = 3600.
- In BigCommerce Admin → Settings → Email, verify that transactional emails are sent through BigCommerce's own SMTP or a connected provider. Check that provider's dashboard for DKIM signing — most (Mailchimp Transactional, SendGrid) provide DKIM DNS records to add alongside DMARC.
- Only escalate DMARC to p=quarantine or p=reject after verifying DKIM/SPF pass in aggregate reports.
_dmarc.yourdomain.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; ruf=mailto:dmarc-forensic@yourdomain.com; sp=none; adkim=r; aspf=r"Add this as a DNS TXT record at your domain registrar or DNS provider. Replace yourdomain.com and the rua address with your actual domain.
Missing permissions policyQuick win
Add a Permissions-Policy HTTP response header to your store to explicitly restrict which browser features (camera, microphone, geolocation, etc.) pages and embedded third-party scripts are allowed to access.
On BigCommerce
- BigCommerce's SaaS infrastructure does not expose direct HTTP header configuration. Use a Cloudflare proxy or BigCommerce's built-in CDN header rules if on an Enterprise plan.
- Option A (Cloudflare): In your Cloudflare dashboard for the domain, go to Rules → Transform Rules → Modify Response Header. Create a rule: Header name = 'Permissions-Policy', Value = 'camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()'. Match all hostnames. Save.
- Option B (BigCommerce Enterprise): Contact BigCommerce support or your TAM about configuring custom response headers at the CDN/edge layer.
- Verify the header appears in browser DevTools → Network → Response Headers on your storefront.
<!-- NOT recommended — use a real HTTP header instead. Shown for reference only. -->
<meta http-equiv="Permissions-Policy" content="camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()">Meta tag delivery is not recommended — use HTTP headers instead. Included for reference only; browser support is partial.
Missing referrer policyQuick win
Add a Referrer-Policy HTTP response header set to strict-origin-when-cross-origin to control what URL information browsers send when users navigate away from your store.
On BigCommerce
- BigCommerce does not provide direct HTTP header configuration from the admin panel.
- The recommended approach is to place a CDN such as Cloudflare in front of your store and add the header there: Cloudflare Dashboard → your domain → Rules → Transform Rules → Modify Response Header → Add 'Referrer-Policy': 'strict-origin-when-cross-origin'.
- As a fallback, inject a <meta> tag via Storefront → Themes → Edit Theme Files → templates/layout/base.html — add <meta name="referrer" content="strict-origin-when-cross-origin"> inside <head>.
- Verify in DevTools → Network → Response Headers.
<meta name="referrer" content="strict-origin-when-cross-origin">Add inside the <head> element of every HTML page as a fallback when HTTP header control is unavailable.
Missing security txtQuick win
Create and publish a /.well-known/security.txt file with at least a Contact: line so security researchers know how to report vulnerabilities responsibly.
On BigCommerce
- BigCommerce does not provide direct filesystem access to serve arbitrary files at /.well-known/.
- The best approach is to place a reverse proxy (e.g. Cloudflare) in front of your BigCommerce store and use a Cloudflare Worker to serve the security.txt content for requests matching /.well-known/security.txt (see Shopify Cloudflare Worker steps and code snippet).
- Alternatively, contact BigCommerce support to ask about serving static files at custom paths — available options vary by plan.
- Verify by visiting https://yourdomain.com/.well-known/security.txt.
Contact: mailto:security@yourdomain.com
Expires: 2026-12-31T23:59:00.000Z
Preferred-Languages: en
Policy: https://yourdomain.com/security-policy
Acknowledgments: https://yourdomain.com/security-acknowledgmentsSave this as security.txt and place it at /.well-known/security.txt on your web server. Update all placeholder values before publishing.
Missing spfQuick win
Add a DNS TXT record containing a valid SPF policy to your domain so that email receivers can verify which servers are authorised to send mail on your behalf.
On BigCommerce
- BigCommerce transactional emails can be sent via BigCommerce's shared infrastructure or routed through a custom SMTP provider.
- To use a custom SMTP provider: BigCommerce Admin → Settings → Email → SMTP settings → enter your provider's credentials (SendGrid, Mailgun, etc.).
- Log in to your domain registrar or DNS host (the registrar where your domain is registered, or Cloudflare/Route 53 if you've delegated DNS).
- Add a new TXT record: Name/Host = '@', Value = v=spf1 include:[your-smtp-provider-include] -all. If using BigCommerce's default sending, check BigCommerce's official documentation for the current include string for their outbound mail servers.
- Save the record and wait for propagation.
- Verify using MXToolbox SPF Lookup and confirm test emails pass SPF authentication by inspecting the email headers.
v=spf1 include:_spf.google.com include:sendgrid.net include:spf.mailgun.org -allAdd this as a DNS TXT record at your domain apex ('@'). Replace the include: values with the exact hostnames from each of your email providers' SPF documentation. Only one SPF TXT record is allowed per domain — combine all providers into one record.
Missing strict transport securityQuick win
Add the Strict-Transport-Security (HSTS) response header to every HTTPS page so browsers always use an encrypted connection to your store.
On BigCommerce
- BigCommerce cloud storefronts serve all pages over HTTPS and the platform manages core transport security.
- Check whether the HSTS header is already present by opening browser DevTools → Network tab → click the homepage request → Response Headers.
- If the header is missing, it is most likely being dropped by a CDN or reverse proxy in front of your store. Log in to your CDN dashboard (e.g., Cloudflare: SSL/TLS → Edge Certificates → HSTS) and enable HSTS with max-age=31536000 and includeSubDomains.
- For BigCommerce Enterprise with a custom server-side layer, add the header in your proxy/middleware configuration.
- Contact BigCommerce support if the header is absent and no CDN is in use — this may be a platform-level configuration they need to adjust for your account.
<!-- HSTS cannot be set via an HTML meta tag. It MUST be sent as an HTTP response header. Use the server-level examples below. -->
<!-- Correct header value -->
<!-- Strict-Transport-Security: max-age=31536000; includeSubDomains -->Meta tags cannot set HSTS — it must be a real HTTP response header. This is a reminder of the correct header value to use at the server level.
Missing x content type optionsQuick win
Add the `X-Content-Type-Options: nosniff` HTTP response header to every page and asset your store serves.
On BigCommerce
- BigCommerce's managed platform controls server-level headers; you cannot set arbitrary HTTP response headers directly from the BigCommerce admin.
- Place Cloudflare (or another CDN/WAF) in front of your BigCommerce store. In Cloudflare: Dashboard → your domain → Rules → Transform Rules → Modify Response Header → Create rule → Add header `X-Content-Type-Options` = `nosniff` → apply to all requests → Save & Deploy.
- Verify by checking DevTools → Network → Response Headers on your storefront.
X-Content-Type-Options: nosniffThis is an HTTP response header — it is sent by the server, not placed in HTML markup. The examples below show where and how to set it.
Missing x frame optionsQuick win
Add the X-Frame-Options HTTP response header set to DENY or SAMEORIGIN to prevent your store's pages from being embedded in iframes on other sites.
On BigCommerce
- BigCommerce sets some security headers automatically, but custom header configuration requires going through Cloudflare or another CDN/proxy in front of your store.
- Log in to Cloudflare (or your CDN) → select your BigCommerce domain → go to Rules → Transform Rules → Response Header Modification.
- Create a new rule: match all incoming requests (or specific paths like /checkout), action = Set header, Header name = X-Frame-Options, Value = SAMEORIGIN → Save and Deploy.
- If you are not using Cloudflare, contact BigCommerce support to ask whether custom response headers can be set at the platform level for your plan.
- Verify with browser DevTools or a header-checker after the CDN rule is live.
X-Frame-Options: SAMEORIGINThis is an HTTP response header — it must be sent by the server, not a meta tag. It should appear in the HTTP response headers for every page.
Passive scan onlyModerate effort
Set up regular active security testing (DAST) on a staging copy of your store to catch vulnerabilities that passive header/cookie/TLS scans cannot find.
On BigCommerce
- BigCommerce does not provide a native staging environment on standard plans; request a sandbox store through BigCommerce Support or use a Partner sandbox account.
- Populate the sandbox with your current theme (Storefront → Themes → Export from production, then import to sandbox) and realistic product data.
- Ensure the sandbox store is not indexed and restrict access: Store Setup → Store Settings → there is no built-in password gate, so request your sandbox URL remain unlisted or add basic-auth via a custom Nginx/Cloudflare rule in front of it.
- Run OWASP ZAP against the sandbox URL: Quick Start → Automated Scan → URL, and configure form-based authentication under Contexts so ZAP can scan authenticated checkout flows.
- Remediate any High/Critical findings by editing your Stencil theme locally (stencil CLI) or adjusting settings in the control panel, then re-scan.
- Deploy fixed theme to production via Storefront → Themes → Upload and apply.
<meta name="robots" content="noindex, nofollow">Add this meta tag to your staging site's <head> to prevent search engines from indexing it while DAST scanning is in progress.
Ssl cert expiring soonQuick win
Renew your SSL/TLS certificate before it expires to keep your store secure, trusted, and visible in search results.
On BigCommerce
- BigCommerce automatically provisions and renews SSL certificates for all storefronts hosted on bigcommerce.com and for custom domains connected through the control panel.
- To verify: go to BigCommerce Admin → Store Setup → Store Profile → Storewide HTTPS and confirm 'Storewide HTTPS' and 'HSTS' are enabled.
- For custom domains, go to Admin → Store Setup → Store Profile and confirm the primary domain is set correctly; BigCommerce will manage its certificate.
- If you use a third-party CDN or a custom SSL certificate (Enterprise plans), log in to your CDN or certificate authority dashboard and follow their renewal steps, then upload the new certificate bundle in your CDN's SSL section.
- Contact BigCommerce Support via the Help Center if the certificate status does not update within 48 hours of DNS being correctly pointed.
<!-- Place this in your maintenance/holding page only if HTTPS is temporarily unavailable -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">Meta-refresh redirect for maintenance: not applicable to SSL renewal. Instead, use this HTML to display a temporary notice if your cert has lapsed and you need to redirect HTTP traffic while fixing HTTPS.
Ssl cert invalidModerate effort
Install a valid SSL/TLS certificate that exactly matches your store's domain name, so browsers trust your site and customer data is encrypted in transit.
On BigCommerce
- BigCommerce auto-provisions free SSL certificates for all storefronts on bigcommerce.com subdomains and for custom domains connected through the control panel.
- Go to Store Setup → Domain Settings. Confirm your custom domain is correctly pointed to BigCommerce (DNS CNAME to stores.yourstore.bcapp.net or the value BigCommerce specifies).
- If the SSL status shows an error, click 'SSL Settings' next to your domain and select 'Let BigCommerce manage my SSL certificate'. BigCommerce will provision a new Let's Encrypt certificate automatically.
- If you are using Cloudflare or another proxy in front of BigCommerce, ensure the SSL mode in Cloudflare is set to 'Full (Strict)' and that a valid certificate is also installed at the BigCommerce origin.
- Contact BigCommerce Support if the certificate does not provision within 24 hours.
Ssl errorModerate effort
Replace or reissue your SSL/TLS certificate so it is valid for the exact domain name your store uses, eliminating the hostname mismatch error.
On BigCommerce
- BigCommerce automatically provisions SSL for your store's default domain (*.mybigcommerce.com) and for custom domains connected through their system.
- Go to: BigCommerce Admin → Store Setup → Domain.
- If your custom domain has an SSL issue, verify that your DNS CNAME record points to your BigCommerce store URL (shown in the Domain settings page).
- Remove the custom domain and re-add it to trigger a fresh certificate provisioning if the mismatch persists.
- For multi-storefront setups, each domain must be added separately and have its own DNS record pointing to BigCommerce.
- Contact BigCommerce Support if automatic provisioning fails after DNS is confirmed correct.
Ssl not accessibleModerate effort
Enable HTTPS on your store by opening port 443 and installing a valid SSL/TLS certificate so every page is served over a secure connection.
On BigCommerce
- BigCommerce provisions and manages SSL certificates automatically for all storefronts hosted on their platform.
- Go to Admin → Store Setup → Store Profile and verify your store URL uses https://.
- For custom domains: Admin → Store Setup → Store Profile → change Store URL to your custom domain, then point your domain's DNS to BigCommerce's servers (instructions in Admin → Store Setup → Store Profile → Domain Settings). BigCommerce will provision the certificate automatically.
- If you are on a legacy plan or using a third-party SSL, contact BigCommerce Support via the Help menu to request certificate provisioning and confirm port 443 is open on their infrastructure.
- If you use a custom storefront on your own servers (BigCommerce headless), open port 443 in your server's firewall and install a TLS certificate as described in the generic steps.
Vulnerable component axiosModerate effort
Update the Axios JavaScript library to its latest stable release to eliminate known security vulnerabilities in your storefront code.
On BigCommerce
- In your BigCommerce control panel, go to Storefront → My Themes → click Customize on your active theme, then open the theme's file editor or download the theme zip for local editing.
- Search the theme files (particularly assets/js/) for 'axios' to find where it is referenced.
- If loaded via a CDN <script> tag in a template file (.html), update the URL to the latest Axios version.
- If bundled in a compiled JS file, edit your local package.json, run `npm install axios@latest && npm run build`, then upload the updated theme zip back via Storefront → My Themes → Upload Theme.
- If the vulnerable Axios comes from a BigCommerce app, go to Apps & Integrations, check for the app's update, or contact the app vendor.
<!-- Load the latest Axios from jsDelivr CDN (always points to newest stable release) -->
<script src="https://cdn.jsdelivr.net/npm/axios@latest/dist/axios.min.js" integrity="" crossorigin="anonymous"></script>
<!-- OR pin to a specific safe version (recommended for production stability) -->
<script src="https://cdn.jsdelivr.net/npm/axios@1.7.9/dist/axios.min.js" crossorigin="anonymous"></script>Replace any hardcoded Axios CDN script tag in your HTML templates with this — always uses the latest stable version.
Vulnerable component jqueryModerate effort
Update jQuery to the latest stable version (3.7+) to eliminate known cross-site scripting (XSS) and prototype-pollution vulnerabilities that attackers actively exploit.
On BigCommerce
- In your BigCommerce Control Panel, go to Storefront → Themes → click 'Advanced' → 'Edit Theme Files' on your active theme (Stencil-based).
- In the file editor, open 'templates/layout/base.html' (or the equivalent base layout) and search for jQuery script tags.
- Update any hard-coded CDN jQuery URL to 'https://code.jquery.com/jquery-3.7.1.min.js'.
- If jQuery is referenced in 'assets/js/app.js' or bundled via Webpack, open 'package.json', update the jQuery version to '^3.7.1', and run 'npm install && stencil bundle' locally before re-uploading the theme.
- Check all installed apps in Apps → My Apps — app-injected jQuery must be fixed by the app vendor; contact them or remove outdated apps.
- Apply the theme changes and use DevTools → Network to confirm no old jQuery version is loaded.
<!-- Remove your old jQuery script tag and replace with this -->
<script
src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>Replace any old jQuery <script> tag in your HTML <head> with this. Get the current SRI hash from https://code.jquery.com/
Weak spfQuick win
Add a hard-fail (-all) or soft-fail (~all) terminator to your SPF DNS record so that mail servers reject or flag email sent from servers not explicitly authorized by your domain.
On BigCommerce
- BigCommerce does not manage your DNS. DNS is controlled by your domain registrar or a CDN/DNS provider such as Cloudflare.
- Log in to your domain registrar (e.g., GoDaddy, Namecheap, Google Domains/Squarespace Domains) or DNS provider.
- Navigate to DNS Management / Zone Editor for your domain.
- Locate the TXT record starting with `v=spf1`. Edit it to add `-all` (recommended) or `~all` at the very end of the record value.
- Save the record and verify propagation with an SPF checker tool.
v=spf1 include:_spf.google.com include:sendgrid.net -allDNS TXT record value for your root domain (@). Replace the include/redirect mechanisms with the ones your email service provider specifies, and always end with -all or ~all.
X content type options weakQuick win
Set the X-Content-Type-Options response header to exactly `nosniff` (once, not duplicated) on every page and asset your store serves.
On BigCommerce
- BigCommerce's platform injects `X-Content-Type-Options: nosniff` by default on storefront responses.
- If your scanner reports a duplicate, the extra copy is likely coming from Cloudflare or another CDN/proxy sitting in front of your store.
- Log in to your Cloudflare (or other CDN) dashboard → Rules / Transform Rules → Modify Response Headers — remove any rule that adds `X-Content-Type-Options`, since BigCommerce already sets it.
- If you use a custom nginx or Apache reverse proxy, remove the header directive from that config.
- Verify with DevTools or securityheaders.com after clearing any CDN cache.
X frame options weakQuick win
Replace the weak X-Frame-Options header value with DENY or SAMEORIGIN to prevent clickjacking attacks on your store.
On BigCommerce
- BigCommerce's managed hosting sets X-Frame-Options: SAMEORIGIN by default on storefront pages — you cannot directly override HTTP response headers from the BigCommerce control panel for the core storefront.
- If the weak header originates from a custom headless frontend, a third-party app, or a middleware layer (e.g. a Contentstack preview URL), configure the header in that service's server settings.
- For headless BigCommerce storefronts (Next.js, Gatsby, etc.) deployed on Vercel or Netlify: add a vercel.json or netlify.toml headers block (see code snippets below).
- For app-level concerns, contact BigCommerce support (Support → Submit a Case) to confirm the expected header behavior and request guidance on overriding it at the CDN/edge layer.
- Verify storefront response headers using DevTools → Network on your live store URL.
<!-- X-Frame-Options MUST be sent as an HTTP response header, not a meta tag. -->
<!-- Use the server-side or platform snippets below instead. -->
<!-- The modern equivalent you CAN set via meta tag (limited support): -->
<meta http-equiv="Content-Security-Policy" content="frame-ancestors 'none';">If you cannot set server-level headers, use this meta-equivalent only as a last resort — note that X-Frame-Options via meta tag is NOT supported by browsers (it must be an HTTP header). This snippet is shown for illustration only; use server-side headers.
Site Lifecycle · 12 fixes
Cms versionModerate effort
Update your CMS and ecommerce platform to the latest stable version immediately to close known security vulnerabilities and maintain vendor support.
On BigCommerce
- BigCommerce core is SaaS and updated automatically — no manual core upgrades required.
- Theme updates: In BigCommerce admin go to Storefront > My Themes. If a newer version of your theme is available, a notification appears. Click 'Make a copy' first (to preserve your current settings), then apply the update.
- For Stencil CLI developers: run 'stencil pull' to fetch the latest framework updates, merge carefully, then run 'stencil push' to deploy.
- Check Apps > My Apps for any apps flagged as having updates, and update them individually.
- Monitor the BigCommerce status page and release notes (bigcommerce.com/release-notes) for upcoming changes that may affect custom integrations.
<!-- REMOVE or suppress this tag from your <head> — it advertises your CMS version to attackers -->
<!-- <meta name="generator" content="WordPress 5.8.1" /> -->
<!-- In WordPress, add this to your theme's functions.php to remove it: -->
<!-- remove_action('wp_head', 'wp_generator'); -->If your site injects a generator meta tag exposing your CMS version publicly, remove it to reduce information exposure to attackers. This does not replace upgrading — it is a secondary hardening step.
Domain expiryQuick win
Log in to your domain registrar, confirm your domain's expiry date, and enable auto-renew so your store never goes offline due to an expired domain.
On BigCommerce
- BigCommerce does not register domains — the domain was purchased through a separate registrar.
- Log in to your registrar (e.g. GoDaddy, Google Domains, Namecheap) directly. Find the domain and enable auto-renew.
- In BigCommerce Admin → Storefront → Domains you can see which domain is connected, but renewal must be managed at the registrar.
<!-- No HTML change required. Domain renewal is managed at your domain registrar's dashboard (e.g. GoDaddy, Namecheap, Cloudflare Registrar). Log in, find the domain, enable auto-renew, and confirm a valid payment method is on file. -->No code change is needed on your website — this fix is completed entirely in your registrar's dashboard. There is no markup or configuration file involved.
Gtm auditModerate effort
Install Google Tag Manager on your store and configure it to fire GA4 with full ecommerce event tracking (view_item, add_to_cart, purchase, and more).
On BigCommerce
- In the BigCommerce admin, go to Storefront › Script Manager › Create a Script.
- Set Location to 'Head', Pages to 'All Pages', and paste the GTM <script> snippet. Save.
- Create a second script, set Location to 'Footer' and paste the GTM <noscript> snippet.
- For ecommerce events, install the 'Better.io' or 'Littledata' app from the BigCommerce App Marketplace — these inject a GA4-compatible ecommerce data layer automatically.
- Configure GA4 Event tags in GTM for the data layer events and publish the container.
<!-- Google Tag Manager (paste in <head>) -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
<!-- Google Tag Manager (noscript) (paste immediately after <body>) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->Replace GTM-XXXXXXX with your real Container ID. First snippet goes in <head>, second immediately after <body>.
Html langQuick win
Add a lang attribute to your site's <html> tag that matches the primary language of your store's content.
On BigCommerce
- In BigCommerce admin, go to Storefront → My Themes.
- Click Customize on your active theme, then choose Edit Theme Files (available in the developer-mode / file editor, or download the theme via Theme Editor → Download).
- Open templates/layout/base.html (Cornerstone theme) or the equivalent base layout template.
- Locate the <html tag and add the lang attribute: <html lang="en"> (replace with your language code).
- Save and upload/apply the theme. For multi-language setups, use the BigCommerce Stencil locale context variable if available in your theme version.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{head.title}}</title>
{{{head.scripts}}}
</head>
<body>
{{{snippet.header}}}
{{{page}}}
{{{snippet.footer}}}
</body>
</html>In templates/layout/base.html of your Stencil theme — replace 'en' with your language code.
Lifecycle oos schema not updatedModerate effort
Update the `offers.availability` value in your Product structured data from `InStock` to `OutOfStock` (or `PreOrder`) whenever a product sells out, so Google's records always match your actual inventory.
On BigCommerce
- BigCommerce injects Product schema through its Stencil theme framework. Open your Stencil theme files (locally via Stencil CLI or via the online Theme Editor for supported themes).
- Locate `templates/components/products/product-view.html` (path may vary by theme). Search for `availability` or `InStock`.
- The availability value should use a Handlebars conditional based on the `product.availability` context variable. Replace any hardcoded string with: `{{#if product.availability}}{{product.availability}}{{else}}https://schema.org/OutOfStock{{/if}}` — but confirm the exact variable name in your theme's context.
- BigCommerce also supports overriding schema via the 'Scripts' section in the Control Panel (Storefront → Script Manager) — check for any injected JSON-LD scripts that hardcode `InStock` and remove or fix them.
- Push the updated theme and validate with Google's Rich Results Test on an out-of-stock product.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Your Product Name",
"image": "https://example.com/images/product.jpg",
"description": "Short product description.",
"sku": "YOUR-SKU-123",
"brand": {
"@type": "Brand",
"name": "Your Brand"
},
"offers": {
"@type": "Offer",
"url": "https://example.com/product-page",
"priceCurrency": "USD",
"price": "29.99",
"availability": "https://schema.org/OutOfStock",
"itemCondition": "https://schema.org/NewCondition"
}
}
</script>Place this inside a <script type='application/ld+json'> tag in the <head> or <body> of your product page. Replace placeholder values with real data. Use OutOfStock when sold out.
Lifecycle orphaned productsModerate effort
Add internal links pointing to every orphaned product page from relevant category pages, collection pages, or other on-site content so search crawlers and shoppers can discover them.
On BigCommerce
- Go to BigCommerce Admin → Products → View, then open the orphaned product.
- Click the 'Categories' tab and check all relevant categories. Save.
- To create a new category, go to Products → Product Categories → Add, then assign products to it.
- Go to Storefront → Navigation to add any newly created category to the main menu.
- For related/cross-sell links, scroll to the 'Related Products' section on the product editing page and manually add related products, or enable 'Automatic Related Products' in Store Setup → Store Settings → Product Settings.
{{!-- BigCommerce Stencil: manual related product links for orphaned products --}}
<section class="related-products">
<h2>{{lang 'products.related_products'}}</h2>
<ul>
{{#each product.related_products}}
<li>
<a href="{{url}}">
<img src="{{getImageSrcset image use_default_sizes=true}}" alt="{{name}}">
<span>{{name}}</span>
</a>
</li>
{{/each}}
</ul>
</section>Add to a Page Builder page or a Stencil template partial (e.g., templates/components/products/related-products.html) to manually link to orphaned products.
Lifecycle products missing from sitemapQuick win
Add all canonical product URLs to your XML sitemap so search engines discover and index every product page quickly.
On BigCommerce
- BigCommerce auto-generates a sitemap at yourdomain.com/xmlsitemap.php — visit this URL to verify product pages are included.
- Go to Admin → Store Setup → Store Settings → Search Engine Optimization tab; confirm 'Enable XML Sitemap' is checked.
- In Admin → Products → View, check that missing products are set to 'Visible' (not 'Hidden') under the product's Storefront visibility setting.
- If products are excluded due to category visibility, go to Admin → Products → Product Categories and ensure the relevant categories are also set to visible.
- Submit the sitemap (yourdomain.com/xmlsitemap.php) in Google Search Console → Indexing → Sitemaps.
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!-- Example product page entry -->
<url>
<loc>https://www.example.com/products/blue-running-shoes</loc>
<lastmod>2024-06-01</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<!-- Repeat one <url> block per canonical product page -->
<url>
<loc>https://www.example.com/products/red-yoga-mat</loc>
<lastmod>2024-05-20</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>Standard XML sitemap structure. Place this at yourdomain.com/sitemap.xml (or reference it from a sitemap index file).
Lifecycle products too deepModerate effort
Move deeply buried product pages closer to the homepage by flattening your site's navigation structure so every product is reachable within 4 clicks (ideally 3) from the homepage.
On BigCommerce
- Go to Products → Product Categories in the BigCommerce control panel.
- Review your category tree. Any category that is a child of a child of a top-level category creates a 4+ click path to its products.
- Select an overly nested category, click Edit, and change its 'Parent Category' to a shallower parent or to the root (no parent).
- Go to Storefront → My Themes → Customize (or Edit Theme Files for Page Builder) and add a 'Featured Products' widget or carousel directly on the homepage linked to the previously buried products.
- In Storefront → Navigation, ensure your main navigation links directly to the restructured categories.
- Use the BigCommerce Catalog API or a sitemap crawler to verify all product URLs are now within 4 clicks.
<!-- Featured Products section on homepage or top category page -->
<section aria-label="Featured Products">
<h2>Featured Products</h2>
<ul>
<li><a href="/products/product-name-1">Product Name 1</a></li>
<li><a href="/products/product-name-2">Product Name 2</a></li>
<li><a href="/products/product-name-3">Product Name 3</a></li>
</ul>
</section>Add direct internal links to deep products from your homepage or top-level category pages. Place this markup in a 'Featured Products' or 'Quick Links' section.
Mixed contentModerate effort
Ensure every resource (images, scripts, stylesheets, fonts, iframes) on your store is loaded over HTTPS, never HTTP, so browsers never block or warn about mixed content.
On BigCommerce
- Go to Storefront → My Themes → your active theme → Advanced → Edit Theme Files.
- Search for 'http://' across template and asset files (.html, .css, .js) and update any found URLs to 'https://'.
- Navigate to Content → Web Pages and check each custom page's HTML source for HTTP asset URLs.
- Check Storefront → Script Manager for any third-party scripts using HTTP src URLs — update them to HTTPS.
- Re-test using browser DevTools Console.
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">Add this meta tag inside <head> to instruct browsers to automatically upgrade HTTP sub-requests to HTTPS. This is a safety net — fix the root URLs too.
Mobile viewportQuick win
Add a responsive viewport meta tag to every page so mobile browsers render your site at the correct width and scale.
On BigCommerce
- In your BigCommerce admin, go to Storefront → My Themes.
- Click Customize on your active theme, then select Edit Theme Files (Advanced).
- Open templates/layout/base.html (the master layout file).
- Search for `<meta name="viewport">`. Cornerstone and most marketplace themes already include it; confirm the content value is `width=device-width, initial-scale=1`.
- If missing, add `<meta name="viewport" content="width=device-width, initial-scale=1">` immediately after the `<head>` tag.
- Save and apply the theme. The change propagates to every page.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Title</title>
</head>
<body>
<!-- page content -->
</body>
</html>Place the viewport meta tag as early as possible in <head>, before any CSS or other meta tags.
Server versionQuick win
Remove or suppress HTTP response headers that advertise your server software name and version to the public internet.
On BigCommerce
- BigCommerce's SaaS infrastructure controls the 'Server' header — it is not configurable from the merchant admin.
- For custom middleware or API-driven storefronts (Catalyst/Next.js), add header suppression in your 'next.config.js' (see code snippets below) and deploy via Vercel or your chosen host.
- If using Cloudflare in front of BigCommerce, create a Cloudflare Transform Rule (Rules → Transform Rules → Modify Response Header) to delete 'X-Powered-By' and set 'Server' to a generic value.
- Verify via DevTools that no technology version string is visible in response headers.
<!-- HTTP response headers cannot be set via HTML meta tags.
Use the server-side or CDN configuration snippets below. -->Meta tags cannot suppress HTTP response headers — this must be done at the server/CDN layer. The snippets below cover the most common server/framework approaches.
Ssl expiryQuick win
Renew your TLS/SSL certificate before it expires and enable automatic renewal so your store never goes offline or shows security warnings.
On BigCommerce
- BigCommerce provisions and auto-renews SSL certificates for all storefronts automatically.
- To verify: go to Store Control Panel → Server Settings → SSL Certificates and confirm your certificate shows as active.
- For custom domains, ensure your DNS CNAME record correctly points to your BigCommerce storefront subdomain so the certificate can be issued.
- If you see an SSL error after a domain change, remove and re-add the domain in the control panel to trigger re-provisioning.
<!-- SERVER-SIDE redirect is strongly preferred. Example nginx config snippet below. -->
<!-- nginx: force HTTPS -->
<!-- server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
} -->Verify your HTTPS redirect is in place at the server/app level. This meta-refresh is a last-resort fallback only — implement a proper server-side 301 redirect instead.
Generative Engine Optimization · 9 fixes
Ai crawler blockedQuick win
Your robots.txt explicitly blocks one or more AI assistants from crawling your store, so those engines can't discover, index, or cite your products when shoppers ask for recommendations.
On BigCommerce
- Go to Channel Manager > your storefront > Customize robots.txt (or Settings > SEO depending on plan).
- Remove any 'Disallow: /' rule under the AI bot's user-agent, or add an explicit allow group for it.
- Save and verify at https://yourstore.com/robots.txt.
Ai crawler not specifiedQuick win
Your robots.txt doesn't explicitly allow several AI crawlers. They aren't blocked, but a number of AI engines act on explicit permission, so naming them removes any ambiguity.
On BigCommerce
- Go to Channel Manager > your storefront > Customize robots.txt (or Settings > SEO depending on plan).
- Remove any 'Disallow: /' rule under the AI bot's user-agent, or add an explicit allow group for it.
- Save and verify at https://yourstore.com/robots.txt.
Geo brand name inconsistentModerate effort
Your brand name appears in multiple different formats across your site (schema, og:site_name, footer, logo). AI engines may treat the variants as separate entities.
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Geo eeat trust signals weakModerate effort
Your store is missing trust signals (E-E-A-T) that AI engines and shoppers look for before recommending a store: clear policies, real contact details, and a credible business identity.
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Geo faqpage missing productsModerate effort
Your product pages don't use FAQPage schema, so AI assistants can't pull direct answers to common buyer questions (sizing, materials, shipping) about your products.
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Geo price not crawlableModerate effort
Your product prices appear to be rendered by JavaScript and may not be present in the static HTML, so AI crawlers (which often don't run JS) can't read or cite them.
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Geo schema org missing sameasModerate effort
Your Organization schema has no sameAs links to your social profiles, Wikipedia, or other authoritative sources - so AI engines can't confidently connect the dots about your brand.
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Geo schema product incompleteModerate effort
Your Product structured data is missing fields AI engines rely on to cite your products accurately (price, availability, currency, brand, ratings).
On BigCommerce
- Edit your Stencil theme templates ('templates/pages/product.html') to extend the JSON-LD with the missing fields using Handlebars ({{product.title}}, {{product.price}}).
- Set your store's social profile URLs and business info so Organization sameAs/address/contactPoint can be emitted.
- Validate with Google's Rich Results Test.
Llms txt missingQuick win
Your store has no llms.txt - the emerging standard (like robots.txt, but for AI) that tells language models which content to read and cite. SEOLZ has generated a ready-to-upload file from your own pages.
On BigCommerce
- BigCommerce doesn't expose the web root directly; serve llms.txt via a redirect to a hosted file or a Page with a raw-text template, or via your CDN/edge rules.
- Paste the generated content and confirm it returns at https://yourstore.com/llms.txt.