Anonymized sample audit · ADAShield deliverable structure

Brand X — WCAG 2.2 AA audit

Real audit on a real US Shopify supplement brand, mid-7-figure annual revenue. Brand identity redacted; methodology, findings, and code patches are unchanged. This is what you get when you commission an ADAShield audit.

Audit window
2026-04-25 → 2026-04-29
Standard
WCAG 2.2 Level AA
Pages tested
25 (top by traffic)
Audit ID
SMPL-2026-04-29

1 · Executive summary

Brand X's online store was audited against WCAG 2.2 Level AA between 25–29 April 2026. We identified 63 non-conformance errors and 177 warnings, distributed across 7 different WCAG success criteria. With remediation per the included roadmap, the site can reach AA conformance in an estimated 14–22 developer-hours, achievable inside a single sprint.

The most-cited gaps are programmatic labelling (form fields and empty headings, 22 instances), duplicate id attributes from repeated Shopify section types (21 instances), and missing accessible names on icon-only buttons in the cart drawer and main navigation.

P0 · Blocking
11

Issues that cited courts have repeatedly weighed against defendants.

P1 · High
38

User-impact issues — keyboard, screen-reader, contrast.

P2 · Moderate
14

Polish items — heading hierarchy, semantic structure.

Conformance score: 62 / 100 (43 / 50 AA criteria fully passing)

2 · WCAG 2.2 AA conformance summary

All 7 failing criteria, ordered by issue count.

Criterion Title Status Issues Severity
1.3.1Info and relationshipsFail22P0
4.1.1Parsing (duplicate IDs)Fail21P1
3.2.2On InputFail7P1
1.4.3Contrast minimumFail5P1
4.1.2Name, Role, ValueFail4P0
2.4.1Bypass blocksFail3P0
1.1.1Non-text content (alt text)Fail1P0

The full conformance table in the delivered PDF lists every Level AA criterion (including passing rows). Excerpt shown here.

3 · Methodology

4 · Top 10 issues with code patches

Selected from the full 30-issue list in the deliverable, one per WCAG criterion plus the most prevalent patterns. Each issue includes the affected element, plain-English explanation, paste-able fix, and developer-hour estimate.

P0 WCAG 1.1.1 · Non-text content Issue 1 / 30

Site logo image has no alt text

Element: #shopify-override > img · Affects every page on the store

The header logo is rendered as a plain <img> with no alt attribute. Screen-reader users hear the image filename or nothing at all when navigating to the home page — the brand identity is invisible to assistive tech.

Fix (in sections/header.liquid or wherever the logo is rendered):

<!-- Before -->
<img src="{{ section.settings.logo | image_url: width: 200 }}">

<!-- After -->
<img src="{{ section.settings.logo | image_url: width: 200 }}"
     alt="{{ shop.name | escape }}"
     width="{{ section.settings.logo.width }}"
     height="{{ section.settings.logo.height }}"
     loading="eager">

Estimated developer time: 5 minutes. Fixes the logo across every page in one edit.

P0 WCAG 1.3.1 · Info and relationships Issue 2 / 30

Empty heading elements creating phantom landmarks

Element: ...> h5 with no text content · 4 instances in the cart-drawer modal

Several <h5> tags in the cart-drawer template wrap empty containers used purely for layout. Screen readers announce them as "heading, level 5" with no content, creating phantom landmarks during heading-by-heading navigation.

Fix (replace with semantic div when used for layout):

{%- comment -%} Before — empty h5 used as layout container {%- endcomment -%}
<h5 class="cart-drawer__row">{{ block.shopify_attributes }}</h5>

{%- comment -%} After — div with appropriate role if needed {%- endcomment -%}
<div class="cart-drawer__row" {{ block.shopify_attributes }}>
  {%- if block.settings.heading != blank -%}
    <h2>{{ block.settings.heading | escape }}</h2>
  {%- endif -%}
</div>

Estimated developer time: 15 minutes. 4 occurrences in sections/cart-drawer.liquid.

P0 WCAG 1.3.1 · Info and relationships Issue 3 / 30

Newsletter signup input has no programmatic label

Element: input[type="email"] in footer newsletter form · Affects every page

The footer email-capture field uses a placeholder for guidance ("Enter your email"). Placeholders are not labels — they disappear when the user starts typing and assistive tech treats them inconsistently. A programmatic label is required.

Fix (in sections/footer.liquid):

<label for="NewsletterFormEmail" class="visually-hidden">
  Email address
</label>
<input id="NewsletterFormEmail"
       type="email"
       name="contact[email]"
       autocomplete="email"
       placeholder="Enter your email"
       required>

Estimated developer time: 10 minutes. Use the existing .visually-hidden CSS class — Dawn-derived themes ship with it.

P1 WCAG 1.4.3 · Contrast minimum Issue 4 / 30

