WCAG Accessibility Report
Requires Professional EditionThe WCAG Accessibility Report lets you check how accessible the websites in your domain portfolio are, see which ones have issues, and drill into the details of what needs fixing.
What Is WCAG?
WCAG stands for the Web Content Accessibility Guidelines, an internationally recognised standard that defines how websites should be built so that people with disabilities can use them. This includes people who use screen readers, keyboard-only navigation, or who have visual, hearing, or cognitive impairments.
WCAG compliance is increasingly a legal requirement in many countries and is considered best practice for any public-facing website. Issues are grouped into three levels of conformance:
| Level | What it means |
|---|---|
| A | The minimum. Failure at this level makes a site unusable for many people with disabilities. |
| AA | The standard most organisations aim for. Required by most accessibility laws and regulations. |
| AAA | The highest level. Not always achievable for all content but represents best practice. |
Using the Report
Which domains appear in this report? By default, the report shows domains assigned to the WCAG Test Domains category in WMD SED. Administrators can also switch the Scope dropdown to Show All Domains to view the full portfolio. If you expect to see a domain in the category-only view but it is missing, ask your administrator to add it to that category.
The Summary Bar
At the top of the report you will see a row of summary cards showing counts for the current scope:
| Card | What it means |
|---|---|
| Total | All domains currently included in the selected scope |
| Scanned | Domains that have been scanned at least once |
| Pass | Domains with no violations at the tested WCAG level |
| Fail | Domains with one or more violations |
| Partial | Domains where some checks could not be completed automatically |
| Error | Domains the scanner could not reach, such as because the site is down or timed out |
| Not Scanned | Domains not yet tested |
The Domain Table
Each row in the table represents one domain. The columns show:
| Column | What it means |
|---|---|
| Domain | The domain name |
| Status | Pass, Fail, Partial, or Error, the result of the last scan |
| Level | The highest WCAG level the domain fully passes, A, AA, AAA, or none |
| Critical | Number of critical violations, these block access for some users entirely |
| Serious | Number of serious violations, these create significant barriers |
| Moderate | Number of moderate violations, these cause difficulty but workarounds may exist |
| Minor | Number of minor violations, these are best-practice issues |
| Scanned At | When the domain was last scanned |
Click any column header to sort by that column. Click again to reverse the sort order.
Filtering the Table
Use the toolbar above the table to narrow down what you see:
- Type a domain name in the search box to filter by domain
- Use the Scope dropdown to switch between WCAG Category Only and Show All Domains
- Use the Status dropdown to show only Pass, Fail, Partial, or Error domains
- Use the Level dropdown to show only domains at a specific WCAG level
Viewing Violation Details
Click any row to open a popup showing the full scan results for that domain. The popup shows:
- A summary of the scan result, level, issue counts, pass count, and when the scan was run
- The URL the scanner actually reached, which may differ from the original domain if there was a redirect
- Violations tab - each accessibility issue found, showing its severity, the WCAG criteria it relates to, a description of the problem, and the HTML elements affected
- Incomplete tab - checks the scanner could not fully evaluate automatically and that may need manual review
Press Escape or click outside the popup to close it.
Resetting a Domain for Rescanning
Each row has a reset button (↺) at the right end. Clicking it marks the domain as not yet scanned, so it will be picked up and rescanned automatically on the next scheduled scan run. Use this when a site has been updated and you want fresh results.
Exporting Data
Two export options are available in the toolbar:
- CSV - downloads a spreadsheet with the summary columns for all domains in the current scope. Useful for sharing results or importing into other tools.
- JSON - downloads a complete export including all violation details for every domain in the current scope. Useful for further analysis or integration with other systems.
How Scanning Works
Scans run automatically in the background on a schedule set by your administrator, typically every 30 minutes. By default, automated scanning targets domains assigned to the WCAG Test Domains category in WMD SED. The browser report can also be switched to show all domains in the portfolio for broader review. If a domain does not appear in the category-only view, check that it has been added to the WCAG category.
Each domain is loaded in a headless browser, tested against the configured WCAG standard, and the results are saved. Domains that have been scanned recently are skipped unless reset manually or force-scanned from the CLI.
The scanner tests the homepage of each domain. It tries https:// first and falls back to http:// if the secure version is not available. If the site cannot be reached at all, the domain is marked as Error.
Not all accessibility issues can be detected automatically. The scanner catches a broad range of common violations, but some issues, particularly those involving meaning, context, or user interaction, require manual review. A passing result means no automated violations were found, not that the site is fully accessible.
Administrator and Setup Guide
The sections below cover installation, configuration, and technical reference for administrators setting up or maintaining the WCAG scanning extension.
If you need help preparing the shared Node.js and Puppeteer environment used by WMD SED website tools, see Webshots and Cookie Analysis Setup.
Main Files in the WCAG Tool
wcag.php- browser-based WCAG report pagewcag-gather.php- command-line gather scriptaxe-scan.js- Node.js and Puppeteer accessibility scannerwcag-setup.sh- setup helper script for Linux environments
wcag.php provides the browser report. The gather process uses axe-scan.js, which should be copied into the Node.js working folder used by WMD SED website scanning tools.
Requirements
- WMD SED already installed with shell access
- Node.js available in the environment used by WMD SED
- A Node.js working folder available for WMD SED website scanning tools
@axe-core/puppeteerinstalled in that Node.js working folder- WMD administrator access for the browser report page
Setup
Linux / Debian / Ubuntu
Download wcag-setup.sh from learn.domainpunch.com/static/downloads/wcag-setup.sh and run it as the wmdsed user:
bash wcag-setup.sh
For standard installations, no editing is normally required. For non-standard installations, edit the variables near the top of the script before running it.
To preview the setup without making changes:
bash wcag-setup.sh --dry-run
The script performs pre-flight checks, installs @axe-core/puppeteer if needed, copies axe-scan.js into the Node.js working folder, creates the required WMD SED custom columns, and can optionally add a cron job for automated scanning.
Windows
On Windows there is no setup script. Setup must be completed manually.
WMD SED website scanning tools rely on a dedicated Node.js working folder. This is the folder where the required npm packages are installed and where scanner scripts such as axe-scan.js are placed.
If your installation already uses Node.js and Puppeteer for other WMD SED website tools, use that same working folder for WCAG scanning as well.
Step 1 - Choose the Node.js Working Folder
Identify the Node.js working folder used by WMD SED for website-related scripts. In many installations this is the same folder already used for Puppeteer-based tooling.
Step 2 - Install @axe-core/puppeteer
Open a command prompt in that Node.js working folder and run:
npm install @axe-core/puppeteer --save
Run the command from inside the Node.js working folder so the package is installed in the same environment used by the WCAG scanner.
If that folder is not already being used for other WMD SED website scanning tools, make sure the required Node.js packages for those tools, including Puppeteer, are installed there as well.
Step 3 - Copy axe-scan.js to the Node.js Working Folder
Copy axe-scan.js from the WCAG tool folder into the same Node.js working folder so it can run with the installed npm packages.
All Platforms
The remaining steps are the same on all platforms.
Step 4 - Create custom WMD columns
php wcag-gather.php --setup-columns
This creates four custom columns in WMD SED:
| Column | Type | Content |
|---|---|---|
wcag_status | string | pass / fail / partial / error |
wcag_level | string | A / AA / AAA / none |
wcag_issue_counts | text | JSON such as {"critical":2,"serious":5,"moderate":1,"minor":3} |
wcag_scanned_at | datetime | Latest scan timestamp |
This command is safe to run multiple times because existing columns are skipped.
Step 5 - Create the WCAG category
In WMD SED, create a category named WCAG Test Domains and assign the domains you want to scan to it.
Step 6 - Dry run to verify domain selection
php wcag-gather.php --dry-run
This lists every domain that would be scanned without actually scanning anything.
Step 7 - Run the first scan
php wcag-gather.php php wcag-gather.php --batch=3
Configuration
The main configuration constants are defined near the top of wcag-gather.php:
| Constant | Default | Purpose |
|---|---|---|
WCAG_NODE_FOLDER | websites | Folder name used for Node.js scanner files |
WCAG_OUTPUT_FOLDER | wcag-data | Folder name used for saved WCAG JSON results |
WCAG_DEFAULT_CATEGORY | WCAG Test Domains | WMD category name to scan by default |
WCAG_PROTOCOL_COLUMN | '' | Optional custom column holding the preferred protocol for each domain |
WCAG_SKIP_RECENT_DAYS | 7 | Skip domains scanned within this many days |
WCAG_LEVEL | AA | WCAG level to test against: A, AA, or AAA |
WCAG_TIMEOUT_MS | 30000 | Puppeteer navigation timeout in milliseconds |
WCAG_LOCK_FILE | wcag-gather.lock | Lock file used to prevent concurrent runs |
WCAG_OUTPUT_FOLDER must match the constant of the same name in wcag.php.
Protocol Resolution
If WCAG_PROTOCOL_COLUMN is set to a custom column name such as site_protocol, the scanner reads the protocol from that column for each domain. If it is left empty, the scanner tries https:// first and falls back to http:// if needed.
CLI Reference - wcag-gather.php
| Argument | Type | Description |
|---|---|---|
--category="Name" | key=value | Override the default category. Category name is case-sensitive. |
--domain=example.com | key=value | Scan one domain only. This also implies force mode for that domain. |
--batch=3 | key=value | Run N Puppeteer processes in parallel. Default is 1. |
--skip-recent=14 | key=value | Override WCAG_SKIP_RECENT_DAYS for this run. |
--force | bare flag | Re-scan all matching domains regardless of wcag_scanned_at. |
--setup-columns | bare flag | Create the four wcag_* custom columns and exit. |
--dry-run | bare flag | Show what would be scanned. No scans and no database writes. |
--debug | bare flag | Enable verbose output including SQL, parameters, and raw results. |
Re-scan Behaviour
| Scenario | Behaviour |
|---|---|
wcag_scanned_at is empty | Always scanned |
Scanned within WCAG_SKIP_RECENT_DAYS | Skipped |
--force flag present | Always scanned |
--domain=x specified | Always scanned because force is implied |
Domain Eligibility
A domain is excluded from scanning if all three of the following are true:
availability = 'available'registry_expiryis NULLregistrar_expiryis NULL
Domains with availability = 'Not Available' or 'possibly available' are still included.
Concurrency Lock
wcag-gather.php uses a lock file named wcag-gather.lock to prevent concurrent runs. If a second instance is started while one is already running, it exits immediately with a warning. Stale locks from crashed processes are detected and removed automatically.
What axe-scan.js Does
axe-scan.js is called once per domain by wcag-gather.php and is executed from the Node.js working folder so it resolves node_modules correctly.
- Launches headless Chromium via Puppeteer
- Navigates to the domain URL, trying
https://first and falling back tohttp://when needed - Runs axe-core at the configured WCAG level
- Outputs a single JSON object to standard output, including on error
Scan Result Status Values
| Status | Meaning |
|---|---|
pass | No violations found at the tested WCAG level |
fail | One or more violations found |
partial | No violations but some items could not be fully evaluated |
error | Navigation failed because the site was unreachable or timed out |
wcagLevel reflects the highest WCAG level at which the page fully passes. A page with no AA violations but some AAA violations returns AA.
Browser Report - wcag.php
Access this as an authenticated WMD administrator through the Custom Built-in Tools page, or directly at https://yourserver/tools/wcag.php.
Features
- Summary stat cards showing total, scanned, pass, fail, partial, error, and not scanned counts
- Scope selector for category-only or all-domain views
- Filterable table by domain name, status, or WCAG level
- Sortable columns
- Reset button per row to clear
wcag_scanned_atso the domain is re-scanned on the next gather run - Row click opens a popup with the full violation report loaded from disk
- Violations tab showing axe violations with impact, WCAG tags, description, and affected HTML
- Incomplete tab showing items axe could not fully evaluate
- Export CSV for summary data
- Export JSON for full data including violation details
- Session expiry handling with a clear prompt to log in again if the WMD session ends
If the WCAG columns have not been created yet, the report page should not be used until setup is completed.
Scheduled Scanning
The lock file prevents re-entry if a previous run is still in progress, so overlapping scheduled runs are not normally a concern regardless of platform.
Linux / Debian / Ubuntu
The wcag-setup.sh script can automatically add a cron job depending on its configuration. A common pattern is to scan every 30 minutes with a batch size of 3.
To add or edit the cron job manually:
crontab -e
Add a line in this form:
*/30 * * * * php /path/to/tools/wcag/wcag-gather.php --batch=3 >> /path/to/wcag-cron.log 2>&1
Windows
On Windows, Task Scheduler is used instead of cron. A batch file can call wcag-gather.php, and a VBScript wrapper can be used to launch that batch file silently if needed.
See learn.domainpunch.com/wmdsed/install/wintask/ for the general Windows scheduled-task pattern used by WMD SED.
Security Notes
wcag-gather.phpis CLI only and exits immediately if accessed through a browserwcag.phprequires a valid WMD administrator session- The WCAG output folder is intended to remain outside the public web root
axe-scan.jsruns headless Chromium with--no-sandbox, so ensure the OS user running PHP has appropriate permissions