Portfolio sample Anonymized real audit. This is a redacted sample of a delivered WCAG 2.2 AA priority remediation plan. The client's brand name, domain, and product names have been replaced with fictional placeholders and on-page screenshots are withheld — every finding, CSS selector, severity rating, and remediation step is reproduced unchanged from the original engagement.

Priority Remediation Plan

Brightleaf Wellness Co.

🔒 client domain withheld · Shopify storefront
WCAG 2.2 AA· 5 pages audited· 8 criteria with active findings· Issued May 2026

Prepared by Andrew Szigety — Harbor Accessibility

35
Level A Issues
5
High Priority
30
Medium Priority
5
Pages Audited
100%
Findings Verified

Scope & conformance target

This plan covers the 8 WCAG 2.2 Level A criteria with active findings. Resolving every item here achieves Level A conformance across the audited pages.

A further 10 Level AA criteria are covered in the accompanying Complete Audit Report.

◗ Target: WCAG 2.2 Level A
Section 1 · Interactive Roles5
Section 5 · Image Alt Text14
Section 6 · Reading Order6
Section 7 · Semantic Markup5
Section 2 · Link Text2
Section 3 · Label in Name1
Section 4 · Use of Color1
Section 8 · Form Labels1
Issues by section · bar width relative to the largest group (Image Alt Text, 14).
High priority — blocks assistive-technology use Medium priority — degrades the experience 100% verified — every finding manually confirmed
1

Interactive Element Roles and Names

High
WCAG 4.1.2 · A 5 issues ✓ 100% verified Complete Report §1
HomepageCollectionTerms & Conditions
Fix summary: Add role, aria-label, and state attributes to custom interactive widgets.
button.product-card-v2__buttonHomepageCollection