Promo banner copy below 4.5:1 contrast ratio

Light gray #9CA3AF on white = 2.85:1. Required: 4.5:1.

The "Free shipping over $75" promo banner uses a light gray that fails the AA 4.5:1 minimum for body text. Affected at 5 surface points across the home, collection, and product templates.

Fix:

/* In your theme's main stylesheet — typically assets/base.css */
.promo-banner__text {
  /* Before */
  color: #9CA3AF;  /* 2.85:1 — fail */

  /* After — passes 4.55:1 on white */
  color: #4B5563;
}

Estimated developer time: 5 minutes. Verify with a contrast checker (e.g., webaim.org/resources/contrastchecker) before committing.

P0 WCAG 2.4.1 · Bypass blocks Issue 5 / 30

Skip-link points to a non-existent anchor

Link href: #megamenu--main-menu — no element with this id exists on the page.

A keyboard-skip link in the header references an anchor that was renamed during a theme update. Keyboard users tabbing onto the link and pressing Enter land nowhere — the link is silently broken.

Fix (the simplest path is to make the skip-link match an existing landmark):

<!-- In layout/theme.liquid, just inside <body> -->
<a class="skip-to-content-link visually-hidden-focusable"
   href="#MainContent">
  Skip to main content
</a>

<!-- And ensure the main wrapper has the matching id -->
<main id="MainContent" tabindex="-1" role="main">
  {{ content_for_layout }}
</main>

