Accessibility
The Accessibility screen shows what real visits met: whether a visit was made by keyboard, at what browser zoom and with which display preferences; what got in the way (focus that could not leave a dialog, a card no keyboard could reach, a page that scrolled sideways at 200%, an animation that ran for someone who had asked it not to); and what happened to your goal afterwards.
It cannot see screen readers or any other assistive technology. Browsers expose nothing, and guessing from behaviour would be a way of detecting disability, which Lynq does not do. The keyboard group includes people who use screen readers, switch access and voice control alongside people who prefer the keyboard, and no number on the screen separates them.
An automated checker reads the markup. This reads the visits. Each observation relates to a WCAG 2.2 success criterion, and none of it is a conformance judgement or a score; it is evidence for whoever does the manual work.
Turning it on
Add data-a11y to the script tag. Nothing is collected without it, and Settings shows whether signals are arriving.
<script defer src="https://lynq.byharsh.com/js/lynq.js" data-site="your-site.com" data-vitals data-a11y></script>The attribute loads a small extra chunk after the page is interactive, and the Accessibility screen appears in the navigation once the first signal arrives. Collecting these signals is processing you are responsible for; read your obligations first.
The screen
Three sections, in this order.
How visits were made. Each group (keyboard, keyboard with no pointer seen, browser zoom 200%+, reduced motion, forced colors) as two figures: the group’s conversion to your KPI goal, “k of n” and its 95% interval beneath, beside the same rate for the comparison. The measured count is in the heading. Details are under How visits were made.
What gets in the way. One table of observations ranked by the sessions affected: what a visit observed, the page, the element, and “12 of 14” (the sessions that met it, of those on the page that could have). A row opens its own page with the criterion, the evidence, when it was last seen, what it cost, and a link that filters every screen to that page. The rules are on How each observation is measured.
What it cost. For each keyboard barrier, sessions that met it and then completed your goal, beside sessions on the same page that did not meet it. See What it cost.
Nothing is shown under 20 sessions or 5 completions. The rules are under Thresholds.
What gets in the way
Sessions reads “12 of 14”: the sessions that met the observation, of those on that page that could have. Who could have depends on the observation: keyboard sessions for the keyboard observations, sessions with reduced motion requested for motion, sessions that used a pointer for small targets and unreachable clickables, and every measured session for the rest.
Element is the site’s own label for it: tag and role, then aria-label, the control’s text, its <label>, an alt inside it, or its title. It is a label, not the accessible name. Anything that is not a control (a card, a row, an image, an editable region) is shown as tag, role and a short hash of its text, so the page’s words never leave it; to find it, Tab through the page. A text field’s value is never used.
Criteria are WCAG 2.2 (W3C Recommendation, 5 October 2023). What each observation counts, and what it cannot see, is on How each observation is measured.
What it cost
For each keyboard barrier on a page (a trap, a loop, Tab not moving, focus dropped, Enter and Space doing nothing, focus leaving a modal or landing in a hidden region, focus that cannot be seen or is covered, navigation leaving focus on the page), the table shows keyboard sessions that met it and completed your KPI goal afterwards, beside keyboard sessions on the same page that did not meet it and completed after reaching the page: “5 of 25 (20%, 9–39)” against “14 of 35 (40%, 26–56)”, each with its 95% interval.
Meeting a barrier takes a Tab sequence on that page, which people further into a task do more, so a gap is a place to look and not a cause. Small targets and unreachable clickables are not here: a click is intent, not obstruction. Page-wide observations (overflow, motion, a locked viewport) are met by everyone on the page and have no other side.
The table needs a KPI goal. A rate needs 5 completions on each side; rows under the floor are counted under the table, not drawn.
How visits were made
Measured is the sessions in which the tag with data-a11y ran, of all sessions in the range. Each group’s conversion is shown beside its comparison, with the group’s sessions and share under its name. The tool answers with the same numbers and adds bounce and pages per session.
| Group | Counted when | Limits |
|---|---|---|
| Navigated by keyboard | Three or more Tab, Shift+Tab or arrow-key moves on one page, each landing on a different element that is not a text field. | Some screen-reader users press Tab and are counted; most navigate by headings, arrow keys or touch and are not. Switch access is counted; voice control clicks and is not. Safari and Firefox on macOS reach links and buttons with Tab only when the system’s keyboard-navigation setting is on, so macOS visits tabbing between fields are undercounted. |
| Keyboard, no pointer seen | Navigated by keyboard, with no mouse, touch or pen press on a control in the session. | Shown apart from the keyboard group only when the two differ by 20 sessions and 5 completions. |
| Browser zoom 200%+ (estimated) | Estimated from the ratio of window width to viewport width, matched to a browser zoom preset. Desktop only, not Firefox, not inside a frame. | Text-only zoom and operating-system scaling are not seen. Unknown stays unknown and is never counted as 100%. 110–149% and 150–199% are filter bands, not rows. |
| Browser zoom 400%+ (estimated) | The same estimate at 400% and up, the width 1.4.10 is judged at. | Included in the 200%+ group; shown apart from it only when the two differ by 20 sessions and 5 completions. |
| Reduced motion requested | The operating system’s reduced-motion setting, as the browser reports it. | Windows Remote Desktop and “adjust for best performance” also set it, so corporate traffic inflates the share. |
| Forced colors (contrast themes) | Windows contrast themes, or Firefox’s colour override, as the browser reports forced colors. | Compared within Windows desktop sessions, where the setting lives. |
Shares are of measured sessions, except zoom (of desktop sessions whose zoom is known) and forced colors (of Windows desktop sessions). Sessions are counted, not people: the same person on two days is two sessions.
The comparison. For the keyboard groups it is sessions that operated the site by pointer and went past one page or fired an event, so both sides used the site; for reduced motion it is measured sessions without the setting. Both are weighted to the group’s device mix: the comparison’s rate is computed per device and combined by the group’s own device shares, so “keyboard converts less” cannot be “desktop converts less” in disguise. A device with no comparison sessions is left out. Zoom and forced colors are compared within their eligible population, unweighted.
Intervals are Wilson score intervals at 95%. Two intervals that overlap are not a finding; two that do not are a place to look. Lynq claims significance only on the Experiments screen.
A keyboard share of a few percent is a share of visits, not of the people the site is for. It is never shown alone: beside it are what those visits met and what it cost.
Filters and ranges
The screen adds four dimensions to the filter bar: Keyboard navigation (keyboard and pointer, keyboard with no pointer seen, none seen), Browser zoom (100%, 110–149%, 150–199%, 200–399%, 400% and up), Reduced motion (requested, not requested) and Forced colors (on, off). They work on this screen only; every other screen refuses them and the chip says so.
So that two views can never be subtracted down to one visit, the screen accepts at most one path filter and one device filter beside those four, each an exact value, and only the ranges yesterday, last 7 days, last 30 days, this week and this month: no today, no last 24 hours, no custom dates, no comparison period. Every range ends at your site’s local midnight, so the screen changes once a day. A filter or range the screen cannot take is dropped, and the chip says what it ran with instead.
Thresholds
Nothing is shown under 20 sessions or 5 completions.
- A group under 20 sessions shows “fewer than 20” and no rate; so does a group whose comparison is under 20, since everyone’s rate minus the group’s would give the rest away.
- A rate is withheld when its completions, or the comparison’s, are under 5.
- A nested group (keyboard with no pointer seen inside keyboard; 400%+ inside 200%+) is shown apart from its parent only when the two differ by 20 sessions and 5 completions.
- With a filter on, a group is also withheld when it has under 20 sessions or under 5 completions outside the filter.
- An observation row under 20 sessions shows neither sessions nor pageviews, and its “last seen” becomes the day rather than the moment.
The thresholds are applied before anything leaves the server; withheld numbers never reach the page, the CSV export or the tool. Twenty sits above the 5–11 used in census tables and below the 100 used for public releases.
What is stored, and for how long
Each observation is a row on the session and page it happened in: its name, the element’s label, and its detail (a count, a key, a width, a zoom preset). The visit’s context (keyboard use, the zoom estimate, the two preferences) is stored per session with the session’s device, operating system and browser, and nothing else: no visitor number, no identify id, no path through the site. These rows are kept for 35 days, whatever the site’s retention for everything else.
No typed text, no form values, no selectors, no content of anything that is not a control. What does leave the page is link and button text (in an app, often “Reply to Jane”), labelled-by text and dialog headings, and a short hash of other text, which a dictionary could reverse for common short strings.
There is no per-session surface. Journeys, the session list, the session drawer and Realtime do not show these flags and refuse the four dimensions. Export and the tool return the same aggregates under the same thresholds.
Your obligations
You are the controller of what your site collects; Lynq processes it for your reports and nothing else. Preference and input data can be used to infer a disability, and data liable to reveal a special category can be Article 9 data under the GDPR whatever the intent (the Court of Justice in Meta Platforms v Bundeskartellamt, C-252/21, and OT v Vyriausioji tarnybinės etikos komisija, C-184/20; the ICO treats inferring health status as special-category processing whether or not the inference is right). The thresholds, the 35-day retention and the absence of a per-visit surface are the mitigations, and they are yours to assess. They do not settle the question: collecting these signals needs a lawful basis, an Article 9(2) consideration, and possibly a data protection impact assessment.
Reading the browser’s motion and colour preferences, the viewport and the page’s animation state is access to information on the visitor’s device in the sense of ePrivacy Article 5(3), as the EDPB’s 2023 guidelines read it. Whether the audience-measurement exemption covers operating-system preferences is an open question, and Lynq does not claim data-a11y is consent-free.
Not measured
Not yet.
- A focus ring removed by CSS with nothing in its place (2.4.7). Built, held back until its precision is measured. A focused element that cannot be seen at all is reported.
- Focus partly hidden under a sticky bar (2.4.11 reports the fully hidden case only), and 2.4.12.
- Context changes on focus (3.2.1), and a Tab that moved focus somewhere unexpected in the order (2.4.3 beyond the cases measured).
- Dragging without a single-pointer alternative (2.5.7), redundant entry (3.3.7) and cognitive-function tests in authentication (3.3.8).
- Motion inside frames and closed shadow roots; script-driven animation, canvas, video and GIFs (2.2.2).
Cannot be measured from a visit.
- Screen readers and other assistive technology. Some screen-reader users press Tab and are in the keyboard group; most navigate by headings, arrow keys or touch and are not; voice control clicks and is in the pointer group.
- Whether a trap’s way out was explained (2.1.2 allows it), and whether moving content has a pause control (2.2.2).
- Whether a small target has an equivalent elsewhere on the page (the 2.5.8 exception), or a hit area enlarged by a wrapper.
- Text-only zoom, the operating system’s font size and its magnifier (1.4.4): the browser exposes none of them.
- Text spacing (1.4.12), content on hover (1.4.13), timing beyond a meta refresh (2.2.1), error messages (3.3.1): what a page says, not what a visit did.
- Everything else in WCAG 2.2 (structure, headings, alternative text, language, forms, colour contrast, accessible names): what audits and automated checks are for.
- People. Sessions are counted, and the same person on two days is two sessions.
- Why. The groups differ in more than the setting named, so a gap between them is a place to look and not a cause.
Where this sits beside the law
No regime asks for field data; they ask for WCAG conformance, judged by audit. The European Accessibility Act (Directive (EU) 2019/882) has applied to consumer-facing services since 28 June 2025. In the United States, the Title II web rule’s compliance dates were extended on 20 April 2026 to 26 April 2027 for state and local governments serving 50,000 people or more, and 26 April 2028 for smaller ones; in the private sector the driver is litigation under Title III. The scanners and the audit you run answer those. This screen answers a different question, where real visitors met a barrier and what it cost, and nothing on it says a site complies.
The demo
Aivia, the demo site, has accessibility defects put there on purpose, so its screen shows real findings. The defects, page by page:
| Page | Defect | Observation |
|---|---|---|
/ | The hero animation loops with no reduced-motion guard | Animation ran with reduced motion on; Animation ran on its own for over five seconds |
/pricing | The plan cards are divs with click handlers and no keyboard route | Clickable, no keyboard route found |
/pricing | The FAQ toggles are div[role=button] that answer clicks only | Focusable, Enter and Space did nothing |
/signup | The “Create your account” dialog swallows Escape and loops Tab | Tab stayed inside one container |
/login | Closing the login help sheet hides the Close button that had focus | Focus lost after a key press (hidden) |
/features | The in-app route leaves focus on the page | In-page navigation left focus on the page |
/docs/* | The pager is a row of 18 px icon buttons | Target under 24 px |
/docs/* | The sticky header covers the first heading link after a Tab | Focus fully hidden under a fixed bar |
/docs/api | The API reference table overflows at 200% zoom | Horizontal overflow; Scrolled sideways |
The keyboard share on the demo is under 5%, and some rows are withheld under 20 sessions; both are what a real site shows.