Interactive element nested inside another interactive element — 4 occurrences in one template (#shopify-section-template), so a single template fix resolves all.

✔ Recommended fix Move the <button> outside its parent link (<a>). Nested interactive elements break assistive-technology focus and name computation.
.header-search-iconTerms & Conditions

Button has no accessible name — a screen reader announces only “button.”

✔ Recommended fix <button aria-label="Search">
div.account-popup__wrapperTerms & Conditions

aria-labelledby references a nonexistent ID "account-popup" — no accessible name is produced from this attribute.

✔ Recommended fix The referenced ID does not exist in the DOM. Add the target element, or update the attribute value to point at a real label.
div.z-10Terms & Conditions

aria-labelledby references a nonexistent ID "mobile-menu" — no accessible name is produced from this attribute.

✔ Recommended fix Add the target element, or update the attribute value to reference an element that exists.
input#Search2 elementsTerms & Conditions

aria-controls references a nonexistent ID "predictive-search-results-list" — no ARIA relationship is formed.

✔ Recommended fix Point aria-controls at the live results container's real ID, or remove the attribute if predictive search is not wired up.
2

Descriptive Link Text

Medium
WCAG 2.4.4 · A 2 issues ✓ 100% verified Complete Report §4
HomepageTerms & Conditions
Fix summary: Make link text describe its destination; add an aria-label where the visible text is generic.
.app-promo__download-button[target="_blank"]Homepage

App-store download link has no accessible name — the control is an icon/image with no text for screen readers.

2🔒Screenshot withheld
Original report pins a screenshot to each flagged element. Redacted here for confidentiality.
✔ Recommended fix
<a href="https://play.google.com/store/apps/details?id=…"
   aria-label="Download on Google Play">
#shopify-section-template--…__main a3 elementsTerms & Conditions

Link text is a raw URL — screen-reader users hear the address read out character by character instead of a destination.

✔ Recommended fix Replace the URL text with a readable label:
Before: <a href="https://‹client-domain›/">https://‹client-domain›/</a>
After:  <a href="https://‹client-domain›/">Brightleaf Wellness Home</a>
Or add: aria-label="Brightleaf Wellness Home"
3

Label in Name

Medium
WCAG 2.5.3 · A 1 issue Complete Report §10
Homepage
Fix summary: Ensure the aria-label includes the visible text verbatim, so voice-control users can activate what they see.
a.flex.items-centerHomepage

Accessible name "/pages/hormone-balance" does not contain the visible text “Hormone Balance+.” The name is being computed from the href because no explicit label is set.

✔ Recommended fix Add an aria-label that includes the visible text — e.g. aria-label="Hormone Balance+".
4

Use of Color

Medium
WCAG 1.4.1 · A 1 issue Complete Report §11
Collection
Fix summary: Add a non-color indicator (icon, symbol, or ARIA role) so color isn't the only thing signalling an error.
div.quick-add-errorCollection

Six error messages rely only on color (red text) with no icon, symbol, or ARIA role to convey the error state. Same element in every instance — one fix resolves all.

✔ Recommended fix Add non-color indicators to the error component:
  • Prefix with an icon or symbol (⚠ ✖ !)
  • Add role="alert" so screen readers announce it
  • Add a border or background change alongside the color
5

Image Alt Text

Medium
WCAG 1.1.1 · A 14 issues Complete Report §14
HomepageCollectionProduct Detail PageQuiz
253 images evaluated 9 missing alt text 61 with generic alt text
Fix summary: Write alt text that describes each image's content or purpose — not just its type (“photo”, “image”, “logo”).
#shopify-section-…__announcement-pdp2 imgsHomepageCollectionPDP

Alt text "Brightleaf Wellness image" is generic. +1 more affected image in the complete report.

#shopify-section-template--…__multirow4 imgsHomepage

Alt text "Brightleaf Wellness image" is generic. +1 more affected image in the complete report.

#shopify-section-template--…__video_slider3 imgsHomepage

Alt text "Brightleaf Wellness image" is generic.

#shopify-section-template--…__app_promo img2 imgsHomepage

Image-only link with no alt text and no accessible name, plus an image with no alt attribute — screen readers announce the filename instead of the content.

✔ Recommended fix Give the link a label and the image meaningful alt text — e.g. <a aria-label="Download our app"><img alt="App preview"></a>.
#shopify-section-template--…__featured_product21 imgsPDP

Alt text "Hormone Balance+" is repeated verbatim across the gallery — generic and non-distinguishing. +13 more affected images in the complete report.

#product-form7 imgsPDP

Alt text "Hormone Balance+" is generic across product-form imagery.

#shopify-section-template--…__content_cards13 imgsPDP

Alt text "Hormone Balance+" is generic. +5 more affected images in the complete report.

#shopify-section-template--…__product_vs_others3 imgsPDP

Alt text "Hormone Balance+" is generic.

Additional generic-alt groups on the PDP — …__landing_featured_logo (4), #block-card (1), …__okendo_reviews (2, +2 more) — follow the same fix.

Third-party app content — fix in the app's settings/dashboard, not theme code:
#octane-quiz-wrapper7 imgsQuiz

Images have no alt attribute — screen readers announce the filename. +7 more in the complete report. Set alt text in the quiz app's media settings.

6

Meaningful Reading Order

Medium
WCAG 1.3.2 · A 6 issues Complete Report §16
HomepageTerms & ConditionsProduct Detail Page
Fix summary: Match DOM order to visual order; remove flex-direction: *-reverse and CSS order that desync the two.
div.review-slider__card__footerHomepage

Uses flex-direction: row-reverse, reversing children's visual order relative to DOM order.

✔ Recommended fix Remove row-reverse and reorder the children in the HTML to match the intended sequence. Need a reversed layout at some breakpoints? Reorder the DOM to the most common reading order and use non-reversed flex with media queries.
div.brand-progress-bar__itemTerms & Conditions

Uses CSS order: 1, which can make visual order differ from DOM reading order.

✔ Recommended fix Remove order: 1 and move the element to position 1 in the source. CSS order desyncs what sighted users see from what screen readers read.
div.price__salePDP

Uses flex-direction: row-reverse, reversing the visual order of its children.

✔ Recommended fix Remove row-reverse and reorder the children in source order.
div.form-checkPDP

Uses CSS order: 2, desyncing visual and DOM order.

✔ Recommended fix Remove order: 2 and move the element to position 2 in the source.
div.multirow-section__text-image-block__contentPDP

Uses flex-direction: row-reverse, reversing children's visual order.

✔ Recommended fix Remove row-reverse and reorder children in the HTML.
Third-party app content — fix in the app's dashboard:
button#filter-toggle.oke-buttonPDP

Uses CSS order: 1. Reorder within the review-app's layout settings or move it to position 1 in source.

7

Semantic Markup and Structure

Medium
WCAG 1.3.1 · A 5 issues Complete Report §17
HomepageCollectionProduct Detail PageQuiz
Fix summary: Use semantic HTML — <h1>–<h6>, <ul>/<ol>, <th scope>, <label>, landmarks.
#shopify-section-…__quiz_announcement15 listsPDPHomepage

15 visual lists use bullet characters instead of semantic <ul>/<ol> — list structure is not programmatically conveyed.

✔ Recommended fix Use list elements: <ul><li>Item 1</li><li>Item 2</li></ul> (or <ol> for ordered items).
#shopify-section-template--…__multirow h6Homepage

Heading level skip: h3 → h6 (“Mix, match, and save!”).

✔ Recommended fix Change the <h6> to <h4>, or add the intermediate heading levels.
#shopify-section-template--…__early_timerCollection

1 visual list uses bullet characters instead of semantic list markup.

✔ Recommended fix Convert to <ul>/<ol> with <li> items.
#QuickAddModal h3Collection

Heading level skip: h1 → h3 (“Unable to load product”).

✔ Recommended fix Change the <h3> to <h2>, or add the intermediate level.
#shopify-section-quiz-start-page-header2 listsQuiz

2 visual lists use bullet characters instead of semantic list markup.

✔ Recommended fix Convert to <ul>/<ol> with <li> items.
8

Form Labels and Instructions

Medium
WCAG 3.3.2 · A 1 issue Complete Report §20
Terms & Conditions
Fix summary: Give every form input a visible label; don't rely on the placeholder alone.
input[type="email"][name="email"]Terms & Conditions

Required field “Email” has no visible required indication in its label — users won't know it must be completed before submitting.

✔ Recommended fix Add a required indicator: include “(required)” in the label text, or add an asterisk (*) with a legend explaining “* indicates required field.”