Estimated developer time: 10 minutes. Cited by federal courts (Robles v. Domino's) — high-priority remediation.

P1 WCAG 3.2.2 · On Input Issue 6 / 30

Newsletter form has no visible submit button

7 forms across the site rely on Enter-key submission only.

Several signup forms are designed for Enter-key submission with no visible button. This is unreliable for assistive tech and breaks for users on touch keyboards or those who don't realize Enter submits.

Fix:

{%- comment -%} Add a real submit button to every form {%- endcomment -%}
<form action="/contact#contact_form" method="post">
  {%- comment -%} ...inputs... {%- endcomment -%}
  <button type="submit" class="newsletter__btn">
    Subscribe
    <span class="visually-hidden">to our newsletter</span>
  </button>
</form>

Estimated developer time: 30 minutes. 7 forms × ~4 minutes each.

P1 WCAG 4.1.1 · Parsing Issue 7 / 30

Duplicate id attributes from repeated section types

21 instances. Most-cited collision: id="Image with Text" appearing 4 times.

When a Shopify theme reuses the same section type (e.g., "Image with Text") multiple times on a page, naive id generation causes collisions. HTML id attributes must be unique — duplicates cause assistive tech to behave unpredictably and break aria-labelledby / aria-describedby references.

Fix (in any section template that generates ids — use Shopify's section.id Liquid variable):

{%- comment -%} Before — collides when section is reused {%- endcomment -%}
<div id="Image with Text">
  <h2>{{ section.settings.heading }}</h2>
</div>

{%- comment -%} After — unique per instance via section.id {%- endcomment -%}
<div id="ImageWithText--{{ section.id }}">
  <h2 id="ImageWithText__heading--{{ section.id }}">
    {{ section.settings.heading | escape }}
  </h2>
</div>

Estimated developer time: 2 hours. Audit every section template; replace static ids with section.id-suffixed unique values.

P0 WCAG 4.1.2 · Name, Role, Value Issue 8 / 30

Cart drawer close button has no accessible name

Element: icon-only <button> in the cart-drawer header

The cart-drawer modal's close button renders an X icon with no accompanying text or aria-label. Screen readers announce it as "button" with no purpose, leaving users unable to dismiss the drawer.

Fix:

{%- comment -%} sections/cart-drawer.liquid {%- endcomment -%}
<button type="button"
        class="cart-drawer__close"
        aria-label="Close cart"
        data-cart-close>
  {%- render 'icon-close' -%}
</button>

Estimated developer time: 5 minutes. Apply the same pattern to the menu-open and search-open icon buttons (Issues 9 + 10).

P1 WCAG 4.1.2 · Name, Role, Value Issue 9 / 30

Cart quantity +/− buttons have no labels

Element: stepper controls in cart-drawer line items

The plus and minus buttons that adjust line-item quantity in the cart drawer are unlabeled icons. Screen-reader users hear "button, button" and can't tell which increases vs decreases quantity.

Fix:

<div class="quantity">
  <button type="button"
          aria-label="Decrease quantity"
          data-quantity-decrease>−</button>
  <input type="number" value="{{ item.quantity }}"
         aria-label="Quantity for {{ item.title | escape }}">
  <button type="button"
          aria-label="Increase quantity"
          data-quantity-increase>+</button>
</div>

Estimated developer time: 15 minutes.

P2 WCAG 1.3.1 · Info and relationships Issue 10 / 30

Heading hierarchy skips levels in the homepage layout

Home page: h1h4 (skipping h2 and h3)

The home page uses one <h1> for the hero, then jumps to <h4> in the "Featured collection" section. Screen-reader users navigating by heading hierarchy lose track of structure when levels are skipped.

Fix (in section templates — use logical heading levels, style with CSS classes for visual sizing):

{%- comment -%} Before — visual jump h1 → h4 {%- endcomment -%}
<h4 class="featured-collection__title">Featured</h4>

{%- comment -%} After — semantically correct h2, styled to match h4 visually {%- endcomment -%}
<h2 class="featured-collection__title h4">
  {{ section.settings.title | escape }}
</h2>

Estimated developer time: 1 hour. Audit every section template; ensure heading levels follow document order.

The full delivered audit covers 30 prioritized issues in the same depth as above, plus all 50 conformance rows in the Section 2 table, the manual-review walkthrough below, and the demand-letter defense memo.

5 · Manual review highlights

Findings that automated scanners can't detect. The full deliverable expands each into a paragraph + screenshot.

Keyboard navigation

Reached cart, product detail, and checkout using Tab + Enter alone. Focus is lost twice — once when opening the cart drawer (focus stays on the trigger button instead of moving into the drawer), and once when closing it (focus moves to the body, not back to the trigger). Both result in disorientation for keyboard-only users.

Screen-reader walkthrough

NVDA + Chrome, full purchase flow. Cart drawer line items are announced inconsistently — sometimes the product title, sometimes "list item, list item." Quantity changes are not announced (no live region). "Add to cart" success is silent.

Focus management

Focus indicator is set to outline: none on buttons and visible only via the browser default ring on links. Custom focus styles needed across all interactive elements at 3:1 contrast minimum.

Color contrast (sampled)

Sale-price strikethrough (#9CA3AF on white) fails. "View details" CTA hover state (#15A29B on #E5E7EB) borderline at 3.7:1. All other surfaces sampled pass.

6 · Remediation roadmap

Phased over 90 days. P0 first, in parallel with the cited-court risk reduction.

Phase 1 · Days 1-30 — All 11 P0 issues

~6 dev-hours. Logo alt, broken skip-link, cart-drawer close button, all empty headings, all newsletter form labels.

Phase 2 · Days 31-60 — All 38 P1 issues

~10 dev-hours. Duplicate ids (largest cluster), all icon-button names, contrast adjustments, form submit buttons.

Phase 3 · Days 61-90 — All 14 P2 + manual-review fixes

~6 dev-hours. Heading hierarchy, focus indicators, live regions for cart updates.

Total estimated effort: 14–22 developer-hours over a calendar quarter, achievable inside a single sprint without disrupting the storefront roadmap.

7 · Demand-letter defense memo

A standalone memo your attorney can put on file. Below is the template — the delivered version is signed, dated, and customized.

Memorandum — Accessibility Remediation Status

Date of audit: 25–29 April 2026
Site audited: [Brand X storefront URL]
Standard: WCAG 2.2 Level AA
Auditor: ADAShield (FatCouple OÜ), operating as a third-party accessibility auditor.
Audit ID: SMPL-2026-04-29

[Brand X] commissioned a comprehensive WCAG 2.2 AA conformance audit of its e-commerce storefront. The audit identified 63 specific non-conformances and adopted a 90-day remediation roadmap (attached as Sections 4–6 of the audit deliverable). [Brand X] has documented its accessibility remediation program from this date forward.

Documented evidence of an ongoing, good-faith accessibility remediation program has been favorably received by US federal courts in mitigation of damages and in pre-litigation negotiation with plaintiffs (see Robles v. Domino's Pizza, 9th Cir. 2019; Gil v. Winn-Dixie, 11th Cir. 2021). It does not constitute a defense against liability and does not guarantee any litigation outcome.

[Auditor signature, date]

8 · Legal disclaimer

This audit identifies WCAG 2.2 Level AA conformance gaps and provides remediation recommendations. It does not constitute legal advice. Compliance with the Americans with Disabilities Act (ADA), Section 508, the European Accessibility Act, or any other accessibility statute is determined by courts and regulatory bodies on a case-by-case basis. WCAG 2.2 AA is the consensus standard cited in most US ADA Title III enforcement actions, but conformance does not guarantee any specific litigation outcome. The customer is solely responsible for implementation of recommended fixes. ADAShield does not warrant that implementation of these recommendations will result in any specific level of compliance, legal protection, or litigation outcome.

Want this for your store?

A real audit, fixed price, 5 business days from payment to PDF. Same depth and structure as the sample above — applied to your store, with your theme's Liquid in the code patches.

Start your audit — $1,495

Or compare tiers on the pricing